ProgressBar под панелью действий

79

Резюме вопроса: как сделать ProgressBarвстроенное приложение ActionBar, как в приложении Chrome?

Подробности: посмотрите на этот снимок экрана из Chrome:

Скриншот Chrome для Android

Я хочу создать панель действий именно так. Прямо под панелью действий находится панель ProgressBar, которая заполняется в зависимости от загрузки страницы. Я видел этот пример во многих приложениях, таких как Feedly, но мне не удалось создать свою собственную реализацию. Я пробовал использовать собственные API Android для его создания:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Request Permission to display the Progress Bar...
    this.requestWindowFeature(Window.FEATURE_PROGRESS);
            this.setWindowContentView(R.layout.activity_main)
    super.onCreate(savedInstanceState);

    this.setProgressBarIndeterminate(true);
}

Но этот код только заставляет ProgressBar отображаться над панелью действий, например:

Скриншот моего приложения

Итак, как я могу сделать так, чтобы ProgressBar отображался под панелью действий, как в приложении Chrome?

Zubietaroberto
источник
возможный дублирующийся вопрос этого ответа: stackoverflow.com/a/10755545/794088
petey
вы уже нашли решение?
Эрик
скриншоты для моей бабушки
Илья Еремин

Ответы:

7

Теперь это собственное поведение, которое можно получить с помощью SwipeRefreshLayout .

Вы можете обернуть свой прокручиваемый вид с помощью a, SwipeRefreshLayoutа затем вам просто нужно прослушать события onRefresh :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    swipeLayout.setOnRefreshListener(this);
    swipeLayout.setColorScheme(android.R.color.holo_blue_bright, 
            android.R.color.holo_green_light, 
            android.R.color.holo_orange_light, 
            android.R.color.holo_red_light);
}


@Override public void onRefresh() {
    new Handler().postDelayed(new Runnable() {
        @Override public void run() {
            swipeLayout.setRefreshing(false);
        }
    }, 5000);
}

В этом блоге можно найти красивое и простое руководство .

AlexGuti
источник
56

Я не был полностью удовлетворен принятым ответом выше, поэтому я сам провел дополнительное исследование.

Уловка, которую, как мне кажется, они использовали, заключалась в том, что они извлекли вид сверху в вызванной иерархии представлений DecorViewи добавили туда индикатор выполнения. Таким образом, индикатор выполнения будет отображаться как над панелью действий, так и над областью содержимого. Обратите внимание, что ответ SD помещает индикатор выполнения в область содержимого и «крадет» пространство у фактического содержимого, что может привести к неожиданным результатам.

Примеры скриншотов этой реализации:

Индикатор

ProgressBarIndeterminate

Код

Просто поместите этот код в onCreateметод какой-либо активности, и он должен работать:

// create new ProgressBar and style it
final ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
progressBar.setProgress(65);

// retrieve the top view of our application
final FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
decorView.addView(progressBar);

// Here we try to position the ProgressBar to the correct position by looking
// at the position where content area starts. But during creating time, sizes 
// of the components are not set yet, so we have to wait until the components
// has been laid out
// Also note that doing progressBar.setY(136) will not work, because of different
// screen densities and different sizes of actionBar
ViewTreeObserver observer = progressBar.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        View contentView = decorView.findViewById(android.R.id.content);
        progressBar.setY(contentView.getY() - 10);

        ViewTreeObserver observer = progressBar.getViewTreeObserver();
        observer.removeOnGlobalLayoutListener(this);
    }
});

Вы можете поиграть с аргументом высоты LayoutParams, чтобы установить progressBar шире или уже, но вам, возможно, придется настроить -10смещение.

Укладка

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

TL; DR: создайте файл progress_horizontal_holo_no_background_light.xmlи вставьте его:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/secondaryProgress">
        <scale android:scaleWidth="100%"
               android:drawable="@drawable/progress_secondary_holo_light" />
    </item>

    <item android:id="@android:id/progress">
        <scale android:scaleWidth="100%"
               android:drawable="@drawable/progress_primary_holo_light" />
    </item>

</layer-list>

Скопируйте соответствующие чертежи .png из sdk/platforms/android-xx/data/res/drawable-xxx/в свой проект, а затем в код вы можете добавить:

progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));

Дополнительно: неопределенный индикатор выполнения

Версии неопределенных индикаторов выполнения до KitKat довольно уродливы и медлительны. Вы можете скачать новый плавный прогрессБар под названием ButteryProgressBar. Просто найдите его в Google (я не могу публиковать больше ссылок, потому что я здесь новичок: [), добавьте класс в свой проект, и вы можете просто заменить предыдущий ProgressBar этим кодом и получить четкую неопределенную полосу выполнения:

final ButteryProgressBar progressBar = new ButteryProgressBar(this);
progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));

Вам также может потребоваться упростить этот код:

final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);
try {
    mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,
            c.getResources().getColor(android.R.color.holo_blue_light));
    mSolidBarHeight = ta.getDimensionPixelSize(
            R.styleable.ButteryProgressBar_barHeight,
            Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));
    mSolidBarDetentWidth = ta.getDimensionPixelSize(
            R.styleable.ButteryProgressBar_detentWidth,
            Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));
} finally {
    ta.recycle();
}

к этому коду:

mBarColor = c.getResources().getColor(android.R.color.holo_blue_light);
mSolidBarHeight = Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity);
mSolidBarDetentWidth = Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity);

Надеюсь, я помог :)

Антимонит
источник
Метод removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener) из типа ViewTreeObserver устарел
Frozen Crayon
@ArjunU. что мы должны использовать вместо этого>
Патрик Гейер
@PatrickGeyer см stackoverflow.com/questions/16189525/...
Замороженные Crayon
Я тестировал неопределенный индикатор выполнения ( ButteryProgressBar), ActionBarActivityно он не работает. Как я могу поставить неопределенный индикатор выполнения под ActionBar/Toolbar? Это макет, который я использую: stackoverflow.com/a/26440880/1480019
user1480019
2
@GerritHoekstra: Если getSupportActionBar().getHeight()функция работает, вы почти у цели . progressBar.setY()Функция устанавливает положение относительно верхней части экрана, в том числе в строке состояния. Итак, что вам нужно сделать, так это setY(supportActionBarHeight + Math.ceil(25 * context.getResources().getDisplayMetrics().density)). Строка состояния имеет высоту 25 пикселей (mdpi) и масштабируется с более высокой плотностью (hdpi / xhdpi / ...). Попробуйте и скажите, работает ли это.
Антимонит
25

Расширьте Activity из следующего класса, чтобы наверху (под ActionBar) каждого из них был ProgressBar, а также getProgressBar()метод:

Родительский класс:

public abstract class ProgressActivity extends Activity {
    private ProgressBar mProgressBar;

    @Override
    public void setContentView(View view) {
        init().addView(view);
    }

    @Override
    public void setContentView(int layoutResID) {
        getLayoutInflater().inflate(layoutResID,init(),true);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        init().addView(view,params);
    }

    private ViewGroup init(){
        super.setContentView(R.layout.progress);
        mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);
        return (ViewGroup) findViewById(R.id.activity_frame);
    }

    protected ProgressBar getProgressBar(){
        return mProgressBar;
    }
}

Макет (progress.xml):

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
    android:layout_width="match_parent" android:layout_height="match_parent">
<ProgressBar android:id="@+id/activity_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-8dp"
    style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
    />
  <FrameLayout android:id="@+id/activity_frame"
      android:layout_width="match_parent"
      android:layout_height="fill_parent"
      />
</LinearLayout>
SD
источник
1
Это работает ... по большей части. ProgressBar выглядит отдельно от панели действий. Мне пришлось добавить в android:layout_marginTop="-8dp"ProgressBar, чтобы имитировать эффект «тени». Но для этого метода, вероятно, более эффективно добавить его непосредственно в основной макет. Но теперь все работает по назначению. Спасибо за взлом.
zubietaroberto 05
@zubietaroberto Да, вы можете добавить его в основной макет, если вы используете его только для одного действия. Если вы хотите, чтобы эта функция была у нескольких действий, вы можете просто расширить класс, показанный выше.
SD
1
Это работает для меня, но индикатор выполнения отображается под хостом вкладок, как я могу сделать его над хостом вкладок и под панелью действий?
DeckyFx 06
4

Я скомпилировал код из этого потока, а также из других потоков в StackOverflow и создал проект, который можно использовать для реализации ButteryProgessbar, а также «потяните вниз, чтобы обновить». https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh

Не стесняйтесь использовать код в своем приложении.

Большое вам спасибо, ребята.

Шантану Пол
источник
3

Пожалуйста, используйте приведенный ниже код. просто используйте один стиль по умолчанию в индикаторе выполнения какstyle="?android:attr/progressBarStyleHorizontal"

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <ProgressBar 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:indeterminate="true"

        />

</RelativeLayout>
Ранг
источник
0

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

Для начала используйте панель действий наложения, а затем установите для фона рисования значение «null», чтобы панель действий наложения была прозрачной.

Теперь в макете действия установите верхнее поле для корневого представления на «высоту панели действий». Это можно сделать следующим образом.

<RelativeLayout
    ...
    android:layout_marginTop="?android:attr/actionBarSize" />

Теперь действие не будет скрывать содержимое вашей активности.

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

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

user2405598
источник