自定义View 总结

自定义View的步骤

 

1.自定义属性和声明与获取

1.分析需要的自定义属性

2.在res/values/attrs.xml定义声明

3.在layout xml文件中进行使用

4.在View的构造方法中进行获取

Tips:

自定义View构造函数的参数的作用

 

2.测量onMeasure

对于普通View,MeasureSpec由父容器的MeasureSpec和自身的LayoutParams共同决定对于顶级View,其MeasureSpec由窗口尺寸和其自身的LayoutParams来共同确定。在测量过程中,系统会将View的LayoutParams根据父容器所施加的规则转换成对应的Spec,然后再根据这个measureSpec来测量出View的宽/高。

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int width = 0;

        if ( widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            int needWidth = measureWidth() + getPaddingLeft() + getPaddingRight();
            if(widthMode == MeasureSpec.AT_MOST) {
                width = Math.min(needWidth,widthSize);
            } else {  //MeasureSpec.UNSPECIFIED
                width = needWidth;
            }
        }

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int height = 0;

        if ( heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            int needHeight = measureHeight() + getPaddingTop() + getPaddingBottom();
            if(heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(needHeight,widthSize);
            } else {
                height = needHeight;
            }
        }

        setMeasuredDimension(width, height);
    }

 

3.绘制onDraw

 

4.状态的存储与恢复

    private static final String INSTANCE = "instance";
    private static final String KEY_TEXT = "key_text";

    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putString(KEY_TEXT,mText);
        bundle.putParcelable(INSTANCE,super.onSaveInstanceState());
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if(state instanceof Bundle) {
            Bundle bundle = (Bundle)state;
            Parcelable parcelable = bundle.getParcelable(INSTANCE);
            super.onRestoreInstanceState(parcelable);
            mText = bundle.getString(KEY_TEXT);
            return;
        }
        super.onRestoreInstanceState(state);
    }

注意为自定义设置id。

自定义View分类

1.继承View重写onDraw方法

需要自己支持wrap_content(参考上文onMeasure()中处理)。

在onDraw()时,要考虑padding处理。

2.继承ViewGroup派生特殊的Layout

3.继承特定的View

4.继承特定的ViewGroup

 

posted @ 2019-04-23 20:18  kyun  阅读(185)  评论(0编辑  收藏  举报