自定义View学习笔记1

自定义View

自定义View是原生系统的控件无法满足,需要开发者自己去实现;
1.组合控件
2.继承控件
3.继承View

onMeasure()

在绘制View时,一定会执行的方法,布局的宽高都是通过这个指定的

// 获取宽高的模式
int withMode = MeasureSpec.getMode(withMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);

通过对宽高模式的对比可以进行执行某些操作,例如:

if(withMode == MeasureSpec.AT_MOST){
//编写执行相应的操作
}

其中宽高的模式有三种
MeasureSpec.AT_MOST
布局中指定wrap_content
MeasureSpec.EXACTLY
布局中指定确切的值、match_parent、fill_parent
MeasureSpec.UNSPECIFIED
尽可能的大,比较少用到,ListView、ScrollView 在测量子布局的时候会用到

引出问题:ScrollView嵌套LIstView显示不全
解决方法

public class MyListView extends ListView {
    public MyListView(Context context) {
        super(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //解决显示不全的问题
        //重新设置高度 heightMeasureSpec是个32位的值  其中的前30位现在变成了Integer.MAX_VALUE >> 2 , 后2位是信息的宽高模式MeasureSpec.AT_MOST
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2 ,MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

onDraw()

	/**
     * 用于绘制
     * @param canvas
     * */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画文本
        canvas.drawText();
        //画弧
        canvas.drawArc();
        //画圆
        canvas.drawCircle();
        //...
        //...
    }

onTouchEvent()

处理用户触摸事件

	/**
     * 处理跟用户交互,手指触摸等
     * @param ev
     * @return 此处涉及到一个设计模式:责任链模式
     * 比如用户在屏幕上按下后滑动再起来这个过程,
     * 如果返回true底层才会去不断循环用户事件的操作  如果返回false则只响应按下的操作就结束  如果返回super.onTouchEvent(ev)则交给父类去处理
     * */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                //手指在屏幕上按下
                break;
            case MotionEvent.ACTION_MOVE:
                //手指在屏幕上移动
                break;
            case MotionEvent.ACTION_UP:
                //手指在屏幕上抬起
                break;
        }
        return super.onTouchEvent(ev);
    }
//源码内容 当target不为空时则一直向下一个目标责任去取,直到执行完毕,所以如果外层返回了false则不再继续向下取责任,所以只执行一次
// Dispatch to touch targets, excluding the new touch target if we already
// dispatched to it.  Cancel touch targets if necessary.
TouchTarget predecessor = null;
TouchTarget target = mFirstTouchTarget;
while (target != null) {
	final TouchTarget next = target.next;
 	if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
		handled = true;
	} else {
		final boolean cancelChild = resetCancelNextUpFlag(target.child)
			|| intercepted;
		if (dispatchTransformedTouchEvent(ev, cancelChild,
			target.child, target.pointerIdBits)) {
			handled = true;
		}
        if (cancelChild) {
			if (predecessor == null) {
				mFirstTouchTarget = next;
			} else {
				predecessor.next = next;
			}
			target.recycle();
			target = next;
            continue;
			}
	}
	predecessor = target;
	target = next;
}

自定义属性

1.声明命名控件,然后在自己的自定义view中使用

xmlns:app="http://schemas.android.com/apk/res-auto"
<com.xxxx.MyTextView
	app:myText="hello"
	app:myTextColor="#878787"
	app:myTextSize="15sp"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"/>

自定义View中获取属性

//获取自定义属性
TypeArray array = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
mText = array.getString(R.styleable.MyTextView_myText);
mTextColor = array.getColor(R.styleable.MyTextView_myTextColor,mTextColor);
mTextSize = array.getDimensionPixelSize(R.styleable.MyTextView_myTextSize,mTextSize);
//回收
array.recycle();

以上是对Android/自定义控件/自定义View 的笔记1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值