1

EDIT --> Please, this is NOT a question WHY getWidth() / getHeight() return zero.

I have a Fragment inside an Activity. I am dynamically adding SubViews (red) to a LinearLayout (RowView, blue) in horizontal orientation that is a child of the Fragment (green). How many of those childviews (SubViews) are added to the LinearLayout is determined at runtime.

enter image description here

The SubViews must have a fixed width of 200dp. Therefore, when dynamically adding the SubViews to the Linearlayout, I want to check if there is enough space for another SubView, or if a new Row needs to be started. The width of the RowView should be variable, and is NOT necessarily equal to the screen size.

In order to check if there is enough space, I simply see if the combined width of all SubViews is smaller than the width of the Linearlayout - the width of one SubView. Inside my custom LinearLayout (RowView), this looks as follows:

public void addSubView(SubView v) {

        int childcount = getChildCount();
        int totalChildWidth = 0;

        for(int i = 0; i < childcount; i++) {
            totalChildWidth += getChildAt(i).getWidth(); 
        }

        if(totalChildWidth < getWidth() - 200) { // there is space left in this row
            addView(v);
        } 
    }

The problem simply is, that getWidth() of the LinearLayout, and getWidth() of already added SubViews return 0, and therefore, the check if there is enough space goes wrong.

The reason for that is that I am calling getWi´dtdh() when the Views (the UI) have not yet been rendered on the screen, so my question is when is the right time to call my addSubView() method? Currently, I am calling it when creating the Fragment, which is obviously wrong:

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

        View v = inflater.inflate(R.layout.fragment, container, false);

        RowView row = (RowView) v.findViewById(R.id.rowView);
        ArrayList<SubView> subViews = DBManager.getSubViewList(); // connects to a database and returns all available subviews

        for(int i = 0; i < subViews.size(); i++) {
            row.addSubView(subViews.get(i));
        }

        return v;
    }

So where to call my addSubView(...) method where it is ensured that getWidth() inside it will not return 0? And in general, when is the correct moment (which callback method, according to Activity lifecycle) for getWidth() or getHeight() of a View to be called, where it is ensured that they will not return 0?

What I have tried so far:

  • Call addSubView(...) of my RowView in Fragments onActivityCreated(...) --> doesn't work
  • Connect to the database inside the RowViwes onSizeChanged(...) method, and all addSubView(...) there --> doesn't work
  • Do it as described in the code above, but with a Handler with 500ms delay --> works, because UI is rendered, but is not a proper solution for me
Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
  • possible duplicate of [getWidth and getHeight are returning a zero](http://stackoverflow.com/questions/6145001/getwidth-and-getheight-are-returning-a-zero) – mah Nov 27 '13 at 15:04
  • Please show me where an answer of that question explains to me when it is the right moment to call getWidth() on a View, according to e.g. Activity lifecycle? – Philipp Jahoda Nov 27 '13 at 15:07
  • It should be clear from that page that there isn't anything related to the activity life cycle that makes it a certainty to be appropriate to read the layout, while also on that page use of `onDraw()` (not a part of the life cycle) is recommended. Between that possibility and the timer you suggest (which I've used before with success), you've exhausted what is available short of making OS level changes. – mah Nov 27 '13 at 15:16

1 Answers1

1

What you try to do is not working as the layouting isn't finished at the moment you want to know the width of the element. There are two solutions. The first one is to determine the actual width of your layout, which is ease in your case, as it is the actual screen width:

int width = getActivity().getResources().getDisplayMetrics().widthPixels

Use this value to determine how many of your subviews you can add in one row by converting the 200dp into pixel:

int viewWidth = (int) (200 * (getActivity().getResources().getDisplayMetrics().densityDpi / 160f));

Then you can calculate the maximal number of views for a row:

int maxViewsToAdd = (int) width/viewWidth;

The other solution is a globalLayoutListener, you can find a description here. But this seems not to work in all cases.

Community
  • 1
  • 1
Baschi
  • 1,128
  • 11
  • 14