J'essaie de désactiver l'utilisateur en faisant glisser BottomSheet
. La raison pour laquelle je veux désactiver est deux choses. 1. Cela empêche la ListView
de faire défiler l'écran vers le bas, 2. Je ne veux pas que les utilisateurs ignorent en utilisant le glissement mais avec un bouton sur la BottomSheetView
. C'est ce que j'ai fait
bottomSheetBehavior = BottomSheetBehavior.from(bottomAnc);
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
//Log.e("BottomSheet", "Expanded");
} else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
//Log.e("BottomSheet", "Collapsed");
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// React to dragging events
bottomSheet.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
return false;
default:
return true;
}
}
});
}
});
Le bottomSheetLayout
<?xml version="1.0" encoding="utf-8"?><FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/white"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="@string/bottom_sheet_behavior"
Android:id="@+id/bottomSheet">
<Android.support.v7.widget.CardView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:elevation="10dp">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="horizontal"
Android:gravity="center_vertical">
<TextView
Android:id="@+id/text1"
Android:layout_width="0dp"
Android:layout_height="wrap_content"
Android:layout_weight="1"
Android:text="Order Items"
Android:layout_margin="16dp"
Android:textAppearance="@Android:style/TextAppearance.Large"/>
<Button
Android:layout_width="50dp"
Android:layout_height="wrap_content"
Android:layout_marginRight="5dp"
Android:background="@drawable/bg_accept"/>
<Button
Android:layout_width="50dp"
Android:layout_height="wrap_content"
Android:layout_marginRight="8dp"
Android:background="@drawable/bg_cancel"/>
</LinearLayout>
<ListView
Android:id="@+id/item_edit"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/white"
Android:divider="@color/md_divider_black"
Android:dividerHeight="1dp"/>
</LinearLayout>
</Android.support.v7.widget.CardView>
Cela peut ne plus être pertinent, mais je vais le laisser ici:
import Android.content.Context;
import Android.support.design.widget.BottomSheetBehavior;
import Android.support.design.widget.CoordinatorLayout;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.view.View;
/**
* Created by vitaliiobideiko on 10/5/16.
*/
public class UserLockBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
public UserLockBottomSheetBehavior() {
super();
}
public UserLockBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
return false;
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
return false;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
return false;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {}
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {
return false;
}
}
Il désactive toutes les actions des utilisateurs, il peut être utilisé lorsque vous souhaitez contrôler BottomSheet uniquement par programme. Vous pouvez le modifier et créer un indicateur booléen pour appeler des méthodes super
au lieu de return false
.
vérifiez l'état dans la méthode onStateChanged
de setBottomSheetCallback
si l'état est BottomSheetBehavior.STATE_DRAGGING
, puis remplacez-le par BottomSheetBehavior.STATE_EXPANDED
afin que vous puissiez arrêter STATE_DRAGGING
par utilisateur. comme ci-dessous
final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
utilisez le bouton pour ouvrir la feuille inférieure fermée comme ci-dessous
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
} else {
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
});
ne pas utiliser setPeekHeight
ou app:behavior_peekHeight
par dessus, vous pouvez atteindre votre objectif
Bon, alors la réponse acceptée n'a pas fonctionné pour moi. Cependant, la { réponse de Виталий Обидейко } _ a inspiré ma solution finale.
Tout d'abord, j'ai créé le BottomSheetBehavior personnalisé suivant. Il annule toutes les méthodes impliquant le toucher et renvoie false (ou n'a rien fait) s'il est verrouillé. Sinon, il agit comme un BottomSheetBehavior normal. Cela désactive la capacité de l'utilisateur à faire glisser le curseur et n'affecte pas le changement d'état dans le code.
LockableBottomSheetBehavior.Java
public class LockableBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean mLocked = false;
public LockableBottomSheetBehavior() {}
public LockableBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setLocked(boolean locked) {
mLocked = locked;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
boolean handled = false;
if (!mLocked) {
handled = super.onInterceptTouchEvent(parent, child, event);
}
return handled;
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
boolean handled = false;
if (!mLocked) {
handled = super.onTouchEvent(parent, child, event);
}
return handled;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
boolean handled = false;
if (!mLocked) {
handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
return handled;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {
if (!mLocked) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
if (!mLocked) {
super.onStopNestedScroll(coordinatorLayout, child, target);
}
}
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {
boolean handled = false;
if (!mLocked) {
handled = super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
}
return handled;
}
}
Voici un exemple d'utilisation. Dans mon cas, j'en avais besoin pour que la feuille inférieure soit verrouillée lors de l'agrandissement.
activité_home.xml
<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout
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:layout_width="match_parent"
Android:layout_height="wrap_content">
<Android.support.design.widget.CollapsingToolbarLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap"
app:titleEnabled="false"/>
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"/>
</Android.support.design.widget.AppBarLayout>
<!-- Use layout_behavior to set your Behavior-->
<Android.support.v7.widget.RecyclerView
Android:id="@+id/recyclerview"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layoutManager="Android.support.v7.widget.LinearLayoutManager"
app:layout_behavior="com.myapppackage.LockableBottomSheetBehavior"/>
</Android.support.design.widget.CoordinatorLayout>
HomeActivity.Java
public class HomeActivity extends AppCompatActivity {
BottomSheetBehavior mBottomSheetBehavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setAdapter(new SomeAdapter());
mBottomSheetBehavior = BottomSheetBehavior.from(recyclerView);
mBottomSheetBehavior.setBottomSheetCallback(new MyBottomSheetCallback());
}
class MyBottomSheetCallback extends BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
if (mBottomSheetBehavior instanceof LockableBottomSheetBehavior) {
((LockableBottomSheetBehavior) mBottomSheetBehavior).setLocked(true);
}
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
});
}
J'espère que cela aide à dissiper beaucoup de confusion!
J'ai fini par écrire une solution de contournement pour résoudre ce cas d'utilisation de la désactivation dynamique de l'utilisateur en faisant glisser, dans lequel BottomSheetBehavior est sous-classé pour remplacer onInterceptTouchEvent et pour l'ignorer lorsqu'un indicateur personnalisé (dans ce cas, mAllowUserDragging) est défini sur false
import Android.content.Context;
import Android.support.design.widget.BottomSheetBehavior;
import Android.support.design.widget.CoordinatorLayout;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.view.View;
public class WABottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean mAllowUserDragging = true;
/**
* Default constructor for instantiating BottomSheetBehaviors.
*/
public WABottomSheetBehavior() {
super();
}
/**
* Default constructor for inflating BottomSheetBehaviors from layout.
*
* @param context The {@link Context}.
* @param attrs The {@link AttributeSet}.
*/
public WABottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setAllowUserDragging(boolean allowUserDragging) {
mAllowUserDragging = allowUserDragging;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!mAllowUserDragging) {
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
Et dans votre mise en page XML:
<FrameLayout
Android:id="@+id/bottom_sheet_frag_container"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:behavior_hideable="true"
app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
app:elevation="@dimen/bottom_sheet_elevation"
app:layout_behavior="com.example.ray.WABottomSheetBehavior" />
Jusqu'à présent, il s'agit de la solution la plus cohérente pour désactiver le glisser-déposer des utilisateurs à la demande.
Toutes les autres solutions reposant sur le déclenchement d'un autre appel setState dans le rappel onStateChanged ont abouti à un mauvais état de BottomSheet ou à d'importants problèmes UX (dans le cas de la publication de l'appel setState dans un Runnable).
J'espère que ça aide quelqu'un :)
Rayon
La réponse acceptée ne fonctionne pas sur le premier appareil de test que j'utilise. Et le rebond n'est pas lisse. Il semble préférable de définir l'état sur STATE_EXPANDED uniquement après qu'un utilisateur a relâché le glissement. Ce qui suit est ma version:
final BottomSheetBehavior behavior = BottomSheetBehavior.from(findViewById(R.id.bottomSheet));
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState > BottomSheetBehavior.STATE_DRAGGING)
bottomSheet.post(new Runnable() {
@Override public void run() {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
Ajoutez ce code à BottomSheetBehavior object. Le dragage sera désactivé . Fonctionne bien pour moi.
final BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent());
behavior.setHideable(false);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
Pour verrouiller la feuille inférieure et éviter à l'utilisateur de la glisser, c'est ce que j'ai fait.
public void showBottomSheet() {
bsb.setHideable(false);
bsb.setState(BottomSheetBehavior.STATE_EXPANDED);
}
public void hideBottomSheet() {
bsb.setHideable(true);
bsb.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
Cela fonctionne assez bien pour moi.
Un moyen facile de verrouiller le glissement est setPeekHeight comme pour la hauteur de la vue .
private LinearLayout bottomSheet;
private BottomSheetBehavior bottomBehavior;
@Override
public void onResume() {
super.onResume();
bottomBehavior = BottomSheetBehavior.from((bottomSheet);
bottomBehavior.setPeekHeight(bottomSheet.getHeight());
bottomBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
Vous n'avez pas besoin de bloquer tous les événements lorsque la feuille du bas est désactivée. Vous ne pouvez bloquer que l'événement ACTION_MOVE. C'est pourquoi utilisez un comportement de fond personnalisé comme celui-ci
public class BottomSheetBehaviorWithDisabledState<V extends View> extends BottomSheetBehavior<V> {
private boolean enable = true;
/**
* Default constructor for instantiating BottomSheetBehaviors.
*/
public BottomSheetBehaviorWithDisabledState() {
super();
}
/**
* Default constructor for inflating BottomSheetBehaviors from layout.
*
* @param context The {@link Context}.
* @param attrs The {@link AttributeSet}.
*/
public BottomSheetBehaviorWithDisabledState(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setEnable(boolean enable){
this.enable = enable;
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!enable && event.getAction() == MotionEvent.ACTION_MOVE){
return false;
}
return super.onInterceptTouchEvent(parent, child, event);
}
}
Réponse tardive, mais, c’est ce qui a fonctionné pour moi, ce qui est un peu différent de ce que d’autres ont suggéré.
Vous pouvez essayer de définir la propriété cancelable
sur false, c.-à-d.
setCancelable(false);
et puis en manipulant manuellement les événements où vous voudriez fermer la boîte de dialogue dans la méthode setupDialog
.
@Override
public void setupDialog(final Dialog dialog, final int style) {
// handle back button
dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(final DialogInterface dialog, final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
dialog.dismiss();
}
return true;
}
});
// handle touching outside of the dialog
final View touchOutsideView = getDialog().getWindow().getDecorView().findViewById(Android.support.design.R.id.touch_outside);
touchOutsideView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
dialog.dismiss();
}
});
}
Cela fonctionne avec un ListView à l'intérieur du fragment de dialogue, qui était où je devenais un peu coincé avec d'autres solutions.
J'ai trouvé une solution incroyable. Le problème initial était qu'une fois que bottomSheet était dans l'état HIDDEN, il n'apparaissait pas à bottomSheetDialog.show () . Mais je voulais que la boîte de dialogue soit visible sur la méthode show () et je voulais également permettre à l'utilisateur de la glisser vers le bas de sorte qu'il se sent comme feuille de fond. Ci-dessous est ce que j'ai fait ..
BottomSheetDialog itemTypeDialog = new BottomSheetDialog(this);
View bottomSheetView = getLayoutInflater().inflate(R.layout.dialog_bottomsheet, null);
itemTypeDialog.setContentView(bottomSheetView);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from((View) bottomSheetView.getParent());
bottomSheetBehavior.setBottomSheetCallback(bottomSheetCallback); // You can also attach the listener here itself.
BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
Log.d(TAG, "BottomSheetCallback: " + newState);
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
itemTypeDialog.dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
Ceci est essentiellement la version kotlin de la bonne réponse en haut:
class LockedBottomSheetBehavior<V : View>(context: Context, attrs: AttributeSet) :
BottomSheetBehavior<V>(context, attrs) {
companion object {
fun <V : View> from(view: V): LockedBottomSheetBehavior<*> {
val params = view.layoutParams as? CoordinatorLayout.LayoutParams
?: throw IllegalArgumentException("The view is not a child of CoordinatorLayout")
return params.behavior as? LockedBottomSheetBehavior<*>
?: throw IllegalArgumentException(
"The view is not associated with BottomSheetBehavior")
}
}
override fun onInterceptTouchEvent(
parent: CoordinatorLayout,
child: V, event: MotionEvent
) = false
override fun onTouchEvent(
parent: CoordinatorLayout,
child: V,
event: MotionEvent
) = false
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
directTargetChild: View,
target: View,
axes: Int,
type: Int) = false
override fun onNestedPreScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
target: View,
dx: Int,
dy: Int,
consumed: IntArray,
type: Int) {
}
override fun onStopNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: V,
target: View,
type: Int) {
}
override fun onNestedPreFling(
coordinatorLayout: CoordinatorLayout,
child: V,
target: View,
velocityX: Float,
velocityY: Float
) = false
}
BottomSheetDialog
dans votre projet et renommez MyBottomSheetDialog
getBottomSheetBehavior
à MyBottomSheetDialog
MyBottomSheetDialog
à la place BottomSheetDialog
code comme ça
public class MyBottomSheetDialog extends AppCompatDialog {
// some code
public BottomSheetBehavior<FrameLayout> getBottomSheetBehavior() {
return mBehavior;
}
// more code
dans votre code
final BottomSheetBehavior<FrameLayout> bottomSheetBehavior = myBottomSheetDialog.getBottomSheetBehavior();
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
Voici une version de travail de la solution principale de Kotlin:
import Android.support.design.widget.BottomSheetBehavior
import Android.support.design.widget.CoordinatorLayout
import Android.view.MotionEvent
import Android.view.View
class CustomBottomSheetBehavior<V : View> : BottomSheetBehavior<V>() {
@Suppress("UNCHECKED_CAST")
companion object {
fun <V : View> from(view: V): CustomBottomSheetBehavior<V> {
val params = view.layoutParams as? CoordinatorLayout.LayoutParams ?:
throw IllegalArgumentException("The view is not a child of CoordinatorLayout")
params.behavior as? BottomSheetBehavior<V> ?:
throw IllegalArgumentException("The view is not associated with BottomSheetBehavior")
params.behavior = CustomBottomSheetBehavior<V>()
return params.behavior as CustomBottomSheetBehavior<V>
}
}
override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
return false
}
override fun onTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean {
return false
}
override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
return false
}
override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {}
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) {}
override fun onNestedPreFling(coordinatorLayout: CoordinatorLayout, child: V, target: View, velocityX: Float, velocityY: Float): Boolean {
return false
}
}
Ensuite, chaque fois que vous voulez utiliser:
val bottomSheetBehavior by lazy {
CustomBottomSheetBehavior.from(bottom_sheet_main)
}
Le bottom_sheet_main
est la vue réelle qui utilise/ Kotlin Android Extensions .
définissez bottomSheet onClickListener sur null.
bottomSheet.setOnClickListener(null);
cette ligne désactive toute action sur bottomSheet uniquement et n'a aucun effet sur la vue interne.
Un échantillon avec BottomSheetDialogFragment. Ça fonctionne parfaitement.
class FragMenuBDrawer : BottomSheetDialogFragment() {
...
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.setOnShowListener {
val bottomSheet = (it as BottomSheetDialog).findViewById<View>(com.google.Android.material.R.id.design_bottom_sheet) as FrameLayout?
val behavior = BottomSheetBehavior.from(bottomSheet!!)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
}
// Do something with your dialog like setContentView() or whatever
return dialog
}
...
}
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.bottomsheet_view_profile_image, null);
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(view);
dialog.setCancelable(false);
BottomSheetBehavior behavior = BottomSheetBehavior
.from(((View) view.getParent()));
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
dialog.show();
J'ai le même problème dans BottomSheetDialogFragment et j'applique de nombreuses solutions en utilisant un comportement de dialogue, mais aucune de celles-ci ne résout mon problème, puis je l'ai résolu en définissant setCancelable(false);
au moment de l'initialisation du dialogue.
DialogEndRide dialogCompleteRide = new DialogEndRide();
dialogCompleteRide.setCancelable(false);
dialogCompleteRide.show(getChildFragmentManager(), "");
Ceci désactivera les gestes sur BottomSheetDialogFragment et vous pourrez fermer la boîte de dialogue par programme en utilisant la fonction dismiss();
.
Ajuster la valeur peakHeight
a fonctionné pour moi.
Je règle la hauteur maximale comme la hauteur de la feuille de dessous si elle est étendue.
private val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_EXPANDED)
bottomSheetBehavior.peekHeight = bottomSheet.height
}
}
Juste au cas où quelqu'un pourrait peut-être aider à l'avenir, la meilleure solution pour moi était de créer un nouveau style et d'attribuer:
<style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog">
<item name="Android:windowCloseOnTouchOutside">false</item>
</style>
puis à l'intérieur de la classe BottomSheetDialogFragment ont remplacé la méthode:
override fun getTheme(): Int = R.style.BottomSheetDialogTheme
Essaye ça.
1) Créez la feuille de fond et déclarez la variable dans votre classe Java comme
private BottomSheetBehavior sheetBehavior;
2) sheetBehavior = BottomSheetBehavior.from(bottomSheet);
3) Dans la fonction de rappel de la feuille inférieure, ajoutez les lignes suivantes.
sheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
Log.d(TAG, "-------------- STATE_HIDDEN");
break;
case BottomSheetBehavior.STATE_EXPANDED: {
Log.d(TAG, "-------------- STATE_EXPANDED");
}
break;
case BottomSheetBehavior.STATE_COLLAPSED: {
Log.d(TAG, "-------------- STATE_COLLAPSED");
}
break;
case BottomSheetBehavior.STATE_DRAGGING:
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
break;
case BottomSheetBehavior.STATE_SETTLING:
Log.d(TAG, "-------------- STATE_SETTLING");
break;
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
Au début, je veux juste remercier tous ceux qui ont essayé de donner une réponse. J'écris juste cette réponse en résolvant ce problème comme je le souhaite. Je vais décrire comment je fais cela étape par étape en prenant l’aide d’ici.
Visualisation: Après avoir cliqué sur le bouton Show BottomSheet
, vous verrez le deuxième écran . Maintenant, vous verrez que BottomSheet est juste verrouillé pour faire glisser . Mais si vous cliquez sur la liste des pays , le BottomSheet sera masqué. Telle était la description maintenant, creusons dans le code.
Au début, ajoutez la bibliothèque de support de conception à votre fichier build.gradle :
implémentation 'com.Android.support:design:28.0.0'
UserLockBottomSheetBehavior.Java : Crédit: James Davis (Homme de remerciement)
public class UserLockBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
public UserLockBottomSheetBehavior() {
super();
}
public UserLockBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
return false;
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
return false;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) {
return false;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) {
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
}
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY) {
return false;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/bottomSheet"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_gravity="center_vertical"
Android:orientation="vertical"
app:behavior_hideable="true"
app:layout_behavior="com.samsolution.custombottomsheet.UserLockBottomSheetBehavior">
<RelativeLayout
Android:id="@+id/minimizeLayout"
Android:background="@color/colorPrimary"
Android:layout_width="match_parent"
Android:layout_height="?android:attr/actionBarSize">
<TextView
Android:layout_centerHorizontal="true"
Android:padding="16dp"
Android:layout_width="wrap_content"
Android:layout_height="?android:attr/actionBarSize"
Android:gravity="center_horizontal|center"
Android:text="Country List"
Android:textColor="#FFFFFF"
Android:textStyle="bold" />
</RelativeLayout>
<Android.support.v7.widget.CardView
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<ListView
Android:id="@+id/homeCountryList"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</Android.support.v7.widget.CardView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="#FFFFFF"
tools:context=".MainActivity">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical"
Android:layout_gravity="center"
Android:onClick="showCountryListFromBottomSheet">
<Button
Android:layout_gravity="center"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:background="@Android:color/holo_red_light"
Android:onClick="showCountryListFromBottomSheet"
Android:padding="16dp"
Android:text="Show BottomSheet"
Android:textAllCaps="false"
Android:textColor="#ffffff" />
</LinearLayout>
<include layout="@layout/bootomsheet" />
</Android.support.design.widget.CoordinatorLayout>
public class MainActivity extends AppCompatActivity {
private BottomSheetBehavior<LinearLayout> bottomSheetBehavior; // BottomSheet Instance
LinearLayout bottomsheetlayout;
String[] list = {"A", "B", "C", "D", "A", "B", "C", "D","A", "B", "C", "D","A", "B", "C", "D","A", "B", "C", "D"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomsheetlayout = findViewById(R.id.bottomSheet);
bottomSheetBehavior = BottomSheetBehavior.from(bottomsheetlayout);
ListView listView = findViewById(R.id.homeCountryList);
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,Android.R.layout.simple_list_item_1,list);
listView.setAdapter(adapter);
bottomSheetHide(); //BottomSheet get hide first time
RelativeLayout minimizeLayoutIV; // It will hide the bottomSheet Layout
minimizeLayoutIV = findViewById(R.id.minimizeLayout);
minimizeLayoutIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bottomSheetHide();
}
});
}
public void showCountryListFromBottomSheet(View view) {
bottomSheetBehavior.setHideable(false);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
public void bottomSheetHide(){
bottomSheetBehavior.setHideable(true);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
}