Как имитировать поведение 3-х фазовых карт Google Maps?
Фон
Мне присваивается пользовательский интерфейс, который ведет себя аналогично тому, как Google Maps показывает нижний лист для найденного результата.
Он имеет три разные фазы:
- Нижнее содержимое. Верхняя область по-прежнему осязаема и не будет прокручивать что-нибудь внизу
- Полноэкранный контент, а верхняя область имеет большой заголовок.
- Полноэкранный контент, а верхняя область имеет только панель инструментов.
Вот что я говорю на Картах Google:
![Введите описание изображения здесь]()
Проблема
Thing is, нижний лист еще не является частью библиотеки дизайна (хотя он был запрошен, здесь).
Не только это, но интерфейс кажется довольно сложным и требует обработки панели инструментов на нескольких этапах.
Что я пробовал
Я нашел хорошую (достаточную) библиотеку для нижнего листа ( здесь) и добавил контент в его фрагмент-образец, чтобы иметь примерно те же взгляды, что и на примерах материального дизайна (например, здесь), чтобы иметь CollapsingToolbarLayout, который позаботится о фазах 2 + 3.
В приложении, которое я создаю, мне также нужно переместить значок при прокрутке, но я думаю, что если мне удастся с остальными, это должно быть легко.
Здесь код:
fragment_my.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
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="@dimen/detail_backdrop_height"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</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_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:clickable="true"
android:src="@android:drawable/ic_menu_send"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
MyFragment.java
public class MyFragment extends BottomSheetFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_my, container, false);
view.setMinimumHeight(getResources().getDisplayMetrics().heightPixels);
CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("AAA");
final Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
final AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NavUtils.navigateUpFromSameTask(getActivity());
}
});
final ImageView imageView = (ImageView) view.findViewById(R.id.backdrop);
Glide.with(this).load(R.drawable.cheese_1).centerCrop().into(imageView);
return view;
}
}
BottomSheetFragmentActivity.java
public final class BottomSheetFragmentActivity extends AppCompatActivity {
protected BottomSheetLayout bottomSheetLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_sheet_fragment);
bottomSheetLayout = (BottomSheetLayout) findViewById(R.id.bottomsheet);
findViewById(R.id.bottomsheet_fragment_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MyFragment().show(getSupportFragmentManager(), R.id.bottomsheet);
}
});
bottomSheetLayout.setShouldDimContentView(false);
bottomSheetLayout.setPeekOnDismiss(true);
bottomSheetLayout.setPeekSheetTranslation(200);
bottomSheetLayout.setInterceptContentTouch(false);
bottomSheetLayout.setDefaultViewTransformer(new BaseViewTransformer() {
@Override
public void transformView(final float translation, final float maxTranslation, final float peekedTranslation, final BottomSheetLayout parent, final View view) {
Log.d("AppLog", "translation:" + translation + " maxTranslation:" + maxTranslation + " peekedTranslation:" + peekedTranslation);
}
});
}
}
Это почти работает. Единственная проблема - переход от # 3 к # 2:
![введите описание изображения здесь]()
Вопрос
Что не так с кодом? Что я могу сделать для достижения требуемого поведения?
Ответы
Ответ 1
Примечание: прочитайте изменения внизу
ОК, я нашел способ сделать это, но мне пришлось изменить код нескольких классов, чтобы нижний лист знал о состоянии appBarLayout (расширенном или нет) и игнорировал прокрутку вверх если он не расширен:
BottomSheetLayout.java
Добавленные поля:
private AppBarLayout mAppBarLayout;
private OnOffsetChangedListener mOnOffsetChangedListener;
private int mAppBarLayoutOffset;
init() - добавлено:
mOnOffsetChangedListener = new OnOffsetChangedListener() {
@Override
public void onOffsetChanged(final AppBarLayout appBarLayout, final int verticalOffset) {
mAppBarLayoutOffset = verticalOffset;
}
};
Добавлена функция для установки appBarLayout:
public void setAppBarLayout(final AppBarLayout appBarLayout) {
if (mAppBarLayout == appBarLayout)
return;
if (mAppBarLayout != null)
mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);
mAppBarLayout = appBarLayout;
mAppBarLayout.addOnOffsetChangedListener(mOnOffsetChangedListener);
}
onDetachedFromWindow() - добавлено:
if (mAppBarLayout != null)
mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);
onTouchEvent() - добавлено:
...
if (bottomSheetOwnsTouch) {
if (state == State.EXPANDED && scrollingDown && mAppBarLayout != null && mAppBarLayoutOffset != 0) {
event.offsetLocation(0, sheetTranslation - getHeight());
getSheetView().dispatchTouchEvent(event);
return true;
}
...
Это были основные изменения. Теперь для того, что их устанавливает:
MyFragment.java
onCreateView() - добавлено:
mBottomSheetLayout.setAppBarLayout((AppBarLayout) view.findViewById(R.id.appbar));
Я также добавил эту функцию:
public void setBottomSheetLayout(final BottomSheetLayout bottomSheetLayout) {
mBottomSheetLayout = bottomSheetLayout;
}
Теперь это то, как активность сообщает фрагменту о appBarLayout:
final MyFragment myFragment = new MyFragment();
myFragment.setBottomSheetLayout(bottomSheetLayout);
myFragment.show(getSupportFragmentManager(), R.id.bottomsheet);
Теперь проект доступен на GitHub:
https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet
Надеюсь, у него нет никаких ошибок.
У решения есть ошибки, к сожалению, поэтому я не буду отмечать этот ответ как правильный:
- Он работает только на Android 6 и выше. Другие имеют странное поведение, показывающее нижний лист, расширенный за небольшую часть времени, каждый раз при его показе.
- Изменения ориентации не сохраняют состояние прокрутки вообще, поэтому я отключил его.
- Редкая проблема в том, что вы можете прокручивать содержимое нижнего листа, пока он все еще рухнул (внизу)
- Если клавиатура была показана раньше, нижний лист может оказаться полноэкранным, когда вы пытаетесь заглянуть.
Если кто-то может помочь с этим, пожалуйста.
Для проблемы №1 я попытался добавить исправление, установив видимость на INVISIBLE, когда нижний лист еще не заглянул, но он не всегда работает, особенно если отображается клавиатура.
Для проблемы №1 я нашел, как ее исправить, просто обернув (в "fragment_my.xml" ) координаторLayout с любым видом, который вы хотите использовать (я использовал FrameLayout) (я просто положил "View" ), как таковой:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--This full sized view, together with the FrameLayout above, are used to handle some weird UI issues on pre-Android-6 -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<...CollapsingToolbarLayout
...
Вероятно, он смутил нижний лист, когда у меня был координаторLayout, являющийся его представлением.
Я обновил проект, но все же, если есть способ получить более приятное решение, я хотел бы узнать об этом.
В последние месяцы Google опубликовал свой собственный класс bottomSheet, но, как я обнаружил, у него много проблем, поэтому я даже не могу его попробовать.
Ответ 2
БОЛЬШОЕ ОБНОВЛЕНИЕ
Потому что было 4 или 5 вопросов на одну и ту же тему, НО с РАЗНЫМИ требованиями, и я попытался ответить на все из них, но не вежливый администратор удалил/закрыл их, заставив меня создать заявку для каждой и изменив их на избегайте "копировать вставку", я дам вам ссылку на полный ответ, где вы сможете найти все объяснения о том, как получить полное поведение, например, Google Maps.
Отвечая на ваш вопрос
Как имитировать поведение 3-х фаз нижних листов Карт Google?
С библиотекой поддержки 23.x. x+ вы можете сделать это, изменив BottomSheetBehavior
по умолчанию, добавив еще одну статистику, выполнив следующие шаги:
- Создайте класс Java и расширьте его из
CoordinatorLayout.Behavior<V>
- Скопируйте код вставки из файла
BottomSheetBehavior
умолчанию в ваш новый. -
Измените метод clampViewPositionVertical
с помощью следующего кода:
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset);
}
int constrain(int amount, int low, int high) {
return amount < low ? low : (amount > high ? high : amount);
}
-
Добавить новое состояние:
public static final int STATE_ANCHOR_POINT = X;
-
Измените следующие методы: onLayoutChild
, onStopNestedScroll
, BottomSheetBehavior<V> from(V view)
и setState
(необязательно)
Я собираюсь добавить эти измененные методы и ссылку на пример проекта.
А вот как это выглядит:
![CustomBottomSheetBehavior]()
Ответ 3
Вы попробовали это?
http://android-developers.blogspot.in/2016/02/android-support-library-232.html?m=1
Здесь говорится, что мы можем просто указать поведение макета нижнего листа.
UPDATE:
В основном состояния ссылок -
Прикрепив BottomSheetBehavior к дочернему представлению CoordinatorLayout (например, добавив app: layout_behavior = "android.support.design.widget.BottomSheetBehavior" ), вы автоматически получите соответствующее сенсорное обнаружение для перехода между пятью состояниями:
STATE_COLLAPSED: this collapsed state is the default and shows just a portion of the layout along the bottom. The height can be controlled with the app:behavior_peekHeight attribute (defaults to 0)
STATE_DRAGGING: the intermediate state while the user is directly dragging the bottom sheet up or down
STATE_SETTLING: that brief time between when the View is released and settling into its final position
STATE_EXPANDED: the fully expanded state of the bottom sheet, where either the whole bottom sheet is visible (if its height is less than the containing CoordinatorLayout) or the entire CoordinatorLayout is filled
STATE_HIDDEN: disabled by default (and enabled with the app:behavior_hideable attribute), enabling this allows users to swipe down on the bottom sheet to completely hide the bottom sheet
Keep in mind that scrolling containers in your bottom sheet must support nested scrolling (for example, NestedScrollView, RecyclerView, or ListView/ScrollView on API 21+).
Если вы хотите получать обратные вызовы изменений состояния, вы можете добавить BottomSheetCallback:
// The View with the BottomSheetBehavior
View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setBottomSheetCallback(new BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
// React to state change
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// React to dragging events
}
});
В то время как BottomSheetBehavior фиксирует стойкий нижний лист, этот выпуск также предоставляет бит BottomSheetDialog и BottomSheetDialogFragment для заполнения случая использования модальных нижних листов. Просто замените AppCompatDialog или AppCompatDialogFragment своими эквивалентами нижнего листа, чтобы ваш диалог был оформлен как нижний лист.
Ответ 4
Мне также пришлось реализовать вид, аналогичный тому, как Google Maps отображает нижний лист для найденного результата.
Вот как выглядит мой:
![Peek view]()
![Expand view scrolled to top]()
![Expand view scrolled to bottom]()
Сначала я определил нижний лист с заголовком и прокручиваемым содержимым, но layout_height, похоже, не оборачивал содержимое ни заголовка, ни прокручиваемого содержимого, несмотря на указание wrap_content
.
Эта проблема исчезла, когда я использовал LinearLayout
вместо ConstraintLayout
для дочернего макета CoordinatorLayout
(и для его дочерних LinearLayout
).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<Button
android:id="@+id/buttonPeek"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Peek"
app:layout_constraintEnd_toStartOf="@+id/buttonExpand"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonExpand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Expand"
app:layout_constraintEnd_toStartOf="@+id/buttonClose"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/buttonPeek"
app:layout_constraintTop_toTopOf="@+id/buttonPeek" />
<Button
android:id="@+id/buttonClose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Close"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/buttonExpand"
app:layout_constraintTop_toTopOf="@+id/buttonExpand" />
<androidx.coordinatorlayout.widget.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:id="@+id/layout_coordinator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/layout_coordinator_child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:layout_behavior="@string/bottom_sheet_behavior">
<LinearLayout
android:id="@+id/layout_bottom_sheet_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFF0000"
android:orientation="vertical" >
<TextView
android:id="@+id/headerTextView_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="a" />
<TextView
android:id="@+id/headerTextView_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="b" />
<TextView
android:id="@+id/headerTextView_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="c" />
<TextView
android:id="@+id/headerTextView_d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="d" />
<TextView
android:id="@+id/headerTextView_e"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="e" />
<TextView
android:id="@+id/headerTextView_f"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="f" />
<TextView
android:id="@+id/headerTextView_g"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="g" />
<TextView
android:id="@+id/headerTextView_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="h" />
<TextView
android:id="@+id/headerTextView_i"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="i" />
<TextView
android:id="@+id/headerTextView_j"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="j" />
<TextView
android:id="@+id/headerTextView_k"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="k" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/layout_bottom_sheet_scrollable_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF00FF00"
android:fillViewport="true" >
<LinearLayout
android:id="@+id/layout_bottom_sheet_scrollable_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textView0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="4" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="6" />
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="7" />
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="8" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="9" />
<TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="10" />
<TextView
android:id="@+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="11" />
<TextView
android:id="@+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="12" />
<TextView
android:id="@+id/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="13" />
<TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="14" />
<TextView
android:id="@+id/textView15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="15" />
<TextView
android:id="@+id/textView16"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="16" />
<TextView
android:id="@+id/textView17"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="17" />
<TextView
android:id="@+id/textView18"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="18" />
<TextView
android:id="@+id/textView19"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="19" />
<TextView
android:id="@+id/textView20"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="20" />
<TextView
android:id="@+id/textView21"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="21" />
<TextView
android:id="@+id/textView22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="22" />
<TextView
android:id="@+id/textView23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="23" />
<TextView
android:id="@+id/textView24"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="24" />
<TextView
android:id="@+id/textView25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25" />
<TextView
android:id="@+id/textView26"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="26" />
<TextView
android:id="@+id/textView27"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="27" />
<TextView
android:id="@+id/textView28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="28" />
<TextView
android:id="@+id/textView29"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="29" />
<TextView
android:id="@+id/textView30"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30" />
<TextView
android:id="@+id/textView31"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="31" />
<TextView
android:id="@+id/textView32"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="32" />
<TextView
android:id="@+id/textView33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="33" />
<TextView
android:id="@+id/textView34"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="34" />
<TextView
android:id="@+id/textView35"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="35" />
<TextView
android:id="@+id/textView36"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="36" />
<TextView
android:id="@+id/textView37"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="37" />
<TextView
android:id="@+id/textView38"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="38" />
<TextView
android:id="@+id/textView39"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="39" />
<TextView
android:id="@+id/textView40"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="40" />
<TextView
android:id="@+id/textView41"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="41" />
<TextView
android:id="@+id/textView42"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="42" />
<TextView
android:id="@+id/textView43"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="43" />
<TextView
android:id="@+id/textView44"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="44" />
<TextView
android:id="@+id/textView45"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="45" />
<TextView
android:id="@+id/textView46"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="46" />
<TextView
android:id="@+id/textView47"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="47" />
<TextView
android:id="@+id/textView48"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="48" />
<TextView
android:id="@+id/textView49"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="49" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.bottomsheetwithscrollablecontent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import androidx.appcompat.app.AppCompatActivity;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
public class MainActivity extends AppCompatActivity {
private CoordinatorLayout layout_coordinator;
private View layout_coordinator_child;
private View layout_bottom_sheet_header;
private BottomSheetBehavior behavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout_coordinator = findViewById(R.id.layout_coordinator);
layout_coordinator_child = layout_coordinator.findViewById(R.id.layout_coordinator_child);
layout_bottom_sheet_header = layout_coordinator.findViewById(R.id.layout_bottom_sheet_header);
behavior = BottomSheetBehavior.from(layout_coordinator_child);
Button buttonPeek = findViewById(R.id.buttonPeek);
buttonPeek.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
behavior.setPeekHeight(layout_bottom_sheet_header.getHeight());
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
Button buttonExpand = findViewById(R.id.buttonExpand);
buttonExpand.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
Button buttonClose = findViewById(R.id.buttonClose);
buttonClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
});
}
}
Приложение /build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.bottomsheetwithscrollablecontent"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01'
implementation "com.google.android.material:material:1.1.0-alpha04"
}