Как reset позиция панели инструментов, управляемая координаторомLayout?
Приложение, над которым я работаю, состоит из ящика навигации, который реализован в Activity. Макет действия выглядит следующим образом:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<include
android:id="@+id/appbar"
layout="@layout/appbar" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/header_drawer"
app:menu="@menu/menu_nav">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
</FrameLayout>
Это очень распространенный шаблон, только часто изменяющееся значение - это фрагмент внутри макета контейнера.
Если какой-либо из фрагментов имеет прокручиваемый элемент, при прокрутке координаторLayout с радостью сделает переводы положения, включая панель инструментов /AppBarLayout.
Реальная проблема здесь в том, что при замене фрагмента позиция для панели инструментов остается той же, то есть, если панель инструментов скрыта, она останется такой
который не предназначен.
Результат:
Это:
![After scroll]()
Задерживается:
![Then change]()
Как можно reset позиция панели инструментов для этого случая?
EDIT:
Вероятно, ошибка, прослушиватель изменений смещения AppBarLayout вызывается только при повторном запуске приложения (нажмите кнопку "Назад" и откройте приложение) и перестанет получать вызов снова после интенсивного перехода.
Ответы
Ответ 1
В reset состояние прокрутки, просто получите объект AppBarLayout.Behavior
CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.coordinator);
AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
и вызовите метод onNestedPreScroll
вручную:
int[] consumed = new int[2];
behavior.onNestedPreScroll(coordinator, appbar, null, 0, -1000, consumed);
Если вы хотите reset плавно с анимацией, вы можете попробовать вместо onNestedFling
:
behavior.onNestedFling(coordinator, appbar, null, 0, -1000, true);
Ответ 2
Сначала получите подтверждение AppBarLayout в вашем MainActivity, затем в состоянии паузы заменяемого фрагмента используйте следующий метод, чтобы развернуть панель инструментов:
MainActivity.appbar.setExpanded(true,true);
И или закрыть панель инструментов:
MainActivity.appbar.setExpanded(false,true);
Второй параметр используется для прокрутки панели инструментов плавно.
Ответ 3
Обновите свою поддержку lib до v23, затем вы можете использовать:
appBarLayout.setExpanded(true/false);
public void setExpanded (boolean расширенный)
Устанавливает, расширяется ли этот AppBarLayout или нет, оживляя, если он уже был выложен.
Как и при прокрутке AppBarLayout, этот метод полагается на этот макет, являющийся прямым дочерним элементом CoordinatorLayout.
расширенный true, если макет должен быть полностью расширен, false, если он должен быть полностью скомпенсирован
Ответ 4
@razzledazzle В AppBarLayout хранятся onOffsetChangedListeners как WeakReferences, что означает, что они собирают мусор, когда это необходимо, например, когда вы делаете интенсивный бросок. См. Решение здесь:
https://code.google.com/p/android/issues/detail?id=176328
Ответ 5
Я использую эти коды до изменения фрагмента.
scrollingElement.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
scrollingElement.dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null);
scrollingElement.stopNestedScroll();
Ответ 6
Замените FrameLayout
android.support.design.widget.CoordinatorLayout
на android.support.design.widget.CoordinatorLayout
с помощью android.support.v4.widget.NestedScrollView
, и он автоматически выполнит задание без каких-либо других хаков.... так что это будет выглядеть так:
<android.support.design.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<include
android:id="@+id/appbar"
layout="@layout/appbar" />
</android.support.design.widget.CoordinatorLayout>
Ответ 7
Как сказано в документе said
AppBarLayout поддерживает
void setExpanded (логическое расширение, логическое анимация);
Устанавливает, будет ли этот AppBarLayout расширен или нет.
- расширенный логический: true, если макет должен быть полностью развернут, и false, если он должен быть полностью свернут
- animate boolean: нужно ли анимировать в новое состояние
Итак, сначала вам нужно
AppBarLayout appBarLayout = findViewById(R.id.appBarLayout);
затем разверните макет
appBarLayout.setExpanded(true, true); // with animation
appBarLayout.setExpanded(true, false); // without animation
и свернуть макет
appBarLayout.setExpanded(false, true); // with animation
appBarLayout.setExpanded(false, false); // without animation