Multiple Solutions for obtaining a view width and height of 0 in android onCreate

Source: Internet
Author: User

Multiple Solutions for obtaining a view width and height of 0 in android onCreate

This problem must have been encountered more than once. It is actually very simple and easy to solve. But what we are pursuing is not to solve it, but to find several solutions, what is the principle of this solution.
Four solutions are listed here:

Activity/View # onWindowFocusChanged

The function indicates that the view has been initialized and the width/height is ready. You can obtain the width/height at this time. However, it should be noted that the onWindowFocusChanged function will be called multiple times. When the Activity window gets the focus and loses the focus, it will be called once. If onResume and onPause are performed frequently, onWindowFocusChanged will also be called frequently.

@Overridepublic void onWindowFocusChanged(boolean hasFocus) {    super.onWindowFocusChanged(hasFocus);    L.i("onWindowFocusChanged : v_view1.getWidth():" + v_view1.getWidth()            + "  v_view1.getHeight():" + v_view1.getHeight());}
View. post (runnable)

Post can deliver a runnable to the end of the message queue, and wait for the UI thread logoff to call this runnable, the view has also been initialized.

v_view1.post(new Runnable() {    @Override    public void run() {        L.i("post(Runnable) : v_view1.getWidth():" + v_view1.getWidth()                + "  v_view1.getHeight():" + v_view1.getHeight());    }});
ViewTreeObserver

The ViewTreeObserver callback can be used to complete this function. For example, when the status of the view tree changes or the visibility of the view tree changes using the OnGlobalLayoutListener interface, the onGlobalLayout method will be called back, so this is a good time to get the width and height of the view. It should be noted that onGlobalLayout will be called multiple times along with the status change of the view tree.

v_view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {    @Override    public void onGlobalLayout() {        L.i("ViewTreeObserver : v_view1.getWidth():" + v_view1.getWidth()                + "  v_view1.getHeight():" + v_view1.getHeight());    }});

The ViewTreeObserver class is used to register the callback listener when the global status of the view tree changes. There are many global events, such as the layout of the entire view tree view, view creation, click event changes, and so on. Do not instantiate the ViewTreeObserver object in the application, because the object is only provided by the view.
The ViewTreeObserver class provides several related functions to add listeners of the view tree:

Public void addOnDrawListener (ViewTreeObserver. onDrawListener) this function is added to api Version 16 to register the callback listener when the view tree is to be drawn, note that this function and the related remove function cannot be called in the onDraw () callback of the listener. Public void addOnGlobalFocusChangeListener (ViewTreeObserver. OnGlobalFocusChangeListener listener) This function is used to register the callback listener when the view tree focus changes. Public void addOnGlobalLayoutListener (ViewTreeObserver. OnGlobalLayoutListener listener) is used to register the callback listener when the global layout attribute or visibility of the view changes in the view tree. Public void addOnPreDrawListener (ViewTreeObserver. OnPreDrawListener listener) This function is used to register the callback listener when the view tree is to be drawn (before the onDraw function of the view. Public void addOnScrollChangedListener (ViewTreeObserver. OnScrollChangedListener listener) This function is used to register the callback listener when the view tree slides, for example, to listen to the sliding status of the ScrollView. Public void addOnTouchModeChangeListener (ViewTreeObserver. onTouchModeChangeListener) registers the callback listener when the touch mode of the view tree changes. The isInTouchMode in the onTouchModeChanged (boolean isInTouchMode) function is the touch mode of the view tree. Public void addon#wattachlistener (ViewTreeObserver. ondeskwattachlistener listener) api 18 is added to register the callback listener when the view tree is attached to a window. Public void addOnWindowFocusChangeListener (ViewTreeObserver. OnWindowFocusChangeListener listener) api 18 is added to register the callback listener when the view tree focus in the window changes. Each add method also has a remove Method to delete the listener.

View. measure (int widthMeasureSpec, int heightMeasureSpec)

You can manually perform the measure operation on the view to obtain the width and height of the view. This situation is complicated. here we need to handle the situation based on the layoutparams of the view:

Match_parent

Give up directly, and cannot measure the specific width/height. The reason is very simple. According to the measure process of view, to construct this MeasureSpec, you need to know the parentSize, that is, the remaining space of the parent container. At this time, we cannot know the size of parentSize, therefore, it is theoretically impossible to measure the view size.

Wrap_content
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST);int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST);v_view1.measure(widthMeasureSpec, heightMeasureSpec);

