Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别

一、设置控件宽高

设置Layout_width/height引发的宽高思考

方式一:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第1张图片


Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第2张图片


Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第3张图片


结果不符合预期。

运行结果:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第4张图片



方式二:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第5张图片


Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第6张图片


结果符合预期。

如下图:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第7张图片



Android控件宽高的规则:  

Android下的控件默认没有宽高,是由父控件给其宽高的。

其中一般的view控件是由(ViewGroup控件:LinearLayout、RelativeLayout 、TableLayout、FrameLayout 、AbsoluteLayou )五大布局给其宽高的。

而像LinearLayout、RelativeLayout等这些最外层的布局控件的宽高是由Android系统的FrameLayout控件设定的。可用android-sdk/tools下的工具hierarchyviewer.bat查看,如下图:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第8张图片


针对方式一的修改方案,如下代码:


Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第9张图片


运行结果如下:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第10张图片



二、Activity中获取控件的宽高

程序启动时想要获取特定视图组件的尺寸大小,在onCreate中可能无法取到,因为窗口Window对象还没创建完成,还没有执行onMeasure 和 onLayout方法,所以,此时getWidth返回值是0。那么如何或者说何时才能获取控件的大小呢?


方案1:在oncreate方法中, 发一个延迟消息,在handleMesaage中获取控件宽高。原理就是延时一段时间,等待控件测量、布局完成后再获取。(虽然有用但不优雅)

   Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case GET_SIZE:
                    int width = listView.getWidth();
                    break;
            }

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_conversation_ui);
        handler.sendEmptyMessageDelayed(GET_SIZE, 500);
    }

方案2:获得全局viewTree的观察者,并添加全局的layout监听。原理就是监听onlayout方法执行完成之后,就可以获取控件大小了。

// 获得全局viewTree的观察者,并添加 全局的layout监听
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.
    OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
      //由于此方法会执行多次,而我们只需要执行一次就可以了,
      //所以,在执行一次的时候,将全局的layout监听取消,此处this指的是,内部的匿名对象
      imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      int width = imageView.getWidth();
    }

});


方案3:主动通知系统去测量,调用measure(0,0)方法 。再用getMeasureWidth就可以得到测量的结果了。

imageView.measure(0, 0);// 主动通知系统去测量
LogUtils.d("========== imageView getMeasuredWidth: "+imageView.getMeasuredWidth());


方案4:重写Activity的onWindowFocusChanged方法。

在Activity窗口获得或失去焦点时被调用,例如创建时首次呈现在用户面前;当前Activity被其他Activity覆盖;当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;用户退出当前Activity。以上几种情况都会调用onWindowFocusChanged。

@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        LogUtils.d("========== imageView getWidth: " + imageView.getWidth());
    }


三、getWidth()与getMeasuredWidth()的区别

从上面代码可以看到,获取控件的宽高有时用getWidth()方法,有时用getMeasuredWidth()方法,这两个方法有什么区别呢?

getWidth()方法源码:

    /**
     * Return the width of the your view.
     *
     * @return The width of your view, in pixels.
     */
    @ViewDebug.ExportedProperty(category = "layout")
    public final int getWidth() {
        return mRight - mLeft;
    }

从源码可以看出,getwidth返回的是右边坐标减去左边坐标(也就是控件右边距屏幕Y轴的距离减去控件左边距屏幕Y轴的距离),这要在布局之后(也就是onLayout()方法执行完之后)才能确定它们的坐标。在布局后(也就是onLayout()方法执行完之后)才能调用getwidth来获取。

总结:getWidth()获得的宽度是View在设定好布局后整个View的宽度。 这个宽度是指在容器ViewGroup中,该view的宽度,可称为:布局宽度。


getMeasuredWidth()方法源码:

    /**
     * Like {@link #getMeasuredWidthAndState()}, but only returns the
     * raw width component (that is the result is masked by
     * {@link #MEASURED_SIZE_MASK}).
     *
     * @return The raw measured width of this view.
     */
    public final int getMeasuredWidth() {
        return mMeasuredWidth & MEASURED_SIZE_MASK;
    }

注释:return The raw measured width of this view 获得的是原始的测量宽度。onMeasure()方法执行完之后就可以调用该方法获取。

总结:getMeasuredWidth()是对View上的内容进行测量后得到的View内容占据的宽度。这个宽度是根据view中的内容决定。可称为:组件宽度

当然要得到View内容占据的宽度,前提是你必须在父布局的onLayout()方法或者此View的onDraw()方法里调用measure(0,0);(measure中的参数的值你自己可以定义),否则你得到的结果和getWidth()得到的结果是一样的。

比如你定义一个组件的宽50、高50;但是你在布局文件中,硬是要把layout_width指定为match_parent(假设只有一个组件),那这个组件的宽度就被拉到全屏了。这时候getWidth()得到的就是布局宽度。如果要想得到原始宽度,必须调用该组件的measure(0,0)方法重新测量 。再用getMeasureWidth就可以得到了。


两者的使用场合:

getMeasuredWidth:在自定义view重写onLayout时、在我们用layoutinflater动态加载view后想获得view的原始宽度时。

getWidth:一般在view已经布局后呈现出来了,想获取宽度时


四、layout_grivaty与grivaty


layout_grivaty使用时的注意点:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第11张图片


结果如下图:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第12张图片



Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第13张图片


结果如下图:

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第14张图片



区别:


Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别_第15张图片








你可能感兴趣的:(Android基础)