2

Sometimes when I change a View in some way I don't get the correct dimensions after I change it.

Let's take for example a TextView that is single lined to true:

txv.setSingleLine(true)

Then I change it to false, let's say by clicking of a button:

txv.setSingleLine(false)

After that I call:

txv.invalidate()

But then I call:

int sizeH = txv.getHeight()

But I don't get the correct size after that. I still have the size of when the View was setSingleLine(true).

So at what time is it correct or safe to get the view dimensions I just had changed?

ci_
  • 8,594
  • 10
  • 39
  • 63
david96develop
  • 145
  • 2
  • 11
  • I don't know the answer to this. The android documentation is terrible. I usually do `view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);` and then `view.getMeasuredHeight()`; instead of `view.getHeight()`. It seems to work, but I can't guarantee it's the correct approach. – Paul Boddington Sep 11 '15 at 16:17
  • 1
    This answer http://stackoverflow.com/a/25846243/3973077 shows why `invalidate()` is not enough, but the first comment after the answer throws up further questions which I can't find an answer to anywhere. – Paul Boddington Sep 11 '15 at 16:29
  • The image confused me more, why is onDraw() after the onMeasure() because measure calculates the size dont ? perhaps is called requesLayout() more than once. So should i make a kind of filter to get the new meassure instead of the last meassure ? – david96develop Sep 11 '15 at 16:50
  • My confusion with that diagram is where `forceLayout` fits into it. `onDraw` has to come after `onMeasure`. You measure everything first so that `onDraw` gets a `Canvas` of the right size. The complexity here is that a parent can impose constraints on a child, so there is a difference between how big a `View` would be if unrestrained and how big a `View` will actually be when measured as part of a larger hierarchy. In many simple cases you can get away with just measuring the single view as I indicate in my first comment, but I don't understand the bigger picture at all. – Paul Boddington Sep 11 '15 at 17:02

1 Answers1

1

Solution 1
You can use ViewTreeObserver

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            view.getHeight(); //height is ready
        }
    });

Update:
Solution 2
Reference the link

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int size = 0;
    int width = getMeasuredWidth();
    int height = getMeasuredHeight();

}
Bruce Lan
  • 347
  • 2
  • 6
  • But is it only when the view is created for first time ? or Can i use it at any time i modify the view size by its content ? – david96develop Sep 11 '15 at 16:16
  • you can try to can call requestLayout() and then use my solution 2. – Bruce Lan Sep 11 '15 at 16:33
  • But in that case i have to extend the view Right ? , is there a way to avoid that ? – david96develop Sep 11 '15 at 16:41
  • Yes, you need to extend TextView and then override the onMeasure, and then you can save the getMeasuredWidth and the getMeasuredHeight in the custom textview. After then, you also implement the public method to get the getMeasuredWidth you saved in the custom textview. – Bruce Lan Sep 11 '15 at 17:04