Wie kann man das 3-Phasen-Verhalten von Google Maps im unteren Bereich nachahmen?

110

Hintergrund

Ich bin damit beauftragt, eine Benutzeroberfläche zu erstellen, die sich ähnlich verhält wie Google Maps ein unteres Blatt für ein gefundenes Ergebnis anzeigt.

Es hat drei verschiedene Phasen:

  1. Unterer Inhalt. Der obere Bereich ist noch berührbar und wird unten nichts scrollen
  2. Vollbildinhalt, während der obere Bereich eine große Kopfzeile hat.
  3. Vollbildinhalt, während der obere Bereich nur die Symbolleiste enthält.

Ich spreche in Google Maps über Folgendes:

Geben Sie hier die Bildbeschreibung ein

Das Problem

Das Ding ist, das untere Blatt nicht ein Teil der Design - Bibliothek ist noch (obwohl es angefordert wurde, hier ).

Darüber hinaus scheint die Benutzeroberfläche recht komplex zu sein und muss in mehreren Phasen mit der Symbolleiste behandelt werden.

Was ich versucht habe

Ich habe eine gute (ausreichende) Bibliothek für das untere Blatt ( hier ) gefunden und dem Fragmentbeispiel Inhalt hinzugefügt, um ungefähr die gleichen Ansichten wie bei Materialdesignbeispielen (wie hier ) zu haben und ein CollapsingToolbarLayout zu haben, das sich darum kümmert der Phasen 2 + 3.

In der App, die ich mache, muss ich beim Scrollen auch ein Symbol verschieben, aber ich denke, wenn ich mit dem Rest Erfolg habe, sollte dies einfach sein. Hier ist der Code:

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

Es funktioniert fast gut. Das einzige Problem ist der Übergang von # 3 zurück zu # 2:

Geben Sie hier die Bildbeschreibung ein

Die Frage

Was ist los mit dem Code? Was kann ich tun, um das erforderliche Verhalten zu erreichen?

Android-Entwickler
quelle
Sehen Sie für mich wie Aktivitätsübergänge aus. Haben Sie versucht, 2 Aktivitäten zu erstellen und Materialübergänge zwischen ihnen anzuwenden? Und CoordinatorLayoutauf dem 2. Bildschirm verwendet?
SD
@ SD Ich bin mir sehr sicher, dass es nicht zwei Aktivitäten sind, da Sie den Bildschirm weiter berühren können, um zu scrollen und zwischen den Phasen zu wechseln. Es hindert Sie nicht daran, zur nächsten / vorherigen Aktivität zu wechseln. Ich glaube nicht, dass es beim Öffnen einer neuen Aktivität möglich ist, dieselben Berührungsereignisse für den Bildlaufmechanismus beizubehalten. Ich bin mir nicht einmal sicher, ob es möglich ist, Fragmente zu verwenden, aber dies ist wahrscheinlich mehr möglich als Aktivitäten.
Android-Entwickler
Dann denke ich, dass alle Ansichten im gleichen Layout sind und jeweils ein bestimmtes Verhalten festgelegt ist. Und alle Verhaltensweisen werden durch vertikales Abfangen von Bildläufen im Root-Layout ausgelöst, das alles koordiniert.
SD
@ SD Weißt du, wie es gut funktioniert? Ist es besser als das, was ich gefunden habe?
Android-Entwickler
1
Ich denke, Sie sollten sich diese Bibliothek ansehen .
Savelii Zagurskii

Antworten:

18

Hinweis : Lesen Sie die Änderungen unten


OK, ich habe einen Weg gefunden, dies zu tun, aber ich musste den Code mehrerer Klassen ändern, damit das untere Blatt den Status des appBarLayout (erweitert oder nicht) kennt und das Scrollen nach oben ignoriert, falls dies der Fall ist nicht erweitert:

BottomSheetLayout.java

Felder hinzugefügt:

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

init () - hat Folgendes hinzugefügt:

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

Funktion zum Festlegen des appBarLayout hinzugefügt:

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

onDetachedFromWindow () - hat Folgendes hinzugefügt:

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

onTouchEvent () - hat Folgendes hinzugefügt:

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

Das waren die wichtigsten Änderungen. Nun zu dem, was sie ausmacht:

MyFragment.java

onCreateView () - hat Folgendes hinzugefügt:

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

Ich habe auch diese Funktion hinzugefügt:

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

So teilt die Aktivität dem Fragment das appBarLayout mit:

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

Das Projekt ist jetzt auf GitHub verfügbar:

https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet

Ich hoffe es hat keine Bugs.


