getWidth与getMeasureWidth

getWidth

      以ImageView为例,源代码:

public final int getWidth() {
        return mRight - mLeft;
    }
      可以发现该方法是final的,只有在View类中有。而在View类中mRight与mLeft的赋值只有在protected boolean setFrame(int left, int top, int right, int bottom)方法中进行。同时在ImageView中没有发现有方法会对mRight进行赋值。

     而setFrame()的方法片断如下:

            mLeft = left;
            mTop = top;
            mRight = right;
            mBottom = bottom;

      而在View中又只有layout()方法调用了setFrame()

 public void layout(int l, int t, int r, int b) {
        int oldL = mLeft;
        int oldT = mTop;
        int oldB = mBottom;
        int oldR = mRight;
        boolean changed = setFrame(l, t, r, b);

因此,可以认为getWidth得到的只是layout()方法参数中的差值

再看layout的参数说明:

left Left position, relative to parent
top Top position, relative to parent
right Right position, relative to parent
bottom Bottom position, relative to parent

        四个参数分别指的是当前View在它的父View中的位置,并且是相对于它的父View来说的(也就是以父View的左上角为原点,向右为正,向下为正建立坐标系时,当前View的左上角(l,t)、右下角(r,b)分别的坐标),并不是相对于整个屏幕来说的

      下面以LinearLayout的onLayout()源代码为例,佐证上面四个参数的含义:

LinearLayout的onLayout()发现它最终会调用layoutVertical(),layoutVertical()片断如下:

 setChildFrame(child, childLeft, childTop + getLocationOffset(child),
                        childWidth, childHeight);
而setChildFrame的代码为:

 private void setChildFrame(View child, int left, int top, int width, int height) {        
        child.layout(left, top, left + width, top + height);
    }
       而在layoutVertical()方法中可以发现childTop是不断进行累加的,并且是在layoutVertical()中进行声明的。

因此,当调用到child.layout()时,传入的参数便是指:child在其父组件中的位置。并且是相对于它的父组件来说的。

       由此可知:getWidth得到的是当前View在其父组件中的所占区域的宽度,也就是它的真实宽度(当调用完layout之后,该组件在父组件中所占的区域已经固定了,所以说是它的真实位置),并不是屏幕展示出来的宽度

如:自定义一个类MyViewGroup继承于ViewGroup,重写其中的onLayout()方法,更改其子View所占的位置

@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		System.out.println(left+"/"+right+"/"+top+"/"+bottom+"/"+getWidth());
		for(int x = 0;x<getChildCount();x++){
			View view = getChildAt(x);
			view.layout(10, 0, getWidth()+123, getHeight()+200);
		}
	}
布局为:

    <com.example.demo.MyViewGroup
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginLeft="20px"
        android:background="#ffffff"
        android:layout_weight="1"
         >

        <ImageView
            android:id="@+id/iv_after"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/big" />
    </com.example.demo.MyViewGroup>
        其中,marginLeft的单位用的是px,而不是常用的dp,这是因为代码中得到的值都是px,dp与px是需要进行换算的,为了方便就不采用dp了。再在activity中调用imageView组件的getWidth()方法,得到的值是:573。

       而onLayout()方法输入的结果是:20/480/0/378/460。

分析:

       首先left的20是因为在布局文件中设置了margin_Left为20px。480是因为MyViewGroup是match_parent的(手机的宽也是480)。

       其中ImageView.getWidth得到的是573:这是因为imageView在MyViewGroup中占的区域为(10,top)与(getWidth()(此处的getWidth指的是MyViewGroup的宽度,即460)+123,bottom)形成的矩形,该矩形的宽度便是460+123-10=573。

最后:由上面的分析知:

       在layout方法结束之后,都可以调用组件的getWidth并且得到正确的值。如重写MyViewGroup的onDraw,在其中调用getWidth就可以得到正确的值。

      getRight等方法返回的都该组件距其父组件边界的某些距离,并不是距离屏幕的

      getWidth():得到的是父View分配给子View的大小,即layout()中所指定的矩形的大小.这个值并不是子View的实际大小。如子View需要200px,但父View只能分配给它100px,此时getWidth就是100px。

getMeasureWidth():

       得到的是该View自己的测量大小,准确点说是通过setMeasuredDimension()方法设置的大小。在measure阶段之后就可以调用该方法得到值了。因此,与getWidth并不是一回事。










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值