Android - So deaktivieren Sie den Status STATE_HALF_EXPANDED eines unteren Blattes

14

Ich habe ein unteres Blatt, das zwischen zwei Zuständen liegen sollte, STATE_COLLAPSEDund STATE_EXPANDED wenn es zusammengeklappt ist, sollte die Höhe sein 200dpund wenn es erweitert wird, wird es im Vollbildmodus angezeigt.

Also setze ich das BottomSheetBehaviormit

isFitToContents = false
peekHeight = 200dp

und ich bin gezwungen, einen anderen Wert halfExpandedRatiofestzulegen, wenn STATE_HALF_EXPANDEDdas untere Blatt die Hälfte des Bildschirms einnimmt.

Ich arbeite mit com.google.android.material:material:1.1.0-rc01

Gibt es eine Möglichkeit, den STATE_HALF_EXPANDEDStaat zu deaktivieren ?

Oder ich sollte tatsächlich festlegen skipCollapsed=true, in Bezug auf das Verhältnis herausfinden, was 200 dp bedeutet, und mit STATE_HALF_EXPANDEDund STATE_EXPANDEDanstelle von STATE_COLLAPSEDund arbeitenSTATE_EXPANDED

Noa Drach
quelle
Bitte geben Sie weitere Details an, z. B. wie das untere Blatt aussieht.
UD ..
@ UD..Ich denke nicht, dass der Inhalt des unteren Blattes in diesem Fall relevant ist. Dies ist eine allgemeinere Frage, ist es möglich, einen der unteren Blattzustände zu deaktivieren
Noa Drach
1
Für meinen Anwendungsfall scheint es, dass das Einstellen halfExpandedRatio=0.25fund peekHeight = 200dpanschließende Behandeln STATE_COLLAPSEDund STATE_HALF_EXPANDEDals ob sie sich in demselben Zustand befinden, das Problem löst. Halten Sie die Frage offen, falls es andere Ideen gibt.
Noa Drach
Sie können diesem Link folgen, es wird androidhive.info/2017/12/android-working-with-bottom-sheet
UD
Akzeptieren Sie unbedingt eine dieser Antworten, wenn Sie die in Ihrer Frage festgelegten Ziele erreichen!
CommonsWare

Antworten:

3

Der Wert des halb erweiterten Verhältnisses muss auf einen Wert zwischen 0 und 1 exklusiv eingestellt werden. Stellen Sie diesen Wert daher auf eine sehr niedrige Zahl ein, die mit Sicherheit unter Ihrer Blickhöhe liegt, z. B. "0,0001f". Mit diesem Wert sollten Sie nicht einmal den STATE_HALF_EXPANDEDStatus sehen. Die Zustände schwanken zwischen STATE_EXPANDEDund STATE_COLLAPSED.


Alternative Lösung

Die obige Lösung funktioniert und deaktiviert den STATE_HALF_EXPANDEDStatus effektiv , ist jedoch hackisch (IMO) und kann in Zukunft nicht mehr funktionieren. Was ist zum Beispiel, wenn ein angemessener Wert für das halb erweiterte Verhältnis erzwungen wird, der irgendwo zwischen der Blickhöhe und der vollen Höhe liegt? Das wäre Ärger.

Die Anforderungen des OP lauten, dass das untere Blatt zwischen der Blickhöhe und der vollen Höhe wechseln muss. Es gibt kein Problem mit der Blickhöhe, aber das OP gibt anisFitToContents = false an, dass die volle Höhe erreicht werden soll. (Ich gehe davon aus, dass sein unteres Blatt kürzer sein kann als der verfügbare Platz.)

Leider, wenn isFitToContents == falseein zusätzliches "halbes" Verhalten eingeführt wird, das das OP vermeiden möchte und daher die Frage.

Zusätzlich zum Verhalten "halbe Höhe" wird ein anderes Verhalten eingeführt, nämlich der "erweiterte Versatz". Der erweiterte Versatz gibt an, wie weit vom unteren Bildschirm entfernt das untere Blatt angehalten wird. Ein Wert von100f beispielsweise hinterlässt 100pxbei vollständiger Erweiterung einen Rand am oberen Rand des unteren Blattes. Der Standardwert für den erweiterten Offset ist Null.

Mir sind keine Verhaltensweisen bekannt isFitToContents == false als die oben genannten bekannt.

Können wir angesichts dieser Anforderungen ein unteres Blatt erstellen, das sich beim Festlegen zwischen der Blickhöhe und der vollen Höhe bewegt? isFitToContents == true wodurch das Problem der "halben Höhe" vermieden wird? Es ist kein erweiterter Offset ungleich Null erforderlich, daher müssen wir uns darüber keine Sorgen machen.

Hier ist eine kurze Demo-App, die zeigt, dass wir diese Anforderungen mit der rechten unteren Blattstruktur erfüllen können:

