Жизненный цикл активности - получение уведомления о завершении макета - PullRequest
31 голосов
/ 06 июля 2011

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

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

Ответы [ 11 ]

28 голосов
/ 21 августа 2012

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

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


РЕДАКТИРОВАТЬ:
Метод #removeGlobalOnLayoutListener устарел, но все еще действителен. Чтобы использовать как новый, так и старый метод, см. этот ответ stackoverflow .

2 голосов
/ 07 июля 2011

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

1 голос
/ 20 июля 2012

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

0 голосов
/ 25 февраля 2013

Я рисую изображения динамически, и хотел установить размеры 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 больше не публикуется.

0 голосов
/ 24 августа 2012

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

0 голосов
/ 03 августа 2011

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

0 голосов
/ 03 августа 2011

Чтобы узнать, когда макет представления завершен, возможно, я бы дал ему 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();
    }
}

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

0 голосов
/ 18 июля 2011

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

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

<LinearLayout 
    ...
    android:orientation="horizontal"
    android:weightSum="3"
    >
    <Button 
        ...
        android:layout_weight="1"
        />
    <Button 
        ...
        android:layout_weight="1"
        />
    <Button 
        ...
        android:layout_weight="1"
        />
</LinearLayout>
0 голосов
/ 08 июля 2011

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

0 голосов
/ 07 июля 2011

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

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

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

<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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...