android How to Obtain the Height and Width of view in the Layout

  • 2021-10-16 02:38:07
  • OfStack

Preface

In many cases, we will need to get the size (width and height) of view in activity. Faced with this situation, many students immediately responded: Do you still have to say such a simple question? Are you stupid. . Then immediately write down getWidth (), getHeight () and other methods, and leave triumphantly. But is this the case? Practice has proved that we can't get the width and height of View in this way.

When we get the width and height of an View component in the onCreate () method, we call the getWidth (), getHeight (), getMeasuredWidth (), getMeasuredHeight () methods directly and get only 0. What is the reason for this? Let's take a look at one of the following

Implementation method

1. Measuring View using View. measure

The width and height measured by this method may be different from the true width and height after the view is drawn.


int width = View.MeasureSpec.makeMeasureSpec(0,
  View.MeasureSpec.UNSPECIFIED);
int height = View.MeasureSpec.makeMeasureSpec(0,
  View.MeasureSpec.UNSPECIFIED);
view.measure(width, height);
view.getMeasuredWidth(); //  Get Width 
view.getMeasuredHeight(); //  Obtain height 

2. Use ViewTreeObserver. OnPreDrawListener to listen for events

Calling this listening event when the view is about to be drawn will be called multiple times, so the listening event should be removed after obtaining the width and height of the view.


view.getViewTreeObserver().addOnPreDrawListener(
  new ViewTreeObserver.OnPreDrawListener() {
 
 @Override
 public boolean onPreDraw() {
  view.getViewTreeObserver().removeOnPreDrawListener(this);
  view.getWidth(); //  Get Width 
  view.getHeight(); //  Obtain height 
  return true;
 }
});

3. Use ViewTreeObserver. OnGlobalLayoutListener to listen for events

Calling this event when the layout changes or the visual state of a view changes will be called multiple times, so you need to execute the remove method to remove the listening event after obtaining the width and height of the view.


view.getViewTreeObserver().addOnGlobalLayoutListener(
  new ViewTreeObserver.OnGlobalLayoutListener() {
 
 @Override
 public void onGlobalLayout() {
  if (Build.VERSION.SDK_INT >= 16) {
   view.getViewTreeObserver()
     .removeOnGlobalLayoutListener(this);
  }
  else {
   view.getViewTreeObserver()
     .removeGlobalOnLayoutListener(this);
  }
  view.getWidth(); //  Get Width 
  view.getHeight(); //  Obtain height 
 }
});

4. Override the onSizeChanged method of View

Calling this method when the size of the view changes will be called many times, so you need to consider disabling the code after obtaining the width and height.
This implementation method needs to inherit View and is called many times, so it is not recommended.


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);
 
 view.getWidth(); //  Get Width 
 view.getHeight(); //  Obtain height 
}

5. Override the onLayout method of View

This method will be called many times, and it is necessary to consider disabling the code after obtaining the width and height.

This implementation method needs to inherit View and has been called many times, so it is not recommended.


@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
 super.onLayout(changed, l, t, r, b);
 
 view.getWidth(); //  Get Width 
 view.getHeight(); //  Obtain height 
}

6. Use View. OnLayoutChangeListener to listen for events (API > = 11)

Calling this event when the view's layout changes will be called multiple times, so you need to execute the remove method to remove the listening event after obtaining the width and height of the view.


view.addOnLayoutChangeListener(
  new View.OnLayoutChangeListener() {
 
 @Override
 public void onLayoutChange(View v, int l, int t, int r, int b,
   int oldL, int oldT, int oldR, int oldB) {
  view.removeOnLayoutChangeListener(this);
  view.getWidth(); //  Get Width 
  view.getHeight(); //  Obtain height 
  }
});

7. Use the View. post () method

The methods in the Runnable object are triggered after the measure, layout, and so on of the View are completed.

The UI event queue processes events sequentially, and after setContentView () is invoked, the event queue contains an message that requires re-layout, so any Runnable objects in the post to queue are executed after Layout changes.

This method will only be executed once, and its logic is simple, so it is recommended to use it.


view.post(new Runnable() {
 
 @Override
 public void run() {
  view.getWidth(); //  Get Width 
  view.getHeight(); //  Obtain height 
 }
});

The above is the reprinted content, personal study collection record

The following is my study record.

First of all, the first method, which has been used before, is really inaccurate. Guess it should be because the parameters are not used well, because the parameters only use the measurement method not specified by UNSPECIFIED, like Wrap_Content, which is the measurement method.

Here, post a relatively easy-to-use method for AndroidUtilCode collection.


 public static int[] measureView(final View view) {
  ViewGroup.LayoutParams lp = view.getLayoutParams();
  if (lp == null) {
   lp = new ViewGroup.LayoutParams(
     ViewGroup.LayoutParams.MATCH_PARENT,
     ViewGroup.LayoutParams.WRAP_CONTENT
   );
  }
  int widthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
  int lpHeight = lp.height;
  int heightSpec;
  if (lpHeight > 0) {
   heightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, View.MeasureSpec.EXACTLY);
  } else {
   heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
  }
  view.measure(widthSpec, heightSpec);
  return new int[]{view.getMeasuredWidth(), view.getMeasuredHeight()};
 }

Then, when I am doing custom view, I need to create add code once. I can't get width and height by using the above method, because I use ScrollView. Like in custom, loading the layout once, the last post method should be selected for most use.

In addition, it should be the third way, which is used externally, such as waiting for the operation after Recyclerview drawing is completed.

Summarize


Related articles: