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