Die Lösung hat leider Fehler, daher werde ich diese Antwort nicht als die richtige markieren:

  1. Es funktioniert nur gut unter Android 6 und höher. Andere haben das seltsame Verhalten, dass das untere Blatt jedes Mal, wenn es angezeigt wird, für einen winzigen Bruchteil einer Zeit erweitert wird.
  2. Änderungen an der Ausrichtung speichern den Status des Bildlaufs überhaupt nicht, daher habe ich ihn deaktiviert.
  3. Seltenes Problem, in den Inhalt des unteren Blattes scrollen zu können, während es noch reduziert ist (unten)
  4. Wenn zuvor eine Tastatur angezeigt wurde, wird das untere Blatt möglicherweise im Vollbildmodus angezeigt, wenn versucht wird, einen Blick darauf zu werfen.

Wenn jemand dabei helfen kann, bitte.


Für Problem Nr. 1 habe ich versucht, einen Fix hinzuzufügen, indem ich die Sichtbarkeit auf UNSICHTBAR gesetzt habe, wenn das untere Blatt noch nicht gesehen wurde, aber es funktioniert nicht immer, insbesondere wenn eine Tastatur angezeigt wird.


Für Problem Nr. 1 habe ich herausgefunden, wie es behoben werden kann, indem ich einfach (in "fragment_my.xml") das CoordinatorLayout mit einer beliebigen Ansicht umhülle, die Sie verwenden möchten (ich habe FrameLayout verwendet), und auch eine Ansicht in voller Größe eingefügt habe es (ich habe gerade "Ansicht" gesetzt) ​​als solches:

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

Es hat wahrscheinlich das untere Blatt verwirrt, als ich das CoordinatorLayout als Ansicht hatte. Ich habe das Projekt aktualisiert, aber wenn es eine Möglichkeit gibt, eine bessere Lösung zu finden, würde ich gerne davon erfahren.


In den letzten Monaten hat Google eine eigene bottomSheet-Klasse veröffentlicht, aber wie ich festgestellt habe, gibt es viele Probleme, sodass ich sie nicht einmal ausprobieren kann.

Android-Entwickler
quelle
aber was ist mit diesem Bild? cloud.githubusercontent.com/assets/5357526/11641271/… Ich möchte diese Art von Bildfolie zusammen mit Bottomsheet implementieren
Hardy
@ HBdroid Ich denke es ist möglich. Ändern Sie möglicherweise für die Funktion "onOffsetChanged" auch die Übersetzung der mBottomSheetBackgroundImageView? Die Anforderung in meinem Fall war, zuerst die 3 Phasen zu behandeln. Jetzt geht es darum, was und wie übergegangen werden soll. Dies ist sehr individuell und hängt von Ihren Anforderungen ab. Es erfordert auch viel nervige Mathematik. Ich schlage vor, die Sofortlauffunktion zu verwenden, um den Versuch zu beschleunigen.
Android-Entwickler
Ich bin nicht in der Lage, die Lösung zu finden, bitte helfen Sie mir
Hardy
@ HBdroid Entschuldigung, ich weiß es nicht. Versuchen Sie vielleicht, diese App zu entfernen: layout_collapseMode = "parallax". Versuchen Sie auch, die Übersetzung in transformView durchzuführen.
Android-Entwickler
2
@Hardy haben Sie am Ende die gewünschte Lösung erstellt? Wenn ja, ist es Open Source und kann es geteilt werden?
N Jay
15

GROSSES UPDATE

Da es ungefähr 4 oder 5 Fragen zum selben Thema gab, ABER mit VERSCHIEDENEN Anforderungen, und ich versuchte, alle zu beantworten, löschte / schloss ein unhöflicher Administrator sie, sodass ich für jedes ein Ticket erstellte und sie in änderte Vermeiden Sie "Kopieren Einfügen" Ich werde Ihnen einen Link zur vollständigen Antwort geben, in dem Sie alle Erklärungen finden, wie Sie ein vollständiges Verhalten wie Google Maps erhalten.


Beantwortung Ihrer Frage

Wie kann man das 3-Phasen-Verhalten von Google Maps im unteren Bereich nachahmen?

Mit der Support-Bibliothek 23.x.x + können Sie die Standardeinstellung ändern BottomSheetBehaviorund eine weitere Statistik mit den folgenden Schritten hinzufügen:

  1. Erstellen Sie eine Java-Klasse und erweitern Sie sie von CoordinatorLayout.Behavior<V>
  2. Kopieren Sie den Einfügecode aus der Standarddatei BottomSheetBehaviorin Ihre neue.
  3. Ändern Sie die Methode clampViewPositionVerticalmit dem folgenden Code:

    @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. Neuen Status hinzufügen:

    public static final int STATE_ANCHOR_POINT = X;
  5. Ändern Sie die folgenden Methoden: onLayoutChild, onStopNestedScroll, BottomSheetBehavior<V> from(V view)und setState(optional)

Ich werde diese geänderten Methoden und einen Link zum Beispielprojekt hinzufügen .

Und so sieht es aus:
CustomBottomSheetBehavior

