自定义view的开发精要

项目中的实践:

  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-------------

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容