web-dev-qa-db-fra.com

Désactiver le glissement de l'utilisateur sur la feuille inférieure

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>

69
Abubakar Oladeji

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.

47
Vitalii Obideiko

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

45

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!

28
James Davis

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

20
Ray W

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

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

      }
});
5
Kaushik R

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.

5

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);
}
4
Sergei K

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

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.

2
chrisw

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

    }
};
2
Deepesh

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
}
1
Jamal
  1. Copiez BottomSheetDialog dans votre projet et renommez MyBottomSheetDialog
  2. ajouter getBottomSheetBehavior à MyBottomSheetDialog
  3. utilisez MyBottomSheetDialog à la place BottomSheetDialog
  4. bottomSheetBehavior.setBottomSheetCallback

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

        }
1
aotian16

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 .

1
Rodrigo Queiroz

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.

1
Hashem Jahangiri

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
    }

    ...
}
1
Sattar Hummatli
    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();
0
SRBhagwat

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();.

0
rana_sadam

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
    }
}
0
pz64_

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
0
Taulant Loshi

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

            }
        });
0
Surendar D

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

}
  • bottomsheet.xml
<?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>
  • activity_main.xml
<?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>
  • MainActivity.Java
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);
    }
}

First ScreenSecond Screen

0
Shahadat Hossain