MiguelHincapieC
quelle
Ich habe das Github-Repo jetzt getestet und es scheint schön zu sein. Aber der obere blaue Bereich sieht manchmal teilweise aus. Außerdem kann ich nicht herausfinden, wo Ansichten verarbeitet werden sollen, die beim Ziehen des unteren Blattes verschoben werden müssen. In dem Repo, das ich erstellt habe (hier: github.com/AndroidDeveloperLB/ThreePhasesBottomSheet ), wird das Bild ausgeblendet und das kleine Bild wird von einem Ort zum anderen verschoben, einschließlich der Änderung seiner Größe. Ich würde gerne wissen, wo ich die Handhabung dieser hinzufügen soll.
Android-Entwickler
Hallo, ich habe eine lokale Version mit Parallaxenbild, aber es funktioniert noch nicht gut (ich kann es pushen, wenn du es sehen willst). Sie können jede Ansicht innerhalb des CoordinatorLayoutIn hinzufügen activity_main.xml. Ich denke, Sie haben gute Erfahrungen mit dem Layout des Koordinators gemacht, ansonsten werfen Sie einen Blick auf diesen Link, den ich gefunden habe
MiguelHincapieC
Ich werde sehen, wie Sie zum Verhalten der Symbolleiste gekommen sind, und werde es bei mir verwenden: D. Übrigens gibt es ein kleines Verhalten, das ich nur nachahmen könnte, wenn ich die Unterstützungsbibliothek 23.2 verwende: Wenn Sie in Google Maps das Bild unter die Symbolleiste ziehen, wird das untere Blatt verschoben, aber wenn Sie auf 23.4 oder minSdkVersion 14+ aktualisieren, werden Sie es tun dieses Verhalten verlieren o_O '
MiguelHincapieC
@androiddeveloper Ich habe es verstanden! Jetzt funktioniert es mit Bildparallaxeneffekten und Symbolleistenanimationen ... Mir fehlt nur die Farbe, die die Symbolleiste annimmt, wenn Sie weiter nach oben rutschen: D
MiguelHincapieC
@ MiguelHincapieC Hallo, ich möchte nur die Hauptsymbolleiste anzeigen und habe das zusammengeführte Appbar-Layout entfernt, aber auf der unteren Folie die Zeitstatusleiste erweitern, die nicht angezeigt wird, und das Parallex-Bild endet an der Position der Statusleiste, und ich möchte das Parallex-Bild unterhalb der Hauptsymbolleiste kleben lassen. Können Sie erklären , wie ich es tun kann
Vijay Rajput
0

Hast du das versucht? http://android-developers.blogspot.in/2016/02/android-support-library-232.html?m=1 Hier heißt es, dass wir nur ein Layoutverhalten für das untere Blatt angeben können.

AKTUALISIEREN:

Grundsätzlich heißt der Link-

Durch Anhängen eines BottomSheetBehavior an eine untergeordnete Ansicht eines CoordinatorLayout (dh Hinzufügen einer App: layout_behavior = "android.support.design.widget.BottomSheetBehavior") erhalten Sie automatisch die entsprechende Berührungserkennung für den Übergang zwischen fünf Status:

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

Wenn Sie Rückrufe von Statusänderungen erhalten möchten, können Sie einen BottomSheetCallback hinzufügen:

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

Während BottomSheetBehavior den persistenten Fall des unteren Blattes erfasst, bietet diese Version auch einen BottomSheetDialog und ein BottomSheetDialogFragment, um den Anwendungsfall der modalen unteren Blätter zu füllen. Ersetzen Sie einfach AppCompatDialog oder AppCompatDialogFragment durch ihre unteren Blattäquivalente, damit Ihr Dialog als unteres Blatt gestaltet wird.

Vaibhav Sharma
quelle
Die Frage wurde gestellt, bevor Google die Support-Bibliotheksklasse zeigte. Wenn Sie eine funktionierende Lösung haben, zeigen Sie diese bitte hier.
Android-Entwickler
@androiddeveloper Ich habe das Datum der Frage nicht gelesen und daher diese Antwort vorgeschlagen. Aber wenn Sie diese Bibliothek verwenden möchten, können Sie das verwenden. Was die funktionierende Lösung für diesen Code betrifft, habe ich sie nicht. Es tut uns leid.
Vaibhav Sharma
0

Ich musste auch eine ähnliche Ansicht implementieren, wie Google Maps ein unteres Blatt für ein gefundenes Ergebnis anzeigt.

So sieht meins aus:

Blick spähen

Erweitern Sie die Ansicht nach oben

Erweitern Sie die Ansicht nach unten

Zuerst habe ich ein unteres Blatt mit einer Kopfzeile und einem scrollbaren Inhalt definiert, aber die layout_height schien den Inhalt weder der Kopfzeile noch des scrollbaren Inhalts trotz Angabe zu umbrechen wrap_content .

Das Problem ging weg , als ich verwenden , LinearLayoutanstatt ConstraintLayoutfür dieCoordinatorLayout Kinder s‘Layout (und für ihre Kinder).

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"
}
Michael Osofsky
quelle