Geben Sie hier die Bildbeschreibung ein

MainActivity5.kt

class MainActivity5 : BaseActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main5)  

        val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet)  
        val sheetBehavior: BottomSheetBehavior<LinearLayout> = BottomSheetBehavior.from(bottomSheet)  
        sheetBehavior.isFitToContents = true // the default  
  sheetBehavior.peekHeight = 200  

  // Log the states the bottom sheet passes through.  
  sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {  
            override fun onStateChanged(bottomSheet: View, newState: Int) {  
                Log.d("MainActivity", "<<<< $newState = ${translateSheetState(newState)}")  
            }  

            override fun onSlide(bottomSheet: View, slideOffset: Float) {}  
        })  
    }  
}

BaseActivity.kt

open class BaseActivity : AppCompatActivity() {  

    protected fun translateSheetState(state: Int): String {  
        return when (state) {  
            BottomSheetBehavior.STATE_COLLAPSED -> "STATE_COLLAPSED"  
  BottomSheetBehavior.STATE_DRAGGING -> "STATE_DRAGGING"  
  BottomSheetBehavior.STATE_EXPANDED -> "STATE_EXPANDED"  
  BottomSheetBehavior.STATE_HALF_EXPANDED -> "STATE_HALF_EXPANDED"  
  BottomSheetBehavior.STATE_HIDDEN -> "STATE_HIDDEN"  
  BottomSheetBehavior.STATE_SETTLING -> "STATE_SETTLING"  
  else -> "Unknown state: $state"  
  }  
    }  
}

activity_main5.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light"
        android:orientation="vertical"
        android:scrollbars="none"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="@string/short_text"
            android:textSize="16sp" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Wenn wir ein langes unteres Blatt haben, funktioniert die folgende Struktur, um es zu scrollen:

activity_main6.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light"
        android:orientation="vertical"
        android:scrollbars="none"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:text="@string/long_text"
                android:textSize="16sp" />
        </androidx.core.widget.NestedScrollView>
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
Cheticamp
quelle
in Bezug auf Ihre erste Antwort - Ich habe gesehen, dass selbst wenn ich das halbe erweiterte Verhältnis einstelle, ein sehr schmaler Hinweis auf das untere Blatt immer noch sichtbar ist. Und überhaupt ist dies nicht das Verhalten, nach dem ich suche. Wie Sie in "Alternative Lösung" erwähnt haben - "Das untere Blatt sollte zwischen der Blickhöhe und der vollen Höhe wechseln"
Noa Drach
Ihre "alternative Lösung" scheint zu funktionieren und es ist die Lösung, die ich brauchte. Meine ersten Tests haben gezeigt, dass ich sie verwenden muss isFitToContents = false, aber das Testen isFitToContents = truefunktioniert jetzt in Ordnung
Noa Drach
@NoaDrach Wenn das untere Blatt ausgeblendet ist, wird am unteren Rand mindestens 1 Pixel angezeigt, da der Versatz des unteren Blattes berechnet wird. Ich dachte nicht, dass das Blatt ausgeblendet werden würde, aber mit 1px könnte das Blatt nur ausgeblendet werden, sheetBehavior.state = BottomSheetBehavior.STATE_HIDDENwenn der halb erweiterte Zustand erreicht ist, aber das wird etwas kompliziert. Die alternative Lösung ist besser.
Cheticamp
2

Geben Sie hier die Bildbeschreibung ein

Wenn Sie oben wie im Bild versuchen möchten, können Sie dem folgenden Code folgen, möge es Ihnen helfen !!!

public class CollectionsBottomSheet extends BottomSheetDialogFragment {
    private BottomSheetBehavior mBehavior;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
        View view = View.inflate(getContext(), R.layout.collections_layout, null);
        LinearLayout linearLayout = view.findViewById(R.id.root);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
        params.height = getScreenHeight();
        linearLayout.setLayoutParams(params);
        dialog.setContentView(view);
        mBehavior = BottomSheetBehavior.from((View) view.getParent());
        return dialog;

    }

    @Override
    public void onStart() {
        super.onStart();
        mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }

    public static int getScreenHeight() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }
}



xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true">


    <LinearLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/filter_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableStart="@drawable/ic_cancel"
                android:drawableLeft="@drawable/ic_cancel"
                android:drawablePadding="30dp"
                android:gravity="center_vertical"
                android:padding="12dp"
                android:text="Filters"
                android:textColor="@color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="10dp"
                android:layout_marginRight="10dp"
                android:padding="5dp"
                android:text="Reset ALL"
                android:textColor="#6f6f6f"
                android:textSize="12sp" />

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#d8dbdb" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_star"
            android:drawableLeft="@drawable/ic_star"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="GUEST RATINGS"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_money"
            android:drawableLeft="@drawable/ic_money"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="PRICE RANGE"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_loan"
            android:drawableLeft="@drawable/ic_star"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="PAY AT HOTEL"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_folder"
            android:drawableLeft="@drawable/ic_folder"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="COLLECTIONS"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_perm_identity_black_24dp"
            android:drawableLeft="@drawable/ic_perm_identity_black_24dp"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="FACILITIES"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_apartment"
            android:drawableLeft="@drawable/ic_apartment"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="CATEGORIES"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_hotel_building"
            android:drawableLeft="@drawable/ic_hotel_building"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="ACCOMMODATION TYPE"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

    </LinearLayout>


