Использование BottomSheetBehavior с внутренним CoordinatorLayout
библиотека поддержки дизайна v. 23.2
ввел BottomSheetBehavior
, что позволяет детям координатора действовать как нижние листы (представления, перетаскиваемые из нижней части экрана).
то, что я хотел бы сделать, это иметь,как вид нижнего листа, следующий вид (типичный координатор + сворачивающий материал):
<CoordinatorLayout
app:layout_behavior=“@string/bottom_sheet_behavior”>
<AppBarLayout>
<CollapsingToolbarLayout>
<ImageView />
</CollapsingToolbarLayout>
</AppBarLayout>
<NestedScrollView>
<LinearLayout>
< Content ... />
</LinearLayout>
</NestedScrollView>
</CoordinatorLayout>
к сожалению, представления нижнего листа должны реализовывать вложенную прокрутку, или они не получат события прокрутки. Если вы попробуете с основным а затем загрузите это представление в качестве нижнего листа, вы увидите, что события прокрутки действуют только на" листе " бумаги, с некоторым странным поведением, как вы можете видеть, если продолжаете читать.
Я уверен, что это может быть обработано подклассами CoordinatorLayout
, или даже лучше, подклассов BottomSheetBehavior
. Ты хоть намекни?
мысли
-
requestDisallowInterceptTouchEvent()
следует использовать, чтобы украсть события у родителя в некоторых условия:- когда
AppBarLayout
смещение > 0 - когда
AppBarLayout
offset is == 0, но мы прокручиваем вверх (подумайте об этом на секунду, и вы увидите)
- когда
первое условие можно получить, установив
OnOffsetChanged
во внутреннюю панель приложений;-
второй требует некоторой обработки событий, например:
switch (MotionEventCompat.getActionMasked(event)) { case MotionEvent.ACTION_DOWN: startY = event.getY(); lastY = startY; userIsScrollingUp = false; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: userIsScrollingUp = false; break; case MotionEvent.ACTION_MOVE: lastY = event.getY(); float yDeltaTotal = startY - lastY; if (yDeltaTotal > touchSlop) { // Moving the finger up. userIsScrollingUp = true; } break; }
вопросы
излишне Слушай, я не могу сейчас это сделать. Я не могу поймать события, когда условия выполнены, и не поймать их в других случаях. На рисунке ниже вы можете увидеть, что происходит со стандартным CoordinatorLayout:
лист отклоняется при прокрутке вниз на панели приложений, но не при прокрутке вниз на вложенном содержимом. Кажется, что вложенные события прокрутки не распространяются на поведение координатора;
существует также проблема с внутренней панелью приложений: вложенное содержимое прокрутки не следует за панелью приложений при ее сворачивании..
у меня настройка пример проекта на github что показывает эти проблемы.
просто чтобы быть ясным, желаемое поведение:
правильное поведение панелей приложений / видов прокрутки внутри листа;
когда лист растет, он может свернуться при прокрутке вниз, но только если внутренняя панель приложений полностью расширена слишком. Прямо сейчас он рушится без учета состояния appbar, и только если вы перетащите appbar;
когда лист свернут, прокрутите вверх жесты расширят его (без эффекта на внутренней панели приложений).
пример из приложения "Контакты" (который, вероятно, не использует BottomSheetBehavior, но это то, что я хочу):
6 ответов
Я, наконец, выпустил свою реализацию. Найти его на Github или непосредственно из jcenter:
compile 'com.otaliastudios:bottomsheetcoordinatorlayout:1.0.0’
все, что вам нужно сделать-это с помощью BottomSheetCoordinatorLayout
как корневой вид для нижнего листа. Он автоматически раздувает рабочее поведение для себя, поэтому не беспокойтесь об этом.
Я использую это в течение длительного времени, и у него не должно быть проблем с прокруткой, поддерживает перетаскивание ABL и т. д.
Я просто следил за тем, как вы задали вышеуказанный вопрос, и придумал решение, которое может потребовать больше объяснений.Пожалуйста, следуйте вашему образцу кода и интегрировать дополнительную часть в xml, чтобы сделать его вести себя как BottomSheeet поведение
<CoordinatorLayout>
<AppBarLayout>
<Toolbar
app:layout_collapseMode="pin">
</Toolbar>
</AppBarLayout>
<NestedScrollView
app:layout_behavior=“@string/bottom_sheet_behavior” >
<include layout="@layout/items" />
</NestedScrollView>
<!-- Bottom Sheet -->
<BottomSheetCoordinatorLayout>
<AppBarLayout
<CollapsingToolbarLayout">
<ImageView />
<Toolbar />
</CollapsingToolbarLayout>
</AppBarLayout>
<NestedScrollView">
<include layout="@layout/items" />
</NestedScrollView>
</BottomSheetCoordinatorLayout>
</CoordinatorLayout>
Примечание : решение, которое сработало для меня, уже объяснено в последнем комментарии вашего вопроса
лучше explantion : https://github.com/laenger/BottomSheetCoordinatorLayout
Если первый ребенок nestedscroll
этого возникает ряд других проблем. Это решение исправлено моя проблема, я надеюсь, также исправить вашу.
<CoordinatorLayout
app:layout_behavior=“@string/bottom_sheet_behavior”>
<AppBarLayout>
<CollapsingToolbarLayout>
<ImageView />
</CollapsingToolbarLayout>
</AppBarLayout>
</LinearLayout>
<NestedScrollView>
<LinearLayout>
< Content ... />
</LinearLayout>
</NestedScrollView>
</LinearLayout>
</CoordinatorLayout>
старайтесь не использовать NestedScrollView
С LinearLayout
, это также вызывает проблемы в моем приложении. Просто используйте только LinearLayout
вместо этого отлично работает для меня.
попробуйте следующее:
<CoordinatorLayout
app:layout_behavior=“@string/bottom_sheet_behavior”>
<AppBarLayout>
<CollapsingToolbarLayout>
<ImageView />
</CollapsingToolbarLayout>
</AppBarLayout>
<LinearLayout>
<!--don't forget to addd this line-->
app:layout_behavior="@string/appbar_scrolling_view_behavior">
< Content ... />
</LinearLayout>
Я следил за первоначальным тестовым проектом GitHub laenger по этой проблеме, и я рад поделиться с вами решением некоторых из его проблем, так как мне тоже нужно было это поведение в моем приложении.
это решение его вопроса : панель инструментов иногда рушится слишком рано
чтобы предотвратить это, вам нужно создать свой пользовательский AppBarLayout.Behavior
, так как это когда вы прокручиваете вверх, все еще перетаскивая это AppBarLayout.behavior
получает движение прокрутки. Нам нужно определить, находится ли он в STATE_DRAGGING и просто возврат, чтобы избежать преждевременного скрытия / сворачивания панели инструментов.
public class CustomAppBarLayoutBehavior extends AppBarLayout.Behavior {
private CoordinatorLayoutBottomSheetBehavior behavior;
public CustomAppBarLayoutBehavior() {
}
public CustomAppBarLayoutBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
behavior = CoordinatorLayoutBottomSheetBehavior.from(parent);
return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) {
if(behavior.getState() == CoordinatorLayoutBottomSheetBehavior.STATE_DRAGGING){
return;
}else {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
}
@Override
public void setDragCallback(@Nullable DragCallback callback) {
super.setDragCallback(callback);
}
}
это может быть хорошим началом, как мы решаем другие вопросы:
панель инструментов не может быть свернута через перетаскивания
макет главного координатора потребляет некоторую прокрутку
Я на самом деле не хороший пользователь/анимационный человек, но hardwork иногда окупает понимание кода, находя правильную функцию обратного вызова/переопределения для реализации.
как поведение appbarlayout
<android.support.design.widget.AppBarLayout
android:id="@+id/bottom_sheet_appbar"
style="@style/BottomSheetAppBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="your.package.CustomAppBarLayoutBehavior">
макет для полного экрана макета appbar выглядит следующим образом: -
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="@dimen/detail_backdrop_height"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum" />
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/card_margin"
android:layout_marginLeft="@dimen/card_margin"
android:layout_marginRight="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Friends"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum" />
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/card_margin"
android:layout_marginLeft="@dimen/card_margin"
android:layout_marginRight="@dimen/card_margin">
<LinearLayout
style="@style/Widget.CardContent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Related"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cheese_ipsum" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
android:src="@drawable/ic_discuss"
android:layout_margin="@dimen/fab_margin"
android:clickable="true"/>
и после этого вы должны реализовать AppBarLayout.OnOffsetChangedListener в вашем классе и установить смещение экрана.