ProgressBar в ActionBar, например, в приложении GMail с обновлением

Я хотел бы сделать то же самое, что и приложение GMail на планшетах Honeycomb. Когда вы нажимаете кнопку «Обновить», значок заменяется ProgressBar. Как я могу это сделать?

Спасибо


person g123k    schedule 19.11.2011    source источник


Ответы (4)


Хорошо, я попробовал то, что предложил Cailean, но это не сработало для меня. Каждый раз, когда я хочу вернуть неопределенный прогресс к исходной кнопке, она становится недоступной для нажатия, я использовал этот макет для прогресса.

(actionbar_refresh_progress.xml)

<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="32dp"
             android:layout_height="32dp"
             android:layout_gravity="center"/>

и этот, чтобы вернуться к кнопке

(actionbar_refresh_button.xml)

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
           android:src="@drawable/ic_menu_refresh_holo_light"
           android:layout_height="wrap_content"
           android:layout_width="wrap_content"/>

мой код был:

private void setRefreshing(boolean refreshing) {
        this.refreshing = refreshing;
        if(refreshMenuItem == null) return;
        View refreshView;
        LayoutInflater inflater = (LayoutInflater)getActionBar().getThemedContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if(refreshing)
            refreshView = inflater.inflate(R.layout.actionbar_refresh_progress, null);
        else
            refreshView = inflater.inflate(R.layout.actionbar_refresh_button, null);

        refreshMenuItem.setActionView(refreshView);
    }

После просмотра исходного кода приложения Google IO, особенно этого файла: http://code.google.com/p/iosched/source/browse/android/src/com/google/android/apps/iosched./ui/HomeActivity.java я нашел другой более простой способ.

Сейчас мне нужен только первый макет с прогрессом и метод работы выглядит так:

private void setRefreshing(boolean refreshing) {
    this.refreshing = refreshing;
    if(refreshMenuItem == null) return;

    if(refreshing)
        refreshMenuItem.setActionView(R.layout.actionbar_refresh_progress);
    else
        refreshMenuItem.setActionView(null);
}

Определение пункта меню:

<item android:id="@+id/mail_refresh"
      android:title="Refresh"
      android:icon="@drawable/ic_menu_refresh_holo_light"
      android:showAsAction="always"/>

Я надеюсь, что кто-то найдет это полезным.

person Ivan G.    schedule 23.10.2012
comment
Код xml для actionbar_refresh_progress неправильно центрирует ProgressBar, как значок обновления. Тем не менее, перейдя по ссылке в приложение Google IO, вытащите непосредственно их actionbar_indeterminate_progress.xml, и это творит чудеса! code.google.com/p/iosched/ источник/обзор/android/разрешение/макет/ - person jcxavier; 25.03.2013

Gmail делает это, используя представление действий для состояния «выполняется обновление». Вызов обновления выполняется с помощью стандартной кнопки действия/пути onMenuItemSelected.

Когда вы входите в состояние обновления, установите для представления действия элемента меню обновления значение ProgressBar. (Создайте его программно, раздуйте его из макета, используйте actionLayout в меню xml, как предлагает CommonsWare, что бы вы ни предпочли.) Когда вы выходите из состояния обновления, установите представление действия обратно в нулевое, сохранив ссылку на него, чтобы вы могли установить это снова при следующем обновлении. Вы можете сохранить ссылку на MenuItem после того, как раздуете меню, и изменения в нем позже будут отражены в панели действий.

Этот подход имеет некоторые преимущества по сравнению с использованием постоянного представления действий и самостоятельного управления другими деталями изменения состояния. Представление действия полностью заменяет сгенерированную кнопку действия для пункта меню, эффективно блокируя возможность пользователя отправлять обычные события onMenuItemSelected для обновления, пока обновление уже выполняется. На одну вещь меньше, и представление действий может оставаться полностью неинтерактивным.

Вероятно, вы могли бы сделать что-то умное с ActionProvider в API 14+, чтобы немного больше инкапсулировать весь процесс, но вышеприведенное оказывается довольно простым.

person adamp    schedule 20.11.2011
comment
Я пробовал это, и это работает, за исключением того, что в Android 4.0.3 происходит сбой при изменении ориентации экрана. Это можно обойти? - person Buttink; 02.05.2012
comment
Но у вас есть трассировка стека исключений? Выглядит нормально на JellyBean. - person Ivan G.; 23.10.2012

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

Получив их, вызовите следующий фрагмент кода для переключения между двумя макетами. Вам решать, когда именно его нужно вызвать во второй раз, чтобы переключить его обратно на значок обновления.

private void doRefresh(Boolean refreshing, MenuItem menuItem)
{
    View refreshView;
    LayoutInflater inflater = (LayoutInflater) getActionBar().getThemedContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(refreshing)
        refreshView = inflater.inflate(R.layout.actionbar_indeterminate_progress, null);
    else
        refreshView = inflater.inflate(R.layout.refresh_icon, null);

    menuItem.setActionView(refreshView);

}
person Cailean    schedule 23.03.2012
comment
Идеально. Не могли бы вы показать свой макет refresh_icon.xml? Каждый раз, когда я надуваю ImageView, кнопка становится недоступной после вызова doRefresh(false, ...); - person Ivan G.; 23.10.2012
comment
Сделал так, почти все работает. Проблема в том, что мой диалог прогресса не анимируется. То становится видимым, то невидимым, но без анимации вообще. Не могу понять, почему. - person Duqe; 31.01.2014

Используйте следующий макет в качестве представления действия для элемента меню панели действий.

actionbar_refresh_progress.xml

<FrameLayout
    android:layout_height="wrap_content"
    android:layout_width="@dimen/abc_action_button_min_width"
    android:minWidth="@dimen/abc_action_button_min_width">
    <ProgressBar
        android:layout_width="32dp"
        android:layout_height="32dp"
         android:layout_gravity="center"
         style="?indeterminateProgressStyle" />
</FrameLayout>

потом

menuItem.setActionView(R.layout.actionbar_refresh_progress);

Работает с Gingerbread и остальными как шарм. Обратите внимание, что я использовал размер из панели действий поддержки для совместимости. Вместо этого вы можете использовать @dimen/action_button_min_width для ICS и выше.

Источник: https://code.google.com/p/iosched/source/browse/android/res/layout/actionbar_indeterminate_progress.xml?r=f4fd7504d43b25a75cc23b58d6f844f3553b48c3

person Ε Г И І И О    schedule 20.08.2013