Android-自定义View

(学习Mooc的笔记)
转载请标明出处:http://blog.csdn.net/yuqing_1102/article/details/55095523

一、如何自定义控件

1.自定义属性的声明与获取
2.测量onMeasure
3.布局onLayout(自定义ViewGroup调用)
4.绘制onDraw
5.onTouchEvent(与用户进行交互调用)
6.onInterceptTouchEvent(自定义ViewGroup,并拦截子View事件调用)

二、自定义属性声明与获取

1.分析需要的自定义属性
2.在res/values/attrs.xml定义声明(文件名字attrs是随意取的)
声明:res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="titleText" format="string"/>
    <attr name="titleColor" format="color"/>
    <attr name="titleSize" format="dimension"/>

    <declare-styleable name="CustomTitleView">
        <attr name="titleText"/>
        <attr name="titleColor"/>
        <attr name="titleSize"/>
    </declare-styleable>

</resources>
3.在layout.xml文件中进行使用自定义View
4.在View的构造方法中进行获取
TypedArray customArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTitleView);
int n = customArray.getIndexCount();
for (int i = 0; i <= n; i++) {
    int attr = customArray.getIndex(i);
    switch (attr) {
    case R.styleable.CustomTitleView_titleText:
        title = customArray.getString(attr);
        break;
    case R.styleable.CustomTitleView_titleColor:
        titleColor = customArray.getColor(attr, Color.BLACK);
        break;
    case R.styleable.CustomTitleView_titleSize:
        titleSize = customArray.getDimensionPixelSize(attr, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 60, getResources().getDisplayMetrics()));
        break;
    default:
        break;
    }
}
customArray.recycle();

三、测量onMeasure

测量自身尺寸范围是有两个元素决定:测量模式和测量值
1.测量模式:EXACTLY(明确的值或者match_parent), AT_MOST(至多不能超过某个值,一般设置在wrap_content), UNSPECIFIED(没限制,一般建于ScrollerView或ListView)
2.MeasureSpec:这个辅助类封装了模式和值,是在onMeasure方法中父控件传下来的
3.setMeasuredDimension:在onMeasure测量完成后调用
4.requestLayout():重新测量和布局,不会触发重新绘制
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int width, height;
    if (widthMode == MeasureSpec.EXACTLY) {
        width = widthSize;
    } else {
        width = getNeedWidth()+getPaddingLeft()+getPaddingRight()); //计算自身需要的宽度
        if (widthMode == MeasureSpec.AT_MOST) {
            width = Math.min(width, widthSize);
        } 
    }
    ...
    setMeasuredDimension(width, height);
}

四、布局onLayout(自定义ViewGroup调用)

该函数是父控件决定子View的显示位置,所以对ViewGroup有效。
1.决定子View的位置
2.尽可能将onMeasure中一些操作移动到此方法中:onMeasure可能会触发多次,onLayout只会触发一次,较轻量级
3.requestLayout():会触发onlayout()函数

五、绘制onDraw

1.绘制内容区域
2.invalidate(), postInvalidate():重新绘制,postInvalidate()是在子线程中调用
3.Cavas.drawXXX
4.translate、rotate、scale、skew
5.save()、restore()
@Override
protected void onDraw(Canvas canvas) {
    //使用Cavas相关API绘制anything you want
}

六、onTouchEvent

1.ACTION_DOWN、ACTION_MOVE、ACTION_UP
2.ACTION_POINTER_DOWN、ACTION_POINTER_UP
3.parent.requestDisallowInterceptTouchEvent(true)
4.VelocityTracker

七、onInterceptTouchEvent(ViewGroup)

1.ACTION_DOWN、ACTION_MOVE、ACTION_UP
2.ACTION_POINTER_DOWN、ACTION_POINTER_UP
3.决定是否拦截该手势
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值