美文网首页
自定义控件从入门到精通(三)自定义view

自定义控件从入门到精通(三)自定义view

作者: ambitioner | 来源:发表于2016-11-07 16:51 被阅读39次

    1.普通自定义view

    今天首先要做的是一个简单的自定义view,实现环形饼图,并有百分比数字。对于自定义view来说,只需要重写onMeasure和onDraw方法。

    初始化

    省略掉了变量声明,直接上初始化

    public NumProgress(Context context, AttributeSet attrs) 
    {    
            super(context, attrs);    
            mPaint = new Paint();    
            mPaint.setColor(Color.RED);    
            mPaint.setStyle(Paint.Style.STROKE);    
            mPaint.setStrokeWidth(50);    
            mtxtPaint = new Paint();    
            mtxtPaint.setColor(Color.BLACK);    
            mtxtPaint.setTextSize(50);    
            //圆弧的矩形轮廓   
           mRect = new RectF();
    }
    

    onMeasure

    onMeasure方法的实质是给自定义的view一个wrap_content属性下的默认大小。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    {    
           super.onMeasure(widthMeasureSpec, heightMeasureSpec);    
           int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);    
           int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);    
           int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);    
           int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);    
           mWidth = widthSpecSize;    
           mHeight = heightSpecSize;    
           if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode ==         MeasureSpec.AT_MOST) 
          {
                  setMeasuredDimension(200, 200);    
          } 
          else if (widthSpecMode == MeasureSpec.AT_MOST) 
          {        
                  setMeasuredDimension(200, heightSpecSize);    
          } 
          else if (heightSpecMode == MeasureSpec.AT_MOST) 
          {        
                  setMeasuredDimension(widthSpecSize, 200);    
          }
    }
    

    代码中的200就是给出的默认值。换句话说,如果在使用你的自定义控件的过程中,不打算用wrap_content属性,是可以不重写onMeasure方法的。

    onDraw

    @Override
    protected void onDraw(Canvas canvas) 
    {    
            //画圆弧
           mRect.set(50, 50, mWidth-50, mHeight-50);    
    
           //swipAngle是圆弧的弧度
           canvas.drawArc(mRect, 0, swipAngle, false, mPaint);
    
           //计算字体的高度,并且绘制文字
          Paint.FontMetrics fm = mtxtPaint.getFontMetrics();
          float y = (mHeight -(fm.bottom +fm.top))/2;
          float x = (mWidth-mtxtPaint.measureText("10%"))/2;
          canvas.drawText("10%",x,y,mtxtPaint);
    }
    

    代码中的弧度和文字目前是写死的,完全可以作为自定义属性传进来,然后赋值,这里是为了简单所以这么写。代码打出来后,发现这个demo确实有些简单。不过还是那句话,先熟悉流程,基本的思想。然后一步一步走向精通。

    2.带动画效果的自定义view

    以前认为带动画的自定义view好牛的样子,其实不然。简单的思想就是,还是如上部分那样绘制自定义view,不过某些绘制的数值变量可以设为成员变量,并且利用ValueAnimator改变其值,然后调用invalidate()重绘即可。

    onMeasure和onDraw

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);   
             int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);    
             int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);    
             int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);   
             int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);    
             mWidth = widthSpecSize;   
             mHeight = heightSpecSize;    
              if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) 
            {        
                      setMeasuredDimension(200, 200);    
            } 
            else if (widthSpecMode == MeasureSpec.AT_MOST) 
            {       
                     setMeasuredDimension(200, heightSpecSize);   
           } else if (heightSpecMode == MeasureSpec.AT_MOST) 
            {        
                      setMeasuredDimension(widthSpecSize, 200);    
            }
    }
    
    @Override
          protected void onDraw(Canvas canvas) 
          {    
                mRect.set(50, 50, mWidth-50, mHeight-50);    
                canvas.drawArc(mRect, 0, swipAngle, false, mPaint);    
                //计算字体的高度,并且绘制文字    
                Paint.FontMetrics fm = mtxtPaint.getFontMetrics();    
                float y = (mHeight -(fm.bottom +fm.top))/2;    
                float x = (mWidth-mtxtPaint.measureText("10%"))/2; 
                canvas.drawText(String.valueOf((int)animationValue*100))+"%",x,y,mtxtPaint);}
    

    可以看到onMeasure和第一部分一样,onDraw只是部分不同。

    新增动画开始的方法

    public void start()
     {    
           ValueAnimator animator = ValueAnimator.ofFloat(0f, 1.0f);      
           animator.setDuration(5000);    
           animator.setInterpolator(new LinearInterpolator());    
           animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() 
            {        
                  @Override       
                  public void onAnimationUpdate(ValueAnimator animation) 
                 {           
                    swipAngle = (int) Math.round((Float) animation.getAnimatedValue() * 360);     
                    animationValue = (Float) animation.getAnimatedValue();            
                    invalidate();           
                  }    
            });    
           animator.start();
      }
    

    该方法是自定义view动画的核心代码,整个方法是供使用view的页面调用的,用来开始动画效果。animation.getAnimatedValue()的值会从0到1变换,从而可以计算出对应的swipAngle值,然后 invalidate()就可以算出该次绘制的值。不断的重绘,动画效果也就出来了。

    相关文章

      网友评论

          本文标题:自定义控件从入门到精通(三)自定义view

          本文链接:https://www.haomeiwen.com/subject/irxouttx.html