Подтвердить что ты не робот

Жизненный цикл операции - получение уведомления о том, что макет завершен

У меня есть активность, в которой у меня есть три кнопки, расположенные рядом друг с другом. Я использовал подкласс Button, который изменит размер текста кнопки, чтобы предотвратить обтекание текста. Я хотел бы, чтобы 3 кнопки имели одинаковый размер текста. Для этого я намерен обнаружить кнопку с наименьшим размером текста и установить другие 2 кнопки в этот размер текста.

Проблема, с которой я сталкиваюсь, - это знать, когда Activity завершила процесс компоновки своих компонентов, чтобы я мог достоверно знать, что произошло изменение размера текста. Из документации для Android будет видно, что последнее уведомление в жизненном цикле - onResume(), но, похоже, макет еще не завершился на этом этапе. Есть ли способ получить уведомление о завершении макета активности?

4b9b3361

Ответ 1

Я сделал что-то подобное, используя Tree Observer. Возможно, вам придется немного поиграть с ним, чтобы найти, какой вид он должен быть прикреплен тоже, но это будет срабатывать, как только будет установлено представление. Оттуда вы можете получить размер текста и внести необходимые изменения.

mTestButton.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // make sure it is not called anymore 
        mTestButton.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        float size = mTestButton.getTextSize();
    }
});


EDIT:
Метод #removeGlobalOnLayoutListener устарел, но все еще действителен. Чтобы использовать как новый, так и старый метод, см. fooobar.com/questions/20225/....

Ответ 2

Из того, что я знаю, нет события или что-то, что говорит вам, что все загружено. То, что вы, возможно, можете сделать, это в конце метода oncreate запустить AsyncTask, который выполняется, пока ширина вашего последнего представления равна 0. Когда макет загружается, представления будут иметь фактический размер вместо 0, чтобы вы знали его загруженный. В обратном вызове из ASyncTask вы можете вычислить самую маленькую кнопку и определить шрифт.

Ответ 3

Методы обратного вызова жизненного цикла Activity и его окно/макет не связаны друг с другом. Тем не менее, вы гарантируете, что Button существует, пока вы манипулируете им после того, как вы вызвали setContentView.

Ответ 4

Возможно, вы могли бы установить OnLayoutChangeListener на своих кнопках (или в группе просмотра, содержащей кнопки), и изменить размер шрифта там? Я не уверен, что это вызвано до или после изменения макета вступили в силу...

Ответ 5

Вы можете попробовать переопределить Activity.onWindowFocusChanged(boolean), чтобы надежно получать уведомление, когда активность стала видимой. Затем вы можете предположить, что макет завершен. Одной из проблем, которые могут возникнуть при таком подходе, является активность, которая будет видна пользователю, и, таким образом, если текст кнопки будет изменен, тогда изменение размера будет кратковременно видимым для пользователя.

Ответ 6

Android выполнит макет в два шага, меру и макет. Поскольку вы просто хотите размер кнопки, вы можете использовать getMeasuredWidth вместо getWidth, так как это будет доступно ранее.

Я бы рекомендовал использовать LinearLayout вместо того, чтобы вручную определять ширину кнопок. Удостоверьтесь, что андроид: weightSum указан, особенно если вы собираетесь использовать макет не полной ширины.

<LinearLayout 
    ...
    android:orientation="horizontal"
    android:weightSum="3"
    >
    <Button 
        ...
        android:layout_weight="1"
        />
    <Button 
        ...
        android:layout_weight="1"
        />
    <Button 
        ...
        android:layout_weight="1"
        />
</LinearLayout>

Ответ 7

Чтобы узнать, когда макет представления закончен, возможно, я бы дал ему runnable в методе onCreate() моей активности, а затем вызвал эту runnable из View.onSizeChanged(). Он должен выглядеть как

public void onCreate() {
    view.setLayoutRunnable(new Runnable() {
    @Override
    public void run() {
        //do layout stuff...
    }
});

а затем сделайте следующее в своем представлении.

public Runnable myRunnable;
public void setLayoutRunnable(Runnable runner) {
    myRunnable = runner;
}

@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
    if (w > 0 && h > 0 && (w != oldw || h != oldh)) {
        if (myRunnable!= null) 
            myRunnable.run();
    }
}

Надеюсь, что это поможет.

Ответ 8

Я рисую изображения динамически и хотел установить размеры ImageViews LinearLayout, а затем использовать эти размеры. Поэтому мне нужно создать изображения после завершения макета.

Я использовал View.post(Runnable) в конце onCreate, а затем создал изображения в Runnable. Я немного экспериментировал и обнаружил, что onStart, onResume и onPostResume произошли до макета (ширина ImageView равнялась 0). Опубликованный Runnable был выполнен после всех из них и после компоновки, поскольку ширина была установлена.

public void run() {
    // acquire the ImageView
    if (image.getWidth() == 0)
        image.post( this );

    else {
        // create the images, initialize the ImageViews etc.
    }
}

Опубликованный Runnable предположительно отправляется в поток пользовательского интерфейса после процедур запуска. ImageViews запросит макеты, а запросы будут отправлены после Runnable. На всякий случай, я проверяю, была ли установлена ​​ширина и перезагрузка Runnable, если она отсутствует. После завершения инициализации Runnable снова не отправляется.

Ответ 9

Когда я пытаюсь сделать горизонтально уложенные кнопки, я просто даю им layout_width of wrap_parent, но даю им layout_weight из 1.

Таким образом, все они стараются занимать столько места, сколько доступно, равномерно распределенное родительским макетом.

Пример кода будет примерно таким, и я надеюсь, что это поможет:

<LinearLayout 
    android:id="@+id/buttons"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    >
    <Button 
        android:id="@+id/okButton"
        android:layout_height="wrap_content" 
        android:layout_width="wrap_content"
        android:text="OK"
        android:layout_weight="1"
        />
    <Button 
        android:id="@+id/cancelButton"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" 
        android:text="Cancel"
        android:layout_weight="1"
        />
</LinearLayout>

-serkan

Ответ 10

Вы можете использовать iswindow(). Обожаю это. Он будет вызываться непосредственно перед onPause().

Ответ 11

В соответствии с жизненным циклом активности макет считается завершенным, когда вызов onResume() вызывается. Это когда пользователю представлен экран. Таким образом, вы можете слепо делать вещи с помощью кнопок из этой функции.