1、自定义属性的声明与获取
2、测量onMeasure
3、布局onLayout(ViewGroup)
4、绘制onDraw
5、onTouchEven
6、onInterceptTouchEven(ViewGroup)
一、自定义属性的声明与获取
1.分析需要的自定义属性
2.在res/values/attrs.xml定义声明
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="icon" format="reference"></attr>
<attr name="color" format="color"></attr>
<attr name="text" format="string"></attr>
<attr name="text_size" format="demension"></attr>
<declare-styleable name="ChangeColorIconWithText">
<attr name="icon"></attr>
<attr name="color"></attr>
<attr name="text"></attr>
<attr name="text_size"></attr>
</declare-styleable>
</resources>
3.在layout xml文件中进行使用
4.在View的构造方法中进行获取
TypedArray a = context.obtainStyledAtributes(attrs, R.styleable.ChangeColorIconWithText);
int n = a.getIndexCount();
for(int i=0; i<n; i++){
int attr = a.getIndex(i);
switch(attr){
case R.styleable.ChangeColorIconWithText_icon:
BitmapDrawable drawable = (BitmapDrawable) a.getDrawable(attr);
mmIconBitmap = drawable.getBitmap();
break;
case R.styleable.ChangeColorIconWithText_color:
mColor = a.getColor(attr, 0xFF45C01A);
break;
case R.styleable.ChangeColorIconWithText_text:
mText = a.getString(attr);
break;
case R.styleable.ChangeColorIconWithText_text_size:
mTextSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getReources().getDisplayMetrics()));
break;
}
}
a.recycke();
二、测量onMeasure
1.EXACTLY,AT_MOST,UNSPECIFIED
2.MeasureSpec
3.setMeasuredDimension
4.requestLayout()
private int measureHeight(int heightMeasureSpec){
int result = 0;
int mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
if(mode == MeasureSpec.EXACTLY){
requestLayout = size;
}else {
// 计算自身需要的高度
requestLayout = getNeedHeight() + getPaddingTop() + getPaddingBottom();
if(mode == MeasureSpec.AT_MOST){
result = Math.min(result, size);
}
}
return result;
}
三、布局onLayout(ViewGroup)
1.决定子Veiw的位置
2.尽可能将onMeasure中一些操作移动到此方法中
3.requestLayout()
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b){
final int childCount = getChildCount();
for(int i=0; i<childCount; i++){
final View child = getChilAt(i);
if(child.getVisibiility()==GONE){
continue;
}
//计算childview layout的左上角x坐标
left = caculateChildLeft();
//计算childview layout的左上角y坐标
top = caculateChildRight();
child.layout(left, top, left + cWidth, top + cWidth);
}
}
四、绘制onDraw
1.绘制内容区域
2.invalidate(), postInvalidate();
3.Canvas.drawXXX
4.translate、rotate、scale、skew
5.save()、restore()
@Override
protected synchronized void onDraw(Canvas canvas){
//使用Canvas相关的API绘制anything you want
}
五、onTouchEven
1.ACTION_DOWN、ACTION_MOVE、ACTION_UP
2.ACTION_POINER_DOWN、ACTION_POINTER_UP
3.parent.requedtDisallowInterceptTouchEvent(true);
4.VelocityTracker
@Override
public boolean onTouchEven(MotionEvent ev){
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
final int action = ev.getAtction();
switch(action & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DWON:
//进行一些初始化、赋值等的操作
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
//如果需要进行速度判断
int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
//释放各种资源、重复变量
break;
case MotionEvent.CANCLE:
//释放各种资源、重复变量
break;
case MotionEvent.ACTION_POINER_DOWN:
/如果支持多指,在此设置activePoniter
final int index = ev.getAtctionIndex();
mLastMotionY = (int) ev.getY(index);
mActivePointerId = ev.getPointerId(index);
break;
case MotionEvent.ACTION_POINER_UP:
//如果支持的是多指且抬起的是activePoniter,则重新选择一个手指为活跃的手指
if(pointerId == mActivePointerId){
final int newPointerIndex = pointerIndex == 0?1:0;
mLastMotionY = (int) ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
if(mVelocityTracker != null){
mVelocityTracker.clear();
}
}
break;
}
return true;
}
六、onInterceptTouchEven(ViewGroup)
1.ACTION_DOWN、ACTION_MOVE、ACTION_UP
2.ACTION_POINER_DOWN、ACTION_POINTER_UP
3.决定是否拦截该手势
@Override
public boolean onInterceptTouchEven(MotionEvent ev){
int action = ev.getAtction();
switch(action & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_MOVE:
final int activePointerId = mActivePointerId;
if(activePointerId == INVALID_POINTER){
break;
}
final int pointerIndex = ev.getAtctionIndex(activePointerId);
final int y = (int) ev.getY(pointerIndex);
final int yDiff = Math.abs(y - mLastMotionY);
if(yDiff > mTouchSlop){
mIsBeingDragged = true;
mLastMotionY = y;
}
break;
case MotionEvent.ACTION_DWON:
break;
case MotionEvent.CANCLE:
case MotionEvent.ACTION_UP:
break;
return mIsBeingDragged;
}
七、还有什么?
1.onSaveInstanceState、onRestoreInstanceState
2.ViewConfiguration(mTouchSlop等)
3.ScaleGestureDetector
4.更多...