• 自定义view(结合刻度盘学习)


     先上效果图

     

    一、View的测量(刻度盘的大小测量)

      在现实生活中,我们如果要去画一个图形,那么便要知道它的大小和位置。所以android绘图时需要我们对view进行测量。android为我们提供了onMeasure()方法来帮助我们去测量一个view,我们只需要重写onMeasur()方法,将我们测算长宽设置给setMeasuredDimension()。

         @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //根据模式测算长宽
            ...
    
            setMeasuredDimension(width,height);
        }

      我们首先测量我们最开始弧形的大小。即图中的样例。

       

      @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //根据模式测算长宽,这里获取的尺寸便是在xml文件中指定的尺寸
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = MeasureSpec.getSize(heightMeasureSpec);
            //以最小值为刻度区域正方形的长
            len = Math.min(width, height);
            //确定圆弧所在的矩形区域
            oval = new RectF(0, 0, len, len);
            radius = len/2;
            //设置测量高度和宽度
            setMeasuredDimension(len,len);
        }

    二、View的绘制(简单绘制出我们需要的弧形)

     测算完成后我们需要将他在画面上显示出来,android为我们提供了onDraw()方法,来绘制view。


    @Override
    protected void onDraw(Canvas canvas) { super.onDraw(canvas);
         //弧形的绘画查看api canvas.drawArc(oval,startAngle,sweepAngle,useCenter,paint); }

    不了解canvas的可以去看看canvas的绘制API

    现在在布局文件中设置后,就可以看见我们最开始的view了。

    三、完善我们的绘制,为仪表盘添加刻度。

        private void drawViewLine(Canvas canvas) {
            canvas.save();
            //移动canvas
            canvas.translate(radius,radius);
            //旋转canvas
            canvas.rotate(30);
            //普通刻度
            Paint linePatin=new Paint();
            //设置普通刻度画笔颜色
            linePatin.setColor(Color.WHITE);
            //线宽
            linePatin.setStrokeWidth(2);
            //设置画笔抗锯齿
            linePatin.setAntiAlias(true);
           /* //画一条刻度线
            canvas.drawLine(0,radius,0,radius-40,linePatin);*/
            //画101条刻度线
            //确定每次旋转的角度
            float rotateAngle=sweepAngle/99;
            //绘制需要有颜色部分的画笔
            Paint targetLinePatin=new Paint();
            targetLinePatin.setColor(Color.GREEN);
            targetLinePatin.setStrokeWidth(2);
            targetLinePatin.setAntiAlias(true);
            //记录已经绘制过的有色部分范围(角度float)
            float hasDraw=0;
            for(int i=0;i<100;i++){
                if (hasDraw <= targetAngle && targetAngle != 0) {
                    //计算已经绘制的比例
                    canvas.drawLine(0, radius, 0, radius - 40, targetLinePatin);
                } else {
                    canvas.drawLine(0,radius,0,radius-40,linePatin);
                }
                hasDraw += rotateAngle;
                canvas.rotate(rotateAngle);
            }
    
            //操作完成后恢复状态
            canvas.restore();
        }

     如图

     

    四、完善onMeasure()测量

      我们先看看在布局中的CircleView

      原先

    <com.example.tyr.circleviewtest.CircleView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

      如图

      

      改成Button

      <Button
               android:layout_width="match_parent"
               android:layout_height="match_parent"
             />

      现在,我么修改CircleView改为wrap_content,如图

      可以发现没有改变

      对比button的wrap_content可以发现如图,

       

      所以我们需要在onMeasure()方法中,对view的模式进行区别测量。

    五、MeasureSpec类

      android系统为我们提供了一个短小精悍的类MeasureSpec。它是一个32位的int值,高两位为测量模式,低30位为测量大小。

      测量模式分为三种:

      1、EXACTLY--系统的默认模式。

          精确模式,当我们将width和height指定100dp、200dp等精确值时或是match_parent属性时系统使用EXACTLY模式

      2、AT_MOST

        最大值模式,当height和width属性指定为wrap_content时,控件大小随子控件或内容的变化而变化,控件大小只要不超过父控件允许的最大尺寸即可。

      3、UNSPECIFIED

          不指定大小测量模式,view想多大就多大,通常在绘制自定义view时才会用。

       将onMeasure()方法进行修改,适应wrap_content

     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //根据模式测算长宽
            int width = measureSize(widthMeasureSpec);
            int height = measureSize(heightMeasureSpec);
            //以最小值为刻度区域正方形的长
            len = Math.min(width, height);
            //确定圆弧所在的矩形区域
            oval = new RectF(0, 0, len, len);
            radius = len/2;
            //设置测量高度和宽度
            setMeasuredDimension(len, len);
        }
    
        private int measureSize(int measureSpec){
         //差不多固定的格式
    int reslut = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec);    if (specMode==MeasureSpec.EXACTLY){ reslut = specSize; }else{ reslut = 200; if (specMode==MeasureSpec.AT_MOST){ reslut = Math.min(reslut,specSize); } } return reslut; }

        

    六、自定义属性

      我们在xml文件中使用的时候往往会使用一些属性类似width和height等等,那么我们便需要为我们的刻度盘添加新的属性。

    <resources> 
        <declare-styleable name="CircleView">
            <attr name="pointDisArc" format="dimension"></attr>
            <attr name="textSize" format="dimension"></attr>
        </declare-styleable>
    </resources>

         在构造方法中处理

     public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            parseAttr(context, attrs, defStyleAttr);
            initPaint();
        }
    
        private void parseAttr(Context context, AttributeSet attrs, int defStyleAttr) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CircleView,defStyleAttr,0);
            pDisArc = typedArray.getDimensionPixelSize(R.styleable.CircleView_pointDisArc,dp2px(context,20));
            textSize = typedArray.getDimensionPixelSize(R.styleable.CircleView_textSize,dp2px(context,20));
            typedArray.recycle();
        }
      <com.example.tyr.circleviewtest.CircleView
               android:id="@+id/cicleview"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               circle:textSize="20sp"
               circle:pointDisArc="20dp"
             />

     到目前为止view的自定义差不多完成了,也可以将刻度盘设计的更加精巧一些,下一节开始viewgroup的绘制,涉及到新的方法onLayout()。

      DEMO

  • 相关阅读:
    (2.3)备份与还原--事务的运行模式与处理机制
    (2.2)备份与还原--备份类型与恢复模式、备份介质
    (2.1)备份与还原--sql server文件的概念及操作
    (1.3.3)权限控制
    (1.3.2)登录验证(加密连接与登录验证)
    (1.3.1)连接安全(连接实例与网络协议及TDS端点)
    static class
    cnblog
    microsoft
    C# socket android
  • 原文地址:https://www.cnblogs.com/yrstudy/p/7445053.html
Copyright © 2020-2023  润新知