Этот компонент (BackDrop) все еще находится в стадии разработки для библиотеки Компоненты материала Android по состоянию на 16 декабря 2018 .
Однако, если вы используете компоненты материалауже не так сложно реализовать свой собственный.Вам потребуется следующее:
Приведенное ниже решение выглядит следующим образом ...
В приведенном ниже примере используется фрагмент, Iопущу детали деятельности хостинга, потому что это не имеет отношения к вопросу / ответу.Тем не менее, вы можете сделать то же самое с деятельностью.Ваш файл макета фрагмента будет выглядеть следующим образом ...
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinatorLayout"
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">
<!--This the interface sitting behind the backdrop and shown when it is collapsed-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorPrimary"
android:padding="@dimen/activity_spacing">
<EditText
android:id="@+id/searchTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_search_primary_xlight_24dp"
style="@style/EditTextStyle.Inverse.Large.Light"
android:hint="@string/search_hint"/>
<EditText
android:id="@+id/datesFilterButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_calendar_primary_xlight_24dp"
style="@style/EditTextStyle.Inverse.Large.Light"
android:hint="@string/select_dates_hint"/>
</LinearLayout>
<!--This is the backdrop's content with a BottomSheetBehaviour applied to it-->
<LinearLayout
android:id="@+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_peekHeight="56dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<!--This is the backdrop's header with a title and icon-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:clickable="true"
android:background="@drawable/ic_list_header_background"
android:padding="@dimen/activity_spacing"
android:elevation="4dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/TextAppearance.Stems.Body2"
android:text="0 items(s)"/>
<ImageView
android:id="@+id/filterIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_filter_black_24dp"
android:layout_gravity="end"/>
</LinearLayout>
<!--And finally this is the body of the backdrop's content. You can add here whatever you need inside a view group (LinearLayout, RelativeLayout, SwipeRefreshLayout, ConstraintLayout, etc.)-->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorBackground">
<!--The content's body goes here-->
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Здесь есть пара вещей, о которых вам нужно знать.Во-первых, LinearLayout
, который находится за фоном, использует цвет colorPrimary
, который в точности совпадает с цветом фона Toolbar
... панель инструментов для ясности была опущена, она объявлена в действии хостинга (помните, это решение для фрагмента).
Тогда класс фрагмента будет выглядеть следующим образом ...
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
coordinatorLayout = (CoordinatorLayout)inflater.inflate(R.layout.fragment_hazards, container, false);
Context context = getContext();
if(context != null){
setTitle(context.getString(R.string.title_hazards));
}
filterIcon = coordinatorLayout.findViewById(R.id.filterIcon);
LinearLayout contentLayout = coordinatorLayout.findViewById(R.id.contentLayout);
sheetBehavior = BottomSheetBehavior.from(contentLayout);
sheetBehavior.setFitToContents(false);
sheetBehavior.setHideable(false);//prevents the boottom sheet from completely hiding off the screen
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);//initially state to fully expanded
filterIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleFilters();
}
});
return coordinatorLayout;
}
private void toggleFilters(){
if(sheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED){
sheetBehavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
}
else {
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
И это все, единственное, что вам нужно иметь в виду, этоэтот корневой макет должен быть CoordinatorLayout
и что BottomSheetBehaviour
должен применяться к непосредственному дочернему элементу корневого макета
Round Corners
Вы также заметите, что яне использовать CardView
в заголовке BackDrop, чтобы получить красивые закругленные углы, которые поставляются с CardView
.Это потому, что мне нужно только закруглить верхние углы, а реализация по умолчанию CardView
не позволяет вам явно устанавливать отдельные углы.Вместо этого я использовал старый добрый LinearLayout
и предоставил свой собственный фон для рисования (ic_list_header_background
).Вот xml-объявление об этом объекте рисования ...
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@color/colorBackground" />
<corners android:topLeftRadius="16dp" android:topRightRadius="16dp" />
</shape>
Ничего особенного, просто прямоугольная форма с выборочными закругленными углами (верхние)
Тень панели инструментов
Вы захотите удалить тень от панели инструментов, для этого вы можете установить ее высоту 0dp
или программно удалить поставщика контуров на родительском элементе AppBarLayout
, как показано ниже ...
appBarLayout.setOutlineProvider(null);
очевидно, это предполагает, что ваш Toolbar
находится внутри AppBarLayout
в соответствии с рекомендациями
Я надеюсь, что это действительно кому-то поможет, пока BackDrop Материального компонента все еще находится в стадии разработки.Это не идеально, потому что вы все еще связаны с функциональными возможностями, предоставляемыми компонентом BottomSheetBehaviour, который он довольно ограничен.Но если вы придирчивы или хотите проявить фантазию, я бы порекомендовал реализовать собственный BottomSheetBehaviour, расширив его по умолчанию
Отключение жеста смахивания пользователя
На основе Рекомендации по проектированию материалов , рекомендуется не использовать жесты смахивания на переднем слое фона
Не используйте жест смахивания на переднем слое, чтобы показать задний слой.
Однако по умолчанию BottomSheetBehaviour
не предоставляет никаких свойств или API для отключения жестов смахивания.Чтобы достичь этого, вам нужно реализовать свой собственный, расширив BottomSheetBehaviour
, переопределяя все методы, связанные с жестами.Вот пример, который я использую в одном из моих проектов (написан на Kotlin)
class GestureLockedBottomSheetBehavior<V: View>(context: Context, attributeSet: AttributeSet?) : BottomSheetBehavior<V>(context, attributeSet){
constructor(context: Context):this(context, null)
override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean = false
override fun onTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean = false
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
directTargetChild: View,
target: View,
axes: Int,
type: Int
): Boolean = false
override fun onNestedPreScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
target: View,
dx: Int,
dy: Int,
consumed: IntArray,
type: Int
) { }
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) { }
override fun onNestedFling(
coordinatorLayout: CoordinatorLayout,
child: V,
target: View,
velocityX: Float,
velocityY: Float,
consumed: Boolean
): Boolean = false
}
Даже если вы не знакомы с Kotlin, не должно быть трудно понять, что все, что я делаюпереопределяет кучу методов и возвращает false или ничего не делает, не вызывая аналога суперкласса
Затем, чтобы использовать этот класс GestureLockedBottomSheetBehavior
, вам необходимо заменить его в макете, как показано ниже ...
<LinearLayout
android:id="@+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_peekHeight="56dp"
app:layout_behavior="ui.behaviors.GestureLockedBottomSheetBehavior">
...
</LinearLayout>
Просто убедитесь, что полное имя задано в соответствии с пакетом, в котором находится пользовательский класс.