android view(5)自定义组件
一、view的绘制流程是从ViewRoot的performTraversals方法开始的,包含以下三个过程:
1.measure过程
从*view开始遍历,在performMeasure调用measure,然后调用OnMeasure。onMeasure会对所有子元素进行measure完成遍历。
2.layout过程
同上。performLayout->layout->onLayout
3.draw过程
同上。performDraw->draw->onDraw
二、DecorView
继续自LinearLayout,view层的事件都先经过DecorView,然后才传递给我们的view.在LinearLayout中,包含两个部分,分别是标题栏和内容栏。内容栏的id就叫content,经常使用的setContentView就是加到这个内容栏中的,如setContentView(R.layout.hello_world_layout);可以这样获取我们设置的view:
ViewGroup content = (ViewGroup)findViewById(android.R.id.content);
content.getChildAt(0)
三、如何获得宽高
因为view的measure过程和activity的生命周期不是同步执行的,因此无法保证activity执行onCreate,onStart,onResume时宽高已经测量完毕。如果没有测量完毕,则会返回0.有四种方法可以获得测量后的宽高,这里只介绍一个简单的:
protected void onStart(){
super.onStart();
view.post(new Runnable(){
public void run(){
int width = view.getMeasuredWidth();
int height = view.getMeasureHeight();
}
}
);
}
通过post可以将一个runnable投递到一个消息队列的尾部,然后等待looper调用此runnable的时候,view也已经初始化好了。
四、自定义组件注意事项
1.重写onMeasure方法并设置wrap_content时的自身大小,否则在布局中使用wrap_content就相当于使用match_parent。
2.在draw方法中支持padding和margin
3.view中如果有线程或者动画需要及时停止。当包含view的activity退出或者当前的view被remove时,view的onDetachedFromWindow方法会被调用,相对应的,启动时执行onAttachedToWindow。
五、自定义组件继承自View重写onDraw方法
public class CircleView extends View{
private int mColor = Color.RED;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public CircleView(Context context){
super(context);
init();
}
public CircleView(Context context,AttributeSet attrs){
super(context,attrs);
init();
}
public CircleView(Context context,AttributeSet attrs,int defStyleAttr){
super(context,attrs,defStyleAttr);
init();
}
private void init(){
mPaint.setColor(mColor);
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//为了让padding和wrap_content生效,要做处理
final int paddingLeft = getPaddingLeft();
final int paddingRight = getPaddingRight();
final int paddingTop = getPaddingTop();
final int paddingBottom = getPaddingBottom();
int width = getWidth() - paddingLeft - paddingRight;
int height = getHeight() - paddingTop - paddingBottom;
int radius = Math.min(width,height)/2;
canvas.drawCircle(paddingLeft+width/2,paddingTop+height/2,radius,mPaint);
}
}
自定义属性参见206页
六、继承viewgroup派生特殊的layout
参见210页
上一篇: 翻译文章(六):如何成为专家-拥抱现实
下一篇: android intent