自定义view的开发精要

作者: ahking17 | 来源:发表于2016-10-27 15:03 被阅读25次

    项目中的实践:

    1. 红点提示ImageView的实现, ImageViewWithDot
    2. 正方形ImageView的实现, SquareImageView

    这篇文章讲的还是很清晰的
    一个规范的自定义View——Android开发艺术探索笔记
    http://blog.csdn.net/l664675249/article/details/50787973

    自定义View的核心是: 重写View的onDraw和onMeasure方法.
    重写onDraw()的目的

    是实现真正的在传进来的canvas对象上绘制图像.

    ImageViewWithDot.java
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (showRedPoint) {
            canvas.drawCircle(getWidth() / 1.3f, getHeight() / 3.4f, mCircleRadius, mPaint);
        }
    }
    

    注意, 如果是直接继承自View的话, 要在重写的onDraw()中去处理有padding的情况.

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        final int paddingLeft = getPaddingLeft();
        final int paddingRight = getPaddingRight();
        final int paddingTop = getPaddingTop();
        final int paddingBottom = getPaddingBottom();
        int width = getWidth() - paddingLeft - paddingRight;
        int height = getHeight() - paddingTop - paddingBottom;
        int radius = Math.min(width, height) / 2;
        canvas.drawCircle(paddingLeft + width / 2, paddingTop + height / 2,
            radius, mPaint);
    }
    
    重写onMeasure()的目的

    直接继承View或ViewGroup的需要自己通过重写onMeasure()处理wrap_content,否则使用wrap_content就相当于使用match_partent.
    也就是说像红点提示ImageViewWithDot直接继承自ImageView,也就没必要自己重写onMeasure()了.
    对onMeasure()的重写代码基本就是模板化, 不用刻意去记, 只需要记住重写的目的就可以了, 用的时候直接copy过来稍加修改就行.

    @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);
        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);
        }
    }
    

    通过重写onMeasure()也可以达到一些特殊的目的,
    例如, 不管使用什么尺寸的bitmap设置给ImageView, 让ImageView的显示保持为正方形.

    public class SquareImageView extends ImageView {
    
        public SquareImageView(Context context) {
            super(context);
        }
    
        public SquareImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //使用宽度值去设置高度值
            super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        }
    }
    

    -----DONE-------------

    相关文章

      网友评论

        本文标题:自定义view的开发精要

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