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页

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值