Note that (1 <30)-1, we know that the first two bits of MeasureSpec are mode and the last 30 bits are size. Therefore, we use the maximum size value to match this maximization mode, let the view calculate the required size.

Specific value (dp/px)

In this mode, you only need to use a specific value to measure. For example, the width/height is 100px:

int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);v_view1.measure(widthMeasureSpec, heightMeasureSpec);
Source code and Result

The demo code is as follows:
Xml:


  
      
       
   
  

Activity:

public class MainActivity extends BaseActivity{    private View v_view1;    private View v_view2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        v_view1 = findViewById(R.id.v_view1);        v_view2 = findViewById(R.id.v_view2);        L.i("normal: v_view1.getWidth():" + v_view1.getWidth()                + "  v_view1.getHeight():" + v_view1.getHeight());        v_view1.post(new Runnable() {            @Override            public void run() {                L.i("post(Runnable) : v_view1.getWidth():" + v_view1.getWidth()                        + "  v_view1.getHeight():" + v_view1.getHeight());            }        });        v_view1.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {            @Override            public void onGlobalLayout() {                L.i("ViewTreeObserver : v_view1.getWidth():" + v_view1.getWidth()                        + "  v_view1.getHeight():" + v_view1.getHeight());            }        });        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST);        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1<<30)-1, View.MeasureSpec.AT_MOST);        v_view1.measure(widthMeasureSpec, heightMeasureSpec);        L.i("measure : v_view1.getMeasuredWidth():" + v_view1.getMeasuredWidth()                + "  v_view1.getMeasuredHeight():" + v_view1.getMeasuredHeight());        v_view2.measure(widthMeasureSpec, heightMeasureSpec);        L.i("measure : v_view2.getMeasuredWidth():" + v_view2.getMeasuredWidth()                + "  v_view2.getMeasuredHeight():" + v_view2.getMeasuredHeight());    }    @Override    public void onWindowFocusChanged(boolean hasFocus) {        super.onWindowFocusChanged(hasFocus);        L.i("onWindowFocusChanged : v_view1.getWidth():" + v_view1.getWidth()                + "  v_view1.getHeight():" + v_view1.getHeight());    }}

Log:

I/[PID:2659]: [TID:1] MainActivity.onCreate(line:28): normal: v_view1.getWidth():0  v_view1.getHeight():0I/[PID:2659]: [TID:1] MainActivity.onCreate(line:50): measure : v_view1.getMeasuredWidth():144  v_view1.getMeasuredHeight():144I/[PID:2659]: [TID:1] MainActivity.onCreate(line:53): measure : v_view2.getMeasuredWidth():16777215  v_view2.getMeasuredHeight():16777215I/[PID:2659]: [TID:1] 2.onGlobalLayout(line:42): ViewTreeObserver : v_view1.getWidth():144  v_view1.getHeight():144I/[PID:2659]: [TID:1] 1.run(line:34): post(Runnable) : v_view1.getWidth():144  v_view1.getHeight():144I/[PID:2659]: [TID:1] MainActivity.onWindowFocusChanged(line:61): onWindowFocusChanged : v_view1.getWidth():144  v_view1.getHeight():144

Interface:

View_1 is small, view_2 is large, and a problem is found in the log: it is wrong for view_2 view to calculate the width and height after using measure, therefore, the results calculated using measure for views of the View class are inaccurate, which requires special attention.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.