美文网首页
Android自定义控件二(View的测量和绘制)

Android自定义控件二(View的测量和绘制)

作者: Olivine_Vip | 来源:发表于2017-05-07 11:49 被阅读0次

    现实生活中,如果我们要去画一个图形,就必须知道它的位置和大小。
    Android系统在绘制View前,也必须对View进行测量,这个过程在onMeasure()方法中进行。

    MeaSureSpec
    Android 提供的测量View的一个类,是一个32位int值,其中高2位为测量模式低30位为测量大小(size)。

    测量模式可分为3类:
    • EXACTLY
      精确值模式:将layout_width或layout_height属性指定为具体数值(30dp)或者match_parent
    • AT_MOST
      最大值模式:将layout_width或layout_height指定为wrap_content。
    • UNSPECIFIED
      View想多大就多大。通常在自定义View才会使用。
    注意:

    View的默认哦那Measure()只支持EXACTLY,
    如果让自定的view支持wrap_content,必须重写onMeasure()来指定wrap_content大小。

    简单示例:
    public class MeasuredView extends View {
        public MeasuredView(Context context) {
            super(context);
        }
        
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // 调用父类的onMeasure()
            super.onMeasure(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
            // 或者直接调用父类的setMeasuredDimension(),因为父类的onMeasure()最终调用了setMeasuredDimension()
            // setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
        }
        
        /**
         * 测量View的width
         * @param measureSpec MeasureSpec对象
         * @return View的width
         */
        private int measureWidth(int measureSpec) {
            int result = 0;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            
            if (specMode == MeasureSpec.EXACTLY) {
                result = specSize;
            } else {
                result = 200;
                if (specMode == MeasureSpec.AT_MOST) {
                    result = Math.min(result, specSize);
                }
            }
            return result;
        }
        
        /**
         * 测量View的height
         * @param measureSpec MeasureSpec对象
         * @return View的height
         */
        private int measureHeight(int measureSpec) {
            int result = 0;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            
            if (specMode == MeasureSpec.EXACTLY) {
                result = specSize;
            } else {
                result = 200;
                if (specMode == MeasureSpec.AT_MOST) {
                    result = Math.min(result, specSize);
                }
            }
            return result;
        }
    }
    

    View的绘制

    2D绘图必备利器——Canvas
    获取Canvas对象的方式:
    a. 由方法中的参数传入,例如,View的onDraw()中有一个参数就是Canvas对象
    b. 通过构造方法构造,即:Canvas canvas = new Canvas(bitmap),在Canvas的构造方法传入一个Bitmap对象,即可获取一个Canvas对象。通过传入Bitmap对象构造Canvas对象的过程称为“画布的装载”,传入的Bitmap对象承载了多有绘制在Canvas上的像素信息,调用Canvas.drawXXX方法(如:Canvas.drawBitmap(bitmap, 0, 0, null))都将发生在该Bitmap对象上。

    利用Canvas绘图
    a. 通过Canvas.drwaXXX进行绘制操作将直接作用于Bitmap对象,当再次刷新View的时候,我们将会被绘制的Bitmap对象发生了改变;
    b. 利用Canvas和Paint进行绘图;
    c. 不管多么复杂、精美的空间,都可以被拆分为一个个小的图形单元,我们只要找到这些图形单元,就可以将控件绘制出来。

    参考:Android群英传
    Android视图控件架构分析之View、ViewGroup

    相关文章

      网友评论

          本文标题:Android自定义控件二(View的测量和绘制)

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