</LinearLayout>
UD ..
quelle
sehr gute Antwort ... hat meinen Tag gerettet
unbekannt
1

Versuchen Sie, ein addBottomSheetCallbackauf Ihrem zu setzen BottomSheetBehavior, und STATE_HALF_EXPANDEDrufen Sie auf , wenn Sie einen Status erkennen. setState(STATE_HIDDEN)Wenn das untere Blatt versucht, den halben Status zu erreichen, wird es einfach geschlossen.

Marmor
quelle
nette Idee, in meinem Fall würde ich den Zustand einstellen STATE_COLLAPSEDund nicht STATE_HIDDEN. Aber ich habe versucht, es umzusetzen und der Übergang von STATE_HALF_EXPANDEDzu STATE_COLLAPSEDfühlt sich klobig an. Der Übergang zwischen den Zuständen ist animiert, so dass Sie sehen, dass das untere Blatt anhält STATE_HALF_EXPANDEDund sich dann zuSTATE_COLLAPSED
Noa Drach
Könnten Sie dies mit einem halfExpandedRatio von 0 kombinieren?
Ridcully
@Ridcully - 2 Probleme hier - 1. halfExpandedRatio muss über 0 liegen 2. Wenn Sie es auf einen sehr niedrigen Wert setzen, wird es für mich fast vollständig minimiert (halb erweiterter Zustand), bevor es in den reduzierten Zustand versetzt wird. Ich dachte daran, diesen Vorschlag mit meiner Arbeitslösung von halfExpandedState=0.25fb / c zu kombinieren , dann wird der Übergang zwischen Staaten nicht so offensichtlich sein. Aber ich bin mir nicht sicher, ob dies eine große Veränderung im Vergleich zu dem sein wird, was ich bereits habe
Noa Drach
1

Ich hatte einen ähnlichen Anwendungsfall, bei dem das Layout ein Drittel der Höhe betragen musste. Ich habe folgendes versucht und es hat super funktioniert.

<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/bottom_sheet_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grey"
    android:clickable="true">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/rounded_bottom_sheet_background"
        android:orientation="vertical"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Ich musste diese dynamisch ändern, damit ich auf dem unteren Blatt Folgendes einstelle, aber Sie können dies auch in XML tun:

bottomSheet.setPeekHeight(200);// 200px
bottomSheet.setHideable(false);

Zum Schließen habe ich meinem Fragment mit der folgenden Funktion eine Animation hinzugefügt:

fragmentTransaction.setCustomAnimations(
                    R.anim.fade_in,
                    R.anim.fade_out,
                    R.anim.fade_in,
                    R.anim.fade_out)

Hoffe das hilft

Saurabh
quelle
0

Ich habe verschiedene Methoden ausprobiert, aber keine Technik hat perfekt funktioniert. Ich habe versucht, Ereignisse in abzufangenBottomSheetBehavior.BottomSheetCallback {} und habe angerufendismiss() basierend auf benutzerdefinierter Logik aber es verursachte einen Ruck.

Also, endlich, in meinem habe BottomSheetDialogFragmentich hinzugefügtbottomSheetBehavior.isDraggable = false und dies verursachte das Ziehen des unteren Blattes durch Berühren. Und ich handhabte die Entlassung des Dialogs selbst. im leeren Bereich Dialog wird sowieso entlassen.

Beachten Sie, dass das untere Blatt immer noch mit Animation erweitert wird. Das ist wirklich toll!

Spaß überschreiben onCreateDialog (savedInstanceState: Bundle?): Dialog {val dialog = super.onCreateDialog (savedInstanceState)

    dialog.setOnShowListener {
        val bottomSheetDialog = it as BottomSheetDialog
        val bottomSheet =
            bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
                ?: return@setOnShowListener

        //Making background to transparent to avoid white background to given space margin.
        bottomSheet.setBackgroundColor(ContextCompat.getColor(context!!, R.color.transparent))

        val inflatedView = fragmentProfileDialogBinding.root
        val parent = inflatedView.parent as View

        val bottomSheetBehavior = BottomSheetBehavior.from(parent)
        bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
        bottomSheetBehavior.isDraggable = false
    }

    return dialog
}
Rahul Rastogi
quelle