Запретить прокрутку RecyclerView в AppBarLayout до того, как AppBarLayout будет свернут
Я создаю заголовок RecyclerView
с заголовком, где заголовок сжимается при прокрутке вверх по RecyclerView
. Я могу достичь этого очень близко к макету ниже, с прозрачными AppBarLayout
и MyCoolView
, которые являются заголовком. Эффект параллакса отлично работает.
Однако, если заголовок все еще отображается и я бросаю RecyclerView
, RV медленно прокручивается вверх, а некоторые элементы находятся под панелью инструментов, пока RV не достигнет вершины представления. Я играл с scrollFlags
, но не достиг желаемого результата. Любые предложения о том, как улучшить опыт броска, чтобы предметы не обрезались?
Посмотрите видео и посмотрите, когда его разворачивается --- https://www.dropbox.com/s/jppd6m7zo41k23z/20160609_151309.mp4?dl=0
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout
android:background="#00000000">
<android.support.design.widget.CollapsingToolbarLayout
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<com.android.myapp.MyCoolView
app:layout_collapseMode="parallax"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView/>
</android.support.design.widget.CoordinatorLayout>
Ответы
Ответ 1
Возможное решение (непроверено). Добавьте OnOffsetChangedListener
в свой AppBarLayout
и обратите внимание на значение смещения. Сначала объявите это поле:
private boolean shouldScroll = false;
Затем, onCreate:
AppBarLayout appbar = findViewById(...);
appbar.addOnOffsetChangedListener(new OnOffsetChangedListener() {
@Override
void onOffsetChanged(AppBarLayout appbar, int offset) {
// Allow recycler scrolling only if we started collapsing.
this.shouldScroll = offset != 0;
}
});
Теперь добавьте прослушиватель прокрутки в свой RecyclerView. Всякий раз, когда он пытается выполнить прокрутку, верните прокрутку, если AppBarLayout все еще расширен:
RecyclerView recycler = findViewById(...);
recycler.addOnScrollListener(new OnScrollListener() {
@Override
void onScrolled(RecyclerView recycler, int dx, int dy) {
// If AppBar is fully expanded, revert the scroll.
if (!shouldScroll) {
recycler.scrollTo(0,0);
}
}
});
Возможно, это потребует некоторой настройки. Я вижу два вопроса:
- Возможное переполнение стека, если scrollTo() вызывает onScrolled() назад. Может быть решена с помощью логического значения или путем удаления/добавления прослушивателя прокрутки
- Возможно, вы хотите предотвратить прокрутку не только, когда AppBarLayout полностью развернута, но более широко, когда AppBarLayout не скомпенсирован. Это означает, что вам не нужно проверять
offset != 0
, а скорее на offset == appBarLayout.getTotalScrollRange()
. Я думаю.
Ответ 2
Возможно, вы можете добавить layout_behavior = "@string/appbar_scrolling_view_behavior" в свой RecylerView, как это.
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Ответ 3
Обтекание RecyclerView в FrameLayout решает эту проблему.
Вам также нужно переместить appbar_scrolling_view_behavior из RecyclerView в FrameLayout, чтобы он был правильно расположен под AppBarLayout.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<!--This RecyclerView MUST be wrapped in a FrameLayout-->
<!--This prevents the RecyclerView from going behind the AppBarLayout-->
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>