Androidはインジケータ付きのプログレスバーを実現します。


背景
UIが私達に設計した効果を見た時、私達の習慣的な考え方はgoogleが私達のためにコントロールを提供してくれるかどうか、あるいはネットで適当な車輪を見つけて持ってきて直接使うことです。しかし、あいにくこのような車輪がない場合があります。また、UIや製品はこのような効果が必要な時は、自分で製作するしかないです。今日は、簡単な指示器付きのプログレスバーを実現するために、Viewの定義を理解してください。
効果の実現図
効果図がないというのは、何をやっているかということになるので、慣例によっては、

仕事を始める
私達が自分で絵を描くと決めた時、まず需要、効果を観察、分析、分解する必要があります。いわゆる大きなことが小さくなり、小さなことがなくなるということです。
  • 観察:効果図には、プログレスバー、三角矢印を有する円角インジケータ、プログレス値、および進捗アニメーション
  • が含まれている。
  • 分析:進捗バー全体をインジケータ、プログレスバー、進捗値、アニメーションの4つの部分
  • に分けることができます。
  • 分解:したがって、上記の部分の構成部分を順次個別に描き、最後の全体的な関連付けを行うことができます。上図の効果を実現します。
  • カスタムViewの流れ(上記の部分に従って)
    描画の流れには三つの部分が含まれています。カスタマイズ属性、測定メディア、draw、layout。しかし、今日私たちが話しているのは進行状況のViewで、View Layoutではないので、layoutの部分は今日は話さないでください。
    ユーザー定義の属性とコードの取得
    属性
    説明
    ap:hpb_センター・Padding=「5 dp」
    インジケータとプログレスバーの間隔
    ap:hpb_プログレスBarBackground Color=「@カラー/color Primary」
    進捗バーの背景色
    ap:hpb_プログレスBarForeground Color=「@カラー/colorAccent」
    プログレスバー前の景色
    ap:hpb_プログレスBarHeight=「2 dp」
    インジケータbottomPadding
    ap:hpb_text BottomPadding="5 dp"
    インジケータとプログレスバーの間隔
    ap:hpb_text LeftPadding="5 dp"
    インジケータleftPadding
    ap:hpb_textRight Padding="5 dp"
    インジケータライトPadding
    ap:hpb_text TopPadding="5 dp"
    インジケータtopPadding
    ap:hpb_text Size="12 sp"
    インジケータの文字サイズ
    ap:hpb_text Color=「钻FFFF」
    インジケータのテキスト色
    ap:hpb_progress=「20」
    進捗値
    
        //       
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBar);
        mTextSize = ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textSize, Utils.sp2px(context, 12));
        mTextColor = ta.getColor(R.styleable.HorizontalProgressBar_hpb_textColor, Color.parseColor("#FFFFFF"));
        currentProgress = ta.getFloat(R.styleable.HorizontalProgressBar_hpb_progress, 0);
        mTextLeftPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textLeftPadding, Utils.sp2px(context, 5));
        mTextRightPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textRightPadding, Utils.sp2px(context, 5));
        mTextTopPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textTopPadding, Utils.sp2px(context, 5));
        mTextBottomPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_textBottomPadding, Utils.sp2px(context, 5));
        mCenterPadding = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_centerPadding, Utils.sp2px(context, 5));
        mProgressHeight = (int) ta.getDimension(R.styleable.HorizontalProgressBar_hpb_progressBarHeight, Utils.sp2px(context, 2));
        mBackgroundColor = ta.getColor(R.styleable.HorizontalProgressBar_hpb_progressBarBackgroundColor, Color.parseColor("#E8E8E8"));
        mForegroundColor = ta.getColor(R.styleable.HorizontalProgressBar_hpb_progressBarForegroundColor, Color.parseColor("#912CEE"));
        ta.recycle();
    
        //            
        mBackgroundPaint = new Paint();
        mBackgroundPaint.setColor(mBackgroundColor);
        mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND);
        mBackgroundPaint.setStrokeWidth(mProgressHeight);
        mBackgroundPaint.setAntiAlias(true);
    
        //   Path     
        mPathPaint = new Paint();
        mPathPaint.setColor(mForegroundColor);
        mPathPaint.setStrokeCap(Paint.Cap.ROUND);
        mPathPaint.setPathEffect(new CornerPathEffect(Utils.dp2px(getContext(), 2)));
        mPathPaint.setAntiAlias(true);
    
        //           
        mProgressPaint = new Paint();
        mProgressPaint.setColor(mForegroundColor);
        mProgressPaint.setStrokeWidth(mProgressHeight);
        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        mProgressPaint.setAntiAlias(true);
    
        //          
        mTextPaint = new Paint();
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setStyle(Paint.Style.FILL);
    
        //   Path   
        mPath = new Path();
    
    測定
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
    
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
    
        setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));
    }
    
    /**
     *     
     *
     * @param mode
     * @param width
     * @return
     */
    private int measureWidth(int mode, int width) {
        switch (mode) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
            case MeasureSpec.EXACTLY:
                mWidth = width;
                break;
        }
        return mWidth;
    }
    
    /**
     *     
     *
     * @param mode
     * @param height
     * @return
     */
    private int measureHeight(int mode, int height) {
        switch (mode) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:
            case MeasureSpec.EXACTLY:
                mHeight = height;
                break;
        }
        return mHeight;
    }
    
    //    
    private void measureText(String text) {
        Rect rect = new Rect();
        mTextPaint.getTextBounds(text, 0, text.length(), rect);
        mTextWidth = rect.width();
        mTextHeight = rect.height();
    }
    
    描画
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mIndicatorWidth = mTextLeftPadding + mTextWidth + mTextRightPadding;
        mIndicatorHeight = mTextTopPadding + mTextHeight + mTextBottomPadding;
    
        float backgroundProgressBarStartX = (float) (1.0 * mIndicatorWidth / 2);
        float backgroundProgressBarEndX = mWidth - mIndicatorWidth / 2;
    
        float foregroundProgress = (float) (1.0 * (mWidth - mIndicatorWidth) * currentProgress / 100);
    
        float foregroundProgressBarStartX = (float) (1.0 * mIndicatorWidth / 2);
        float foregroundProgressBarEndX = foregroundProgressBarStartX + foregroundProgress;
    
        Log.e(TAG, "backgroundProgressBarStartX----" + backgroundProgressBarStartX
                + "----backgroundProgressBarEndX----" + backgroundProgressBarEndX
                + "----foregroundProgress----" + foregroundProgress
                + "----foregroundProgressBarStartX----" + foregroundProgressBarStartX
                + "----foregroundProgressBarEndX----" + foregroundProgressBarEndX
        );
    
        float progressX = foregroundProgress;
        float progressY = (float) (mCenterPadding + mIndicatorHeight * 1.5);
    
    
        //    
        canvas.drawLine(backgroundProgressBarStartX, progressY, backgroundProgressBarEndX, progressY, mBackgroundPaint);
    
        //     
        canvas.drawLine(foregroundProgressBarStartX, progressY, foregroundProgressBarEndX, progressY, mProgressPaint);
    
        //   
        drawPath(canvas, progressX, 45);
    
        //  
        drawText(canvas, mTextProgress, progressX);
    }
    
    1.インジケータの描画
    Pathで描画します。矩形と下角を描きます。
    
    /**
     *      
     *
     * @param canvas
     * @param progressX
     */
    private void drawPath(Canvas canvas, float progressX, float rotateAngle) {
        mPath.reset();
    
        mPath.moveTo(progressX, 0); //1
        mPath.lineTo(progressX + mIndicatorWidth, 0); //2
        mPath.lineTo(progressX + mIndicatorWidth, mIndicatorHeight); //3
        mPath.lineTo((float) (progressX + mIndicatorWidth * 0.75), mIndicatorHeight); //4
        mPath.lineTo((float) (progressX + mIndicatorWidth * 0.5), (float) (mIndicatorHeight * 1.5)); //5
        mPath.lineTo((float) (progressX + mIndicatorWidth * 0.25), mIndicatorHeight); //6
        mPath.lineTo(progressX, mIndicatorHeight);//7
        mPath.close();
    
        canvas.drawPath(mPath, mPathPaint);
    }
    
    2.テキストの描画
    文字の描画は測定上の測定に関して言及されていますが、描画中にベースラインの取得に関しては以下のようになります。
    
    /**
     *                  
     *
     * @param p
     * @return    centerY   
     */
    public float getBaseline(Paint p) {
        Paint.FontMetrics fontMetrics = p.getFontMetrics();
        return (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
    }
    
    /**
     *     
     *
     * @param canvas
     * @param text
     * @param progressX
     */
    private void drawText(Canvas canvas, String text, float progressX) {
        float baseline = getBaseline(mTextPaint);
        float textY = mTextTopPadding + mTextHeight / 2 + baseline;
        canvas.drawText(text, progressX + mTextTopPadding, textY, mTextPaint);
    }
    
    締め括りをつける
    以上の完全なコードはすでにgithubにアップロードされました。githubアドレスは上に行ってみてもいいです。直接にダウンロードしたり、jcenterを通して導入したりもできます。jcenterの現状はメンテナンスが停止されていますので、後でmavenに移行します。
    以上はAndroidがインジケータ付きのプログレスバーを実現するための詳細です。Androidインジケータのプログレスバーに関する資料は他の関連記事に注目してください。