web-dev-qa-db-fra.com

Android - Comment désactiver l'état STATE_HALF_EXPANDED d'une feuille inférieure

J'ai une feuille inférieure qui doit aller entre 2 états, STATE_COLLAPSED et STATE_EXPANDED quand il s'est effondré, la hauteur devrait être 200dp et une fois développé, il sera en plein écran.

Je mets donc le BottomSheetBehavior avec

isFitToContents = false
peekHeight = 200dp

et je suis obligé de définir une valeur dans halfExpandedRatio sinon à STATE_HALF_EXPANDED la feuille du bas occupera la moitié de l'écran.

Je travaille avec com.google.Android.material:material:1.1.0-rc01

Existe-t-il un moyen de désactiver le STATE_HALF_EXPANDED Etat?

Ou je devrais en fait définir skipCollapsed=true, déterminez en termes de ratio ce que signifie 200dp et travaillez avec STATE_HALF_EXPANDED et STATE_EXPANDED au lieu de STATE_COLLAPSED et STATE_EXPANDED

14
Noa Drach

La valeur du rapport semi-étendu doit être définie sur une valeur comprise entre 0 et 1 exclusif, définissez donc cette valeur sur un nombre très faible qui sera certainement inférieur à votre hauteur de vue, par exemple " 0,0001f ". Avec cette valeur, vous ne devriez même pas voir le STATE_HALF_EXPANDED Etat. Les états fluctueront entre STATE_EXPANDED et STATE_COLLAPSED.


Solution alternative

La solution ci-dessus fonctionne et désactive efficacement le STATE_HALF_EXPANDED état, mais il est hackish (IMO) et peut se casser à l'avenir. Par exemple, que se passe-t-il si une valeur raisonnable pour le rapport semi-étendu qui se situe quelque part entre la hauteur de coup d'œil et la hauteur totale est appliquée? Ce serait un problème.

Les exigences énoncées par le PO sont que la feuille inférieure doit faire la transition entre la hauteur de coup d'œil et la hauteur totale. Il n'y a pas de problème avec la hauteur de l'aperçu, mais l'OP spécifie isFitToContents = false pour atteindre sa pleine hauteur. (Je suppose que sa feuille inférieure peut être plus courte que l'espace disponible.)

Malheureusement, lorsque isFitToContents == false un comportement "demi-hauteur" supplémentaire est introduit que l'OP veut éviter et donc la question.

En plus du comportement "demi-hauteur", un autre comportement est introduit qui est le "décalage étendu". Le décalage étendu spécifie à quelle distance en bas du plein écran la feuille inférieure s'arrêtera. Une valeur de 100f, par exemple, laissera un 100px bordure en haut de la feuille inférieure lorsqu'elle est complètement développée. La valeur par défaut pour le décalage étendu est zéro.

Je n'ai connaissance d'aucun comportement qui isFitToContents == false introduit d'autres que ceux mentionnés ci-dessus.

Donc, étant donné ces exigences, pouvons-nous façonner une feuille inférieure qui se déplace entre la hauteur de l'aperçu et la hauteur totale tout en spécifiant isFitToContents == true évitant ainsi le problème de la "demi-hauteur"? Il n'y a aucune exigence pour un décalage étendu non nul, nous n'avons donc pas à nous en soucier.

Voici une courte application de démonstration démontrant que nous pouvons répondre à ces exigences avec la structure de feuille inférieure droite:

enter image description here

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>

Si nous avons une longue feuille inférieure, la structure suivante fonctionne pour la faire défiler:

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>
3
Cheticamp

enter image description here

si vous voulez essayer ci-dessus comme dans l'image, vous pouvez suivre le code ci-dessous, que cela vous aide !!!

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

J'ai eu un cas d'utilisation similaire où la disposition devait être un tiers de la hauteur. J'ai essayé ce qui suit et cela a très bien fonctionné.

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

J'ai dû les modifier dynamiquement, j'ai donc défini ce qui suit sur la feuille inférieure, mais vous pouvez également le faire en xml:

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

Pour le rejet, j'ai ajouté une animation à mon fragment en utilisant la fonction suivante:

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

J'espère que cela t'aides

1
Saurabh

essayez de définir un addBottomSheetCallback sur votre BottomSheetBehavior, et lorsque vous détectez un état STATE_HALF_EXPANDED, appelez setState(STATE_HIDDEN) donc chaque fois que la feuille inférieure essaie d'atteindre l'état à mi-chemin , ça va juste se fermer.

1
marmor

Essayez de définir BottomSheetBehavior.setHalfExpandedRatio(0f) . Il n'y a pas grand-chose d'autre qui pourrait affecter STATE_HALF_EXPANDED, à moins de définir explicitement l'état avec . setState () . Il devrait également être possible de créer un Behavior personnalisé, qui étend CoordinatorLayout.Behavior<View> et n'a pas STATE_HALF_EXPANDED. par exemple. Tout intercepter avec des comportements de coordinateur .

1
Martin Zeitler

J'ai essayé différentes manières, mais aucune technique ne fonctionnait parfaitement. J'ai essayé d'intercepter des événements dans BottomSheetBehavior.BottomSheetCallback {} Et j'ai appelé dismiss() sur la base d'une logique personnalisée, mais cela a provoqué une secousse.

Donc, enfin, dans mon BottomSheetDialogFragment j'ai ajouté bottomSheetBehavior.isDraggable = false et cela a provoqué un glissement de la feuille inférieure par le toucher Et, j'ai géré le rejet de la boîte de dialogue par moi-même. sur la boîte de dialogue de zone vide de toute façon être rejeté.

Notez que la feuille inférieure se développe toujours avec une animation. C'est vraiment génial!

remplacer le fun onCreateDialog (SavedInstanceState: Bundle?): Dialogue {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
}
0
Rahul Rastogi