自定义View

自定义View 可以完全控制View的外观和view的行为,如需对预设的widget做修改可以继承于该widget,若需完全自定义可根据以下步骤:

  1. 创建自定义的控件类(MyView)继承于View或其子类(若只有该activity会使用到自定义的控件类,则可创建自定义控件类做为activity的内部类)
  2. 在attrs中定义在MyView中需要用到的属性,在res/layout/XXX.xml中MyView中添加需要的attrs属性
  3. 在MyView的构造器中通过TypeArray初始化通过xml定义的属性值
  4. override一些view的方法,onMeasure()(用于控制控件的位置宽高),onDraw()(用于控件的外观渲染),onKeyDown(),layout()(用于设置子view的位置,当自定义的view为ViewGroup时才会用到)等方法等,并设置自定义的监听事件
  5. 完成以上就可以在activity中应用自定义的view了
**
 * 继承于View只能绘制2D的UI,如需要绘制3D的UI则需要继承于SurfaceView
 */

public class MyView extends View {
    private boolean showText;//自定义的属性变量
    private final int defaultWidth = 100;
    private final int defaultHeight = 150;


    public MyView(Context context) {
        super(context);
        showText = false;
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyView, 0, 0);
        try {
            //通过typedArray把在xml中定义的属性值初始化给自定义的属性变量
            showText = typedArray.getBoolean(R.styleable.MyView_showText, false);
        } finally {
            typedArray.recycle();
        }
    }

    //onMeasure()方法,用于定义自定义控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureDimension(defaultWidth, widthMeasureSpec);
        int height = measureDimension(defaultHeight, heightMeasureSpec);
        //重写onMeasure()方法时必须调用setMeasuredDimension()方法,否则会抛出异常
        setMeasuredDimension(width, height);
    }

    private int measureDimension(int defaultSize, int measureSpec) {
        int result = defaultSize;
        int measureSpecMode = MeasureSpec.getMode(measureSpec);
        int measureSize = MeasureSpec.getSize(measureSpec);

        //1. layout给出了确定的值,比如:100dp
        //2. layout使用的是match_parent,但父控件的size已经可以确定了,比如设置的是具体的值或者match_parent
        if (measureSpecMode == MeasureSpec.EXACTLY) {
            result = measureSize;

            //1. layout使用的是wrap_content
            //2. layout使用的是match_parent,但父控件使用的是确定的值或者wrap_content
        } else if (measureSpecMode == MeasureSpec.AT_MOST) {
            result = Math.min(defaultSize, measureSize);
            //没有任何限制,多用于layout父控件,用于自由控制大小
        } else {
            result = defaultSize;
        }
        return result;

    }
    //绘制自定义View的外观
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制外观图形
    }
}
  • 关于view的getTop(),getLeft(),getRight(),getBotton(),getX(),getY(),getTranslationX(),getTranslationY()的关系和坐标系
    这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值