Когда правильный момент для вызова getWidth() / getHeight() в представлении?

РЕДАКТИРОВАТЬ -> Пожалуйста, это не вопрос, почему getWidth() / getHeight() возвращают ноль.

У меня есть фрагмент внутри деятельности. Я динамически добавляю SubViews (красный) к LinearLayout (RowView, синий) в горизонтальной ориентации, которая является дочерним элементом фрагмента (зеленый). Сколько из этих дочерних представлений (SubViews) добавляется в LinearLayout, определяется во время выполнения.

введите описание изображения здесь

Подвиды должны иметь фиксированную ширину 200dp. Поэтому при динамическом добавлении SubViews к Linearlayout я хочу проверить, достаточно ли места для другого SubView или нужно запустить новую строку. Ширина RowView должна быть переменной и НЕ обязательно равна размеру экрана.

Чтобы проверить, достаточно ли места, я просто вижу, меньше ли объединенная ширина всех SubViews, чем ширина Linearlayout - ширина одного SubView. Внутри моего пользовательского LinearLayout (RowView) это выглядит следующим образом:

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);
        } 
    }

Проблема просто в том, что getWidth() LinearLayout, и getWidth() из уже добавленных SubViews возвращает 0, и, следовательно, проверка, достаточно ли места, идет не так.

Причина этого заключается в том, что я вызываю getWi´dtdh(), когда Views (UI) еще не отображены на экране, поэтому мой вопрос в том, когда подходящее время для вызова моего метода addSubView()? В настоящее время я вызываю его при создании фрагмента, что явно неправильно:

    @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;
    }

Так, где вызвать мой метод addSubView(...), где гарантируется, что getWidth() внутри это не вернет 0? И вообще, когда правильный момент (какой метод обратного вызова, согласно жизненному циклу Activity) для getWidth() или же getHeight() вида, который будет вызван, где гарантируется, что они не вернут 0?

Что я уже пробовал:

  • Вызов addSubView(...) моего RowView в фрагментах onActivityCreated(...) -> не работает
  • Подключиться к базе данных внутри RowViwes onSizeChanged(...) метод и все addSubView(...) там -> не работает
  • Сделайте это, как описано в приведенном выше коде, но с обработчиком с задержкой 500 мс -> работает, потому что пользовательский интерфейс отображается, но не является для меня правильным решением

1 ответ

То, что вы пытаетесь сделать, не работает, так как верстка не закончена в тот момент, когда вы хотите узнать ширину элемента. Есть два решения. Первый - определить фактическую ширину вашего макета, что легко в вашем случае, так как это фактическая ширина экрана:

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

Используйте это значение, чтобы определить, сколько ваших подпредставлений вы можете добавить в одну строку, преобразовав 200dp в пиксель:

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

Затем вы можете рассчитать максимальное количество просмотров для строки:

int maxViewsToAdd = (int) width/viewWidth;

Другое решение - это globalLayoutListenerВы можете найти описание здесь. Но это, кажется, не работает во всех случаях.

Другие вопросы по тегам