7

I am trying to convert my Android app to Fragments to support multiple screen sizes and to use the new ICS tabs correctly. Previously I used the onWindowFocusChanged() method and ran the following code inside of it - basically this did some dynamic formatting of my layout after it was created.

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

LinearLayout theLayout = (LinearLayout)inflater.inflate(R.layout.tab_frag2_layout, container, false);

getWidthEditButton = (ImageButton) theLayout.findViewById(R.id.buttonEditPoints);
buttonAddPointsManual = (ImageView) theLayout.findViewById(R.id.buttonAddPointsManual);

linearPointsUsed = (LinearLayout) theLayout.findViewById(R.id.linearLayoutPointsUsed);

int paddingLeftForTracker = linearPointsUsed.getPaddingLeft();
int paddingRightForTracker = getWidthEditButton.getWidth();

linearPointsUsed.setPadding(paddingLeftForTracker, 0, paddingRightForTracker, 0);
}

Now that I have moved to Fragments and for some reason my paddingRightForTracker returns 0. I ran into an issue previously where I was trying to get width too early, hence my move to onWindowFocusChanged previously, but that is not available to Fragments. The strange thing is that paddingLeftForTracker actually returns a non-zero value.

If I set paddingRightForTracker manually, the change takes place so I know the code is running. Just can't figure out why my getWidth is returning 0.

Any help would be greatly appreciated.

mattdonders
  • 1,328
  • 1
  • 19
  • 42

2 Answers2

22

You could try doing it in onActivityCreated(). So, you would save a reference to those views in onCreateView, and then access them in onActivityCreated(). I think the view isn't completed created when you're trying to access it, which is why it returns no width.

http://developer.android.com/reference/android/app/Fragment.html#onActivityCreated(android.os.Bundle)


Ok, so I found out about another way to get the width. I, too, cannot get a button width on neither onViewCreated, onCreateView, nor onResume. I found this, tried it, and it's returning a value, so maybe it'll work for you!

How to get height and width of Button

ViewTreeObserver vto = button.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
        width = button.getWidth();
        height = button.getHeight(); 
    }
});

FYI, I ran this code in onResume, so I'm not exactly sure where else it could work.

Community
  • 1
  • 1
leenephi
  • 900
  • 5
  • 13
  • Is getPaddingLeft different than getWidth? Shouldn't they either both return 0 or both return a non-zero value? That's my only issue here is that I get a non-zero value from getPaddingLeft, but not from getWidth. So if the View wasn't drawn yet I shouldn't get either value. Maybe I am mistaken though. – mattdonders Jul 23 '12 at 13:07
  • 1
    getPaddingLeft should only be returning a value that is already set. When you say it's returning a nonzero value, is it the value you have set in XML? (What does your initial layout look like?) – leenephi Jul 23 '12 at 14:13
  • Oh oh oh, I actually didn't think about that. I do have a value set in XML for paddingLeft of the LinearLayout hence why it returns a non-zero value even though the layout hasn't been drawn yet. So based on your advice above I will try to implement the code in that function - thank you. – mattdonders Jul 23 '12 at 14:22
  • Quick question though - do you know if onActivityCreated can be accessed within something that extends a Fragment rather than extending an Activity? – mattdonders Jul 23 '12 at 18:50
  • Yup. onActivityCreated() is a Fragment method, if you copy that link I posted up there and make sure to enter in the end parenthesis, it'll take you right to it. It's called after onCreateView() and before onStart() – leenephi Jul 23 '12 at 19:20
  • So I tried `int paddingRightForTracker = buttonEditPoints.getWidth();` in `public void onActivityCreated(Bundle savedInstanceState)` and I still get a width of 0. FYI: `buttonEditPoints = (ImageButton) theLayout.findViewById(R.id.buttonEditPoints);` is declared in onCreateView so it does have an assignment. – mattdonders Jul 24 '12 at 13:58
  • This is perfect - thank you so much for your help. Just out of curiosity, what is a ViewTreeObserver? – mattdonders Jul 24 '12 at 16:20
  • http://developer.android.com/reference/android/view/ViewTreeObserver.html A view tree observer is used to register listeners that can be notified of global changes in the view tree. Such global events include, but are not limited to, layout of the whole tree, beginning of the drawing pass, touch mode change. It's just a bunch of callbacks on the entire tree of the view. In this case, it gets a callback when the view/visibility of the button changes. – leenephi Jul 24 '12 at 16:39
  • This has a problem, it is being called multiple times. – Moisés Olmedo Jul 10 '13 at 22:55
  • The code snippet from this answer worked for me in my Fragment's `onCreateView()` method. – ban-geoengineering Jun 24 '15 at 15:21
1

This works for me and it looks cleaner (I am also using lambda but it's not required):

v.post(() -> {
        int width = v.getWidth();
        doSomething(width>300);
    });
TacoEater
  • 2,115
  • 20
  • 22