カスタムビューの継承ビュー(円形進捗図、プレーヤーバー)


新しいコントロールを実現するためにViewを書き換える
AndroidでViewを書き換えるのはAndroidの難点ですが、多くの特効はカスタムViewに基づいて実現されているので、2つの例でカスタムViewを学んでみましょう.
まず実例図を見てみましょう.[
えんけいず
図を見ることで、図全体を3つの部分、内部の円環、外部の弧、文字に分けることができます.
  • まず、定義したフィールド
  • を見てみましょう.
      /** *      */
        private int mCircleXY;
    
        /** *       */
        private int mRadius;
    
        /** *       */
        private int width;
        /** *       */
        private String mText;
    
        /** *       */
        private Paint mArcPaint;
    
        /** *       */
        private Paint mTextPaint;
    
        /** *        */
        private Paint mCirclePaint;
    
    
        /** *         */
        private Rect mArcRect;
    
    
        /** *      */
        private String mCenterText = "Alex_Mahao";
    
        /** *        */
        private Rect mTextBound = new Rect();
    
        /** *         */
        private int mSweepAngle;
    
        /** *           */
        private int mEndAngle;
    
  • onMeasure()メソッドを書き換えます.
  •  @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            width = Math.min(getMeasuredWidth(),getMeasuredHeight());
    
            setMeasuredDimension(width,width);
    
            mCircleXY = width/2;
    
            mRadius = width/2/2;
    
            initPaint();
    
            //       
            mArcRect = new Rect(width/2/2/2/2,width/2/2/2/2,width-width/2/2/2/2,width-width/2/2/2/2);
            //       
            mTextPaint.getTextBounds(mCenterText, 0, mCenterText.length(), mTextBound);
    
            //       
            setProgress(270);
        }

    onMeasure()メソッドでは、まず、このViewが正方形であるため、幅と高さを比較して最小値を取ります.6行目では、測定後の幅の高さを取得し、最小値を取り、コントロールの幅の高さを再設定します.
    次に、コントロールの中心座標を取得します.内部円の半径をコントロール幅の4分の1にします.
  • 初期化ブラシ
  •   private void initPaint() {
            mArcPaint = new Paint();
            mArcPaint.setColor(Color.BLUE);
            mArcPaint.setAntiAlias(true);
            mArcPaint.setStyle(Paint.Style.STROKE);
            mArcPaint.setStrokeWidth(width/2/2/2);
    
    
            mCirclePaint = new Paint();
            mCirclePaint.setColor(Color.RED);
            mCirclePaint.setStyle(Paint.Style.FILL);
            mCirclePaint.setAntiAlias(true);
    
            mTextPaint = new Paint();
            mTextPaint.setColor(Color.WHITE);
            mTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
            mTextPaint.setAntiAlias(true);
    
        }

    この方法ではmArcPaint,mCirclePaint,mTextPaintを初期化し,mArcPaintの設定では円形円弧を描くためにPaintのブラシ幅を設定し,ブラシ幅を設定した後,我々のonMeasure()メソッドでは円弧矩形の範囲を初期化し,その円弧の幅の半分は矩形を内接するので,円弧矩形の半分を減算しなければならない.及び円弧の幅がwidth/2/2である場合、対応する内接矩形は(width/2/2/2、width/2/2/2、width-width/2/2/2、width-width/2/2/2、width-width/2/2)である.
  • onDraw()メソッドを書き換え、対応するグラフィックを描画します.
  •  @Override
        protected void onDraw(Canvas canvas) {
    
            canvas.drawCircle(mCircleXY,mCircleXY,mRadius,mCirclePaint);
    
            canvas.drawText(mCenterText,width/2-mTextBound.width()/2,getHeight()/2+mTextBound.height()/2,mTextPaint);
    
            //          ,                
            canvas.drawArc(new RectF(mArcRect),-90,mSweepAngle,false,mArcPaint);
    
            if(mEndAngle>mSweepAngle){
                mSweepAngle++;
                postInvalidateDelayed(5);
            }
    
    
        }

    canvasでdrawCircle()メソッドは内部円を描き,パラメータはそれぞれ円心x座標,円心y座標,半径,ブラシである.
    canvasでdrawText()は、文字を中心に描くため、onMeasure()メソッドでPaintのgetTextBounds()で文字が占める空間の大きさを含むRectオブジェクトを測定し、コントロール幅の半分-Rectオブジェクトの半分をコントロールすることで、対応する中心に設定します.
    canvasでdrawArc()メソッドは弧を描き,パラメータはそれぞれ,内接矩形,開始度数(0はいずれも右側,-90度は上方),弧のオフセット度数,円心を描くかどうか,ブラシを描く.
    外部アークを徐々に増加させたくない場合は、mSweepAngleを直接固定値に設定すればよい.ゆっくりスクロールしたい場合は、バッファ効果があります.次の方法を追加する必要があります.
     public void setProgress(int endAngle){
            mEndAngle = endAngle;
            mSweepAngle = 0;
            postInvalidate();
        }

    このメソッドは、activityで呼び出すことができます.私は簡単にするためにonMeasure()メソッドで呼び出しました.このメソッドでは、私たちの最終的なアーク値を0に設定し、コントロール(onDraw()メソッドを呼び出す)をリフレッシュする3つのことをしました.では、onDraw()メソッドでは、if(mEndAngle>mSweepAngle)に進み、現在の度数を増やしながら、5 ms後に試行された遅延タスクをリフレッシュします.
  • OK、できました.私たちは自分のニーズに合わせて、内部の文字、色などをカスタマイズすることができます.

  • バーグラフ
    慣例に従って、フィールドを先に入力します.
           /** *       */
        private int mWidth;
    
        /** *       */
        private int mRectHeight;
    
        /** *       */
        private int mRectWidth;
    
        /** *       */
        private int mRectCount = 5;
        /** *        */
        private LinearGradient mLinearGradient;
    
        /** *    */
        private Paint mPaint;
        /** *         */
        private double mRandom;
  • 構造方法でブラシ
  • を初期化する.
            /** *       */
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setAntiAlias(true);
  • onSizeChange()メソッドでは、いくつかの必須属性
  • を取得する.
            //     
            mWidth = getWidth();
    
            //       ,      
            mRectHeight = getHeight();
    
            //          
            mRectWidth = (int) (mWidth*0.6/mRectCount);
    
            //   ,
            mLinearGradient = new LinearGradient(0,0,mRectWidth,mRectHeight, Color.YELLOW,Color.BLUE, Shader.TileMode.CLAMP);
    
            //     
            mPaint.setShader(mLinearGradient);
  • onDraw()に棒グラフを描きます.
  •    for(int i=0;i<mRectCount;i++){
                //     ,       
                mRandom = Math.random();
                float currentHeight = (float) (mRectHeight*mRandom);
    
                //     
                canvas.drawRect((float)(mWidth*0.4/2+mRectWidth*i),
                            currentHeight,
                        (float)( mWidth*0.4/2+mRectWidth*(i+1)),
                            mRectHeight,
                            mPaint
                        );
            }
            //300ms    ,     
            postInvalidateDelayed(300);

    注釈はもうはっきりしているので,これ以上説明しない.
    この2つのコントロールの知識点をまとめます
    まとめ1.通過するdrawArc()円弧を描き、ブラシの幅を設定すると円弧の外接矩形が制限され、外接は円弧の最外端の画素ではなくブラシの幅の半分になるので、この場合外接矩形を計算する際には、ブラシの幅を考慮する必要がある.2.文字を中央に配置することは、常にカスタムViewで頭が痛いことです.私たちはPaintのgetTextBounds(String text,int start,int end,Rect bounds)メソッドを通じて、文字が占める空間の大きさを取得し、このコントロール値の間に入力boundsパラメータに格納されます.この場合、canvas.drawText(String text,float x,float y,Paint paint);ここにはもう一つのピットがあり、xは左上xの座標を表し、yは右下yの座標を表す.3.TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()),sp->dpの変換
    カスタムViewのソースコードがgithubにアップロードされました.ソースコードが必要な場合は移動してくださいhttps://github.com/AlexSmille/CustomView