Розмітка координатора за допомогою панелі інструментів у фрагментах або діяльності


94

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

Тож з цим, чи слід пересувати панель інструментів до кожного фрагменту? Якщо це так, я повинен встановлювати supportActionBar кожного разу, коли я показую фрагмент, а також маю посилання на активність у фрагменті, що зводить нанівець незалежний характер фрагментів. Якщо я залишаю панель інструментів у «Діяльності» наодинці, мені потрібно визначити кілька макетів для кожного типу поведінки у кожному фрагменті. Який буде найкращий підхід?


1
Привіт, ти знайшов рішення?
SERG

2
для мого поточного проекту я вирішив дотримуватися панелі інструментів в Activity і робити належну анімацію, коли це потрібно. Але це трохи заплутано. Я спробував використовувати панель інструментів у кожному фрагменті, і вона працює нормально, але анімувати панель інструментів між переходами фрагментів складніше, і я навіть не знаю, чи можливо це, оскільки я не маю великого досвіду з анімацією переходів фрагментів.
mobilepotato7

будь-які оновлення чи кращі рішення щодо цього зараз?
Сагар Наяк,

Відповіді:


56

Як на мене, це здається занадто дивним, коли в кожному фрагменті є панель додатків та панель інструментів. Тож я вибрав активність однієї панелі додатків із панеллю інструментів.

Щоб вирішити цю проблему за допомогою CoordinatorLayout, вам доведеться встановити іншу поведінку вашого FrameLayout(або будь-якого іншого макета), який повинен містити фрагменти кожного фрагмента, який ви хочете замінити поведінкою за замовчуванням.

Припустимо, що ваша поведінка за замовчуванням така app:layout_behavior="@string/appbar_scrolling_view_behavior"

Тоді у вашому fragment_activity_layout.xml у вас може бути щось подібне:

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:id="@+id/dashboard_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.Toolbar"
            app:layout_scrollFlags="scroll|enterAlways"/>
    </android.support.design.widget.AppBarLayout>

    <FrameLayout
        android:id="@+id/dashboard_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

І в кожному фрагменті, який ви хочете не реалізовувати, app:layout_behavior="@string/appbar_scrolling_view_behavior"вам доведеться замінити onAttachі onDetachметоди, які змінять поведінку вашого FrameLayout:

CoordinatorLayout.Behavior behavior;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if(behavior != null)
        return;

    FrameLayout layout =(FrameLayout) getActivity().findViewById(R.id.dashboard_content);
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) layout.getLayoutParams();

    behavior = params.getBehavior();
    params.setBehavior(null);

}

@Override
public void onDetach() {
    super.onDetach();
    if(behavior == null)
        return;

    FrameLayout layout =(FrameLayout) getActivity().findViewById(R.id.dashboard_content);
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) layout.getLayoutParams();

    params.setBehavior(behavior);

    layout.setLayoutParams(params);

    behavior = null;
}

Після цього CoordinatorLayout не згортатиме панель додатків тощо і дозволить макети фрагментів мати повний зріст.


Хороший, доведеться спробувати це і подивитися, чи це спрощує ситуацію. Дякую.
mobilepotato7

Якщо ви знайдете щось простіше - дайте мені знати. Я думаю, що можна змінити поведінку координатора в будь-який момент протягом життєвого циклу фрагментів (наприклад, у вас зазвичай є переробник із деякими речами, але в рідкісних випадках він може бути порожнім, і onLoadFinishedви будете знати, що лише після завантажувача можливо, люблю показувати зображення в центрі, що повідомляє, що тут нічого немає, як у додатку Inbox), але я ще не пробував цього. Можливо, пізніше сьогодні.
Клаус Шварц

Добре, це працює досить добре. Я створив помічника, який піклується про увімкнення / вимкнення координатора, коли це доречно, тому я просто телефоную enableCoordinator(Activity activity)/ disableCoordinator(Activity activity)з фрагментів.
Клаус Шварц

Де твій помічник, @ КлаусШварц? Коли ти називаєш це?
santhyago

1
@santhyago In the Fragment
Клаус Шварц

8

Ось моє рішення

<!-- Put your fragment inside a Framelayout and set the behavior for this FrameLayout -->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <!-- Your fragment -->
    <include layout="@layout/content_main" />

</FrameLayout>

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>


1

Це справді гарне запитання: чи потрібно тим Toolbar, хто повинен діяти так, як ActionBarщоб утримувати в a Activityчи a Fragment? Дослідивши різні запитання та документацію, я не зміг знайти рішення, яке охоплює всі випадки. Тому насправді залежить від вашої ситуації, яким шляхом піти.

Випадок 1: Панель інструментів повинна замінювати ActionBar

Якщо панель інструментів повинна вести себе як звичайна панель дій (або якщо час від часу відображається максимум 1 фрагмент), я думаю, найкращим / найпростішим способом є використання традиційної Activitiesтам власної панелі інструментів і розміщення вашого фрагмента там. Таким чином, вам не доведеться турбуватися про те, коли яка панель інструментів повинна відображатися.

Змінити ActionBar (-behaviour) з Fragments також можливо, але я б не рекомендував цього, оскільки це змушує вас відстежувати, який Fragment змінив ActionBar коли. Я навіть не знаю, чи можна встановити ActionBar кілька разів.

Випадок 2: Кожен фрагмент повинен мати власну (частину) панелі інструментів

Ви також можете помістити різні окремі панелі інструментів у різні фрагменти за їхніми власними діями. Таким чином ви можете відображати різні фрагменти поруч один з одним - кожен зі своїми діями на своїй панелі інструментів - і припускати, що це 1 панель інструментів (можливо, як додаток Gmail, хоча я не впевнений). Однак це означає, що вам доведеться надувати ці панелі інструментів самостійно, але це не повинно бути дуже складно.

Сподіваюся, це допоможе зробити вибір.

(Вибачте, якщо я допустив (мовні) помилки)


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