Прогресбар під панеллю дій


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?


можна дублювати питання таку відповідь: stackoverflow.com/a/10755545/794088
Піті

Ви вже знайшли рішення?
Ерік

скріншоти для моєї бабусі
IlyaEremin

Відповіді:


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

Гарний і простий підручник можна знайти в цьому блозі .


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

Додатково: невизначений прогрес

Версії невизначених індикаторів виконання Pre-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 застарілий
Заморожений олівець

@ArjunU. що нам замість цього використовувати>
Патрік Гейєр


Я перевірив невизначений індикатор прогресу ( 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

Розширте Діяльність з наступного класу, щоб мати ProgressBar вгорі (нижче ActionBar) кожного, а також 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>

1
Це працює ... здебільшого. Панель ProgressB дійсно виглядає окремо від панелі дій. Мені довелося додати android:layout_marginTop="-8dp"до ProgressBar, щоб імітувати ефект "тіні". Але для цього методу, можливо, ефективніше додавати його до самого основного макета. Однак зараз це працює за призначенням. Дякую за хак.
zubietaroberto

@zubietaroberto Так, ви можете додати його до основного макета, якщо ви просто використовуєте його для однієї діяльності. Якщо ви хочете, щоб ця функція мала кілька функцій, ви можете просто розширити клас, показаний вище.
SD

1
Це працює для мене, але панель виконання відображається під хостом вкладок, як я можу зробити це над вкладкою та під панеллю дій?
DeckyFx

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

Ну, я зробив щось подібне для одного зі своїх додатків для домашніх тварин, і не впевнений, що це єдиний спосіб чи найкращий спосіб це зробити, але це точно працює.

Для початку використовуйте панель дій накладання, а потім встановіть фон, що малюється, на «нуль», щоб панель дій накладання був прозорим.

Тепер у макеті активності встановіть верхнє поле для кореневого подання на "висота панелі дій". Ви можете зробити це так.

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

Тепер дія не збирається приховувати будь-який вміст вашої активності.

Наступне, що вам потрібно зробити зараз, - це додати вид заголовка поверх вашого кореневого подання з висотою, такою ж, як і панель дій. Встановіть для нього колір тла. Тепер це буде колір вашої панелі дій, і оскільки панель дій ідеально вирівнюється зверху на цьому поданні заголовка.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.