Jak naśladować 3-fazowe zachowanie Map Google w dolnej części?


110

tło

Zostałem przydzielony do stworzenia interfejsu użytkownika, który zachowuje się podobnie do tego, jak Mapy Google pokazują dolny arkusz znalezionego wyniku.

Ma trzy różne fazy:

  1. Dolna treść. Górny obszar jest nadal dotykalny i nie przewija niczego na dole
  2. Treść pełnoekranowa, podczas gdy górny obszar ma duży nagłówek.
  3. Treść pełnoekranowa, podczas gdy w górnym obszarze znajduje się tylko pasek narzędzi.

Oto, o czym mówię w Mapach Google:

Tutaj wprowadź opis obrazu

Problem

Chodzi o to, że dolny arkusz nie jest jeszcze częścią biblioteki projektów (chociaż został o to poproszony tutaj ).

Co więcej, interfejs użytkownika wydaje się dość złożony i wymaga obsługi paska narzędzi w wielu fazach.

Co próbowałem

Znalazłem dobrą (wystarczającą) bibliotekę dla dolnego arkusza ( tutaj ) i dodałem zawartość do jej próbki fragmentu, aby mieć mniej więcej takie same widoki, jak pokazano na przykładach Material Design (jak tutaj ), aby mieć CollapsingToolbarLayout, który zajmie się faz 2 + 3.

W aplikacji, którą tworzę, muszę również przesuwać ikonę podczas przewijania, ale myślę, że jeśli uda mi się z resztą, to powinno być łatwe. Oto kod:

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);
            }
        });
    }
}

Prawie działa. Jedynym problemem jest przejście z # 3 z powrotem do # 2:

wprowadź opis obrazu tutaj

Pytanie

Co jest nie tak z kodem? Co mogę zrobić, aby osiągnąć wymagane zachowanie?


Wygląda na to, że dla mnie przejście aktywności Czy próbowałeś utworzyć 2 działania i zastosować między nimi przejścia materiałowe? I używany CoordinatorLayoutna drugim ekranie?
SD,

@SD Jestem pewien, że to nie są 2 czynności, ponieważ możesz nadal dotykać ekranu, aby przewijać i przełączać się między fazami. Nie przeszkadza ci to przejść do następnej / poprzedniej czynności. Nie sądzę, aby podczas otwierania nowego działania można było zachować te same zdarzenia dotykowe dla mechanizmu przewijania. Nie jestem nawet pewien, czy jest to możliwe przy użyciu fragmentów, ale jest to prawdopodobnie bardziej możliwe niż działania.
programista Androida

Wtedy myślę, że wszystkie widoki są w tym samym układzie, a każdy ma ustawione określone zachowanie . Wszystkie zachowania są wywoływane przez przechwytywanie przewijania w pionie w układzie głównym, który wszystko koordynuje.
SD

@SD Czy wiesz, jak to działa? Czy to lepsze niż to, co znalazłem?
programista Androida

1
Myślę, że powinieneś zajrzeć do tej biblioteki .
Savelii Zagurskii

Odpowiedzi:


18

Uwaga : przeczytaj zmiany na dole


OK, znalazłem sposób, aby to zrobić, ale musiałem zmienić kod wielu klas, aby dolny arkusz wiedział o stanie appBarLayout (rozwinięty lub nie) i zignorować przewijanie w górę, jeśli jest nierozwinięty:

BottomSheetLayout.java

Dodane pola:

private AppBarLayout mAppBarLayout;
private OnOffsetChangedListener mOnOffsetChangedListener;
private int mAppBarLayoutOffset;

init () - dodał:

    mOnOffsetChangedListener = new OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(final AppBarLayout appBarLayout, final int verticalOffset) {
            mAppBarLayoutOffset = verticalOffset;
        }
    };

Dodano funkcję ustawiania appBarLayout:

public void setAppBarLayout(final AppBarLayout appBarLayout) {
    if (mAppBarLayout == appBarLayout)
        return;
    if (mAppBarLayout != null)
        mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);
    mAppBarLayout = appBarLayout;
    mAppBarLayout.addOnOffsetChangedListener(mOnOffsetChangedListener);
}

onDetachedFromWindow () - dodano:

    if (mAppBarLayout != null)
        mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);

onTouchEvent () - dodano to:

      ...
      if (bottomSheetOwnsTouch) {
        if (state == State.EXPANDED && scrollingDown && mAppBarLayout != null && mAppBarLayoutOffset != 0) {
            event.offsetLocation(0, sheetTranslation - getHeight());
            getSheetView().dispatchTouchEvent(event);
            return true;
        }
      ...

To były główne zmiany. Teraz co je ustawia:

MyFragment.java

onCreateView () - dodał:

    mBottomSheetLayout.setAppBarLayout((AppBarLayout) view.findViewById(R.id.appbar));

Dodałem również tę funkcję:

 public void setBottomSheetLayout(final BottomSheetLayout bottomSheetLayout) {
    mBottomSheetLayout = bottomSheetLayout;
}

W ten sposób aktywność informuje fragment o appBarLayout:

            final MyFragment myFragment = new MyFragment();
            myFragment.setBottomSheetLayout(bottomSheetLayout);
            myFragment.show(getSupportFragmentManager(), R.id.bottomsheet);

Projekt jest już dostępny na GitHub:

https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet

Mam nadzieję, że nie ma żadnych błędów.


Niestety rozwiązanie zawiera błędy, więc nie oznaczę tej odpowiedzi jako poprawnej:

  1. Działa dobrze tylko na Androidzie 6 i nowszych. Inne mają dziwne zachowanie polegające na tym, że dolny arkusz jest rozszerzany przez niewielki ułamek czasu, za każdym razem, gdy jest wyświetlany.
  2. Zmiany orientacji w ogóle nie zapisują stanu przewijania, więc je wyłączyłem.
  3. Rzadki problem z możliwością przewijania zawartości dolnego arkusza, gdy jest on nadal zwinięty (na dole)
  4. Jeśli klawiatura była wcześniej wyświetlana, dolny arkusz może być wyświetlany na pełnym ekranie podczas próby podglądania.

Jeśli ktoś może w tym pomóc, zrób to.


W przypadku problemu nr 1 próbowałem dodać poprawkę, ustawiając widoczność na INVISIBLE, gdy dolny arkusz nie jest jeszcze podglądany, ale nie zawsze działa, zwłaszcza jeśli jest wyświetlana klawiatura.


W przypadku problemu nr 1 znalazłem, jak to naprawić, po prostu opakowując (w „fragment_my.xml”) układ CoordinatorLayout dowolnym widokiem, którego chcesz użyć (użyłem FrameLayout), a także umieszczając pełnowymiarowy widok w it (po prostu wstawiłem „Widok”), tak jak:

<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 
    ...

Prawdopodobnie pomylił dolny arkusz, gdy miałem widok CoordinatorLayout. Zaktualizowałem projekt, ale jeśli istnieje sposób na ładniejsze rozwiązanie, to chciałbym się o tym dowiedzieć.


W ostatnich miesiącach Google opublikowało własną klasę bottomSheet, ale jak odkryłem, ma wiele problemów, więc nie mogę jej nawet wypróbować.


ale co z tym obrazem? cloud.githubusercontent.com/assets/5357526/11641271/ ... chcę zaimplementować ten rodzaj slajdu obrazu wraz z arkuszem dolnym idzie w górę
Hardy

@HBdroid Myślę, że to możliwe. może dla funkcji "onOffsetChanged" zmienić także tłumaczenie mBottomSheetBackgroundImageView? Wymóg w moim przypadku polegał na tym, aby najpierw obsłużyć 3 fazy. Teraz jest pytanie, co i w jaki sposób przejść, a to jest bardzo dostosowane i zależy od Twoich potrzeb. Wymaga też dużo irytującej matematyki. Sugeruję użycie funkcji natychmiastowego uruchamiania, aby przyspieszyć próbę.
programista Androida

nie jestem w stanie znaleźć rozwiązania, pomóż mi
Hardy

@HBdroid Przepraszam, nie wiem. Może spróbuj usunąć tę aplikację: layout_collapseMode = "parallax". spróbuj również wykonać tłumaczenie w transformView.
programista Androida

2
@Hardy, czy udało Ci się stworzyć rozwiązanie, które chciałeś? jeśli tak, czy jest to oprogramowanie typu open source i czy można je udostępniać?
N Jay

15

DUŻA AKTUALIZACJA

Ponieważ było 4 lub 5 pytań na ten sam temat, ALE z RÓŻNYMI wymaganiami i próbowałem odpowiedzieć na wszystkie, ale niepoprawny administrator je usunął / zamknął, zmuszając mnie do utworzenia biletu dla każdego i zmiany na unikaj „kopiuj wklej”. Podam link do pełnej odpowiedzi, w której można znaleźć wszystkie wyjaśnienia dotyczące pełnego zachowania, takiego jak Mapy Google.


Odpowiadając na Twoje pytanie

Jak naśladować 3-fazowe zachowanie Map Google w dolnej części?

Dzięki obsłudze biblioteki 23.x.x + możesz to zrobić modyfikując domyślne BottomSheetBehavior, dodając jeszcze jedną statystykę, wykonując następujące kroki:

  1. Utwórz klasę Java i rozszerz ją z CoordinatorLayout.Behavior<V>
  2. Skopiuj kod wklejania z domyślnego BottomSheetBehaviorpliku do nowego.
  3. Zmodyfikuj metodę clampViewPositionVerticalza pomocą następującego kodu:

    @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);
    }
  4. Dodaj nowy stan:

    public static final int STATE_ANCHOR_POINT = X;
  5. Modyfikować następujące metody: onLayoutChild, onStopNestedScroll, BottomSheetBehavior<V> from(V view)i setState(opcjonalnie)

Zamierzam dodać te zmodyfikowane metody i link do przykładowego projektu .

A oto jak to wygląda:
CustomBottomSheetBehavior


Przetestowałem teraz repozytorium github i wydaje się fajne. Ale górny niebieski obszar czasami wygląda na częściowy. Nie mogę też dowiedzieć się, gdzie obsługiwać widoki, które wymagają przesunięcia podczas przeciągania dolnego arkusza. W utworzonym przeze mnie repozytorium (tutaj: github.com/AndroidDeveloperLB/ThreePhasesBottomSheet ) obraz zanika, a mały obrazek przesuwa się z jednego miejsca na drugie, w tym zmienia jego rozmiar. Chciałbym wiedzieć, gdzie dodać obsługę tych.
programista Androida

Cześć, mam lokalną wersję z obrazem paralaksy, ale nie działa ona jeszcze dobrze (mogę ją wcisnąć, jeśli chcesz ją obejrzeć). Możesz dodać dowolny widok wewnątrz pliku CoordinatorLayoutin activity_main.xml. Myślę, że masz dobre doświadczenie z układem koordynatora, w przeciwnym razie spójrz na ten link, który znalazłem
MiguelHincapieC

Zobaczę, jak uzyskałeś zachowanie paska narzędzi i użyję go na moim: D. Nawiasem mówiąc, jest pewne zachowanie, które mógłbym naśladować tylko wtedy, gdy używam biblioteki wsparcia 23.2: w mapach Google, jeśli przeciągniesz obraz, który poniżej paska narzędzi przesunie dolny arkusz, ale jeśli zaktualizujesz do 23.4 lub minSdkVersion 14+, stracić to zachowanie o_O '
MiguelHincapieC

@androiddeveloper Mam to! teraz działa z efektem paralaksy obrazu i animacjami pasków narzędzi ... Brakuje mi tylko koloru, który zajmuje pasek narzędzi, gdy przesuwasz się w górę: D
MiguelHincapieC

@MiguelHincapieC Cześć, chcę wyświetlić tylko główny pasek narzędzi i usunąłem scalony układ paska aplikacji, ale na dolnym arkuszu pasek stanu rozwinięcia czasu nie jest wyświetlany, a obraz paraleksowy kończy się na pozycji paska stanu i chcę paraleksować obraz przyklejony poniżej głównego paska narzędzi. czy możesz wyjaśnić, jak mam to zrobić
Vijay Rajput,

0

Próbowałeś tego? http://android-developers.blogspot.in/2016/02/android-support-library-232.html?m=1 Tutaj jest napisane, że możemy po prostu określić zachowanie układu dolnego arkusza.

AKTUALIZACJA:

Zasadniczo łącze stwierdza:

Dołączając BottomSheetBehavior do podrzędnego widoku CoordinatorLayout (tj. Dodając app: layout_behavior = "android.support.design.widget.BottomSheetBehavior") automatycznie uzyskasz odpowiednie wykrywanie dotyku umożliwiające przejście między pięcioma stanami:

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+).

Jeśli chcesz otrzymywać wywołania zwrotne zmian stanu, możesz dodać 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  
   }  
 });  

Podczas gdy BottomSheetBehavior przechwytuje trwały przypadek dolnego arkusza, ta wersja udostępnia również BottomSheetDialog i BottomSheetDialogFragment do wypełniania modalnego przypadku użycia dolnych arkuszy. Po prostu zastąp AppCompatDialog lub AppCompatDialogFragment ich odpowiednikami w dolnym arkuszu, aby Twoje okno dialogowe było stylizowane na dolny arkusz.


Pytanie zostało zadane, zanim Google pokazało swoją klasę biblioteki wsparcia. Jeśli masz działające rozwiązanie, które go używa, pokaż je tutaj.
programista Androida

@androiddeveloper Nie przeczytałem daty pytania i dlatego zasugerowałem tę odpowiedź. Ale jeśli chcesz korzystać z tej biblioteki, możesz jej użyć. Jeśli chodzi o działające rozwiązanie dla tego kodu, to nie mam go. Przepraszam.
Vaibhav Sharma

0

Musiałem również zaimplementować widok podobny do tego, jak Mapy Google pokazują dolny arkusz znalezionego wyniku.

Oto jak wygląda mój:

Rzuć okiem

Rozwiń widok przewinięty do góry

Rozwiń widok przewinięty do dołu

Na początku zdefiniowałem dolny arkusz z nagłówkiem i przewijaną treścią, ale layout_height nie wydawał się zawijać zawartości ani nagłówka, ani przewijalnej zawartości pomimo określenia wrap_content.

Problem odszedł kiedy użyłem LinearLayoutzamiast ConstraintLayoutna CoordinatorLayout„s układ dzieci (i dla swoich dzieci).

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);
            }
        });
    }
}

app / 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"
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.