分享

onMeasure和onLayout理解

 quasiceo 2015-06-30
2012-07-23 12:22 3951人阅读 评论(2) 收藏 举报
 
2012-05-05 10:30 329人阅读 评论(0) 收藏 举报
我们知道View在屏幕上显示出来要先经过measure和layout. 在调用onMeasure(int widthSpec, int heightSpec)方法时,要涉及到MeasureSpec的使用,MeasureSpec有3种模式分别是UNSPECIFIED, EXACTLY和AT_MOST, 那么这些模式和我们平时设置的layout参数fill_parent, wrap_content有什么关系呢。经过代码测试就知道,当我们设置width或height为fill_parent时,容器在布局时调用子view的measure方法传入的模式是EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的。而当设置为wrap_content时,容器传进去的是AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸。当子view的大小设置为精确值时,容器传入的是EXACTLY, 而MeasureSpec的UNSPECIFIED模式目前还没有发现在什么情况下使用。

   View的onMeasure方法默认行为是当模式为UNSPECIFIED时,设置尺寸为mMinWidth(通常为0)或者背景drawable的最小尺寸,当模式为EXACTLY或者AT_MOST时,尺寸设置为传入的MeasureSpec的大小。

   有个观念需要纠正的是,fill_parent应该是子view会占据剩下容器的空间,而不会覆盖前面已布局好的其他view空间,当然后面布局子view就没有空间给分配了,所以fill_parent属性对布局顺序很重要。以前所想的是把所有容器的空间都占满了,难怪google在2.2版本里把fill_parent的名字改为match_parent.

有关Android的自定义View的框架今天我们一起讨论下,对于常规的游戏,我们在View中需要处理以下几种问题:
  1.控制事件
  2.刷新View
  3. 绘制View.(文/Android开发网)
  1.对于控制事件今天我们只处理按键事件onKeyDown,以后的文章中将会讲到屏幕触控的具体处理onTouchEvent以及Sensor重力感应等方法。
  2.刷新view的方法这里主要有
  invalidate(int l, int t, int r, int b) 刷新局部,四个参数分别为左、上、右、下
  整个view刷新 invalidate()
  刷新一个矩形区域invalidate(Rect dirty)
  刷新一个特性DrawableinvalidateDrawable(Drawable drawable)
  执行invalidate类的方法将会设置view为无效,最终导致onDraw方法被重新调用。
  由于今天的view比较简单,Android123提示大家如果在线程中刷新,除了使用handler方式外,可以在Thread中直接使用postInvalidate方法来实现。
  3. 绘制View主要是onDraw()中通过形参canvas来处理,相关的绘制主要有drawRect、drawLine、drawPath等等。
  view方法内部还重写了很多接口,其回调方法可以帮助我们判断出view的位置和大小,比如onMeasure(int, int) Called to determine the size requirements for this view and all of its children。 、onLayout(boolean, int, int, int, int) Called when this view should assign a size and position to all of its children 和onSizeChanged(int, int, int, int) Called when the size of this view has changed。 具体的作用,大家可以用Logcat获取当view变化时每个形参的变动。

这两个函数都是系统来调用的,onMeasure是计算view的宽和高,onLayout是确定布局和位置的

我遇到了关节ViewGroup界面显示和刷新的问题

问题一:动态添加控件(如,textview)
描述:通oncreate里面动态new出添加控件(textView),添加到ViewGroup内是可以正常显示视图的。如果我换成按钮点击事件,点击一下加一个添加控件(如:textView),发现第一次添加的时候是没有任何反应的,ViewGroup没有任何变化,第二次就正常了。我观察到onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4)中arg4 == 0 ,整个ViewGroup的高度为0,所以没有任何变化。

请问:为何第一次ViewGroup的高度为0,如何解决此类问题。

问题二:ViewGroup里面添加N个组建(如textview,button),逻辑是点击某个组建以后,该组件gone掉,重排整个视图,但是结果是该视图消失了,留下一个空洞。。整个视图并没有按照onLayout里面的逻辑重新排列。

请问:ViewGroup应该如何动态刷新界面。(虽然控件gone掉了也算是刷新了界面,但是却不是我想要的效果)

第二个问题我已经解决了,虽然在我的业务里面比较麻烦,不过理论还是比较简单的。

比如控件的列表为 listview<TextView> list ...

1、删除该textView :list.remove(tv);
2、移除所有子视图:viewGroup.removeAllViews();
3、重新加载子视图:viewgroup.add(tv);
这样就解决了不能按照onlayout方法刷新的问题

但是我还是疑惑为什么这样做就不会出现上述问题一的情况,不是因为控件已经初始化过,因为后面我发现虽然控件初始化过,但是一西行添加多条的时候,viewgroup还是原始大小

  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多