sociales redes mediatica informacion android android-support-library android-support-design

android - redes - informacion mediatica



Deshabilitar al usuario arrastrando en la hoja inferior (22)

  1. Copie BottomSheetDialog a su proyecto y cambie el nombre a MyBottomSheetDialog
  2. agregar getBottomSheetBehavior a MyBottomSheetDialog
  3. use MyBottomSheetDialog lugar de BottomSheetDialog
  4. bottomSheetBehavior.setBottomSheetCallback

código como este

public class MyBottomSheetDialog extends AppCompatDialog { // some code public BottomSheetBehavior<FrameLayout> getBottomSheetBehavior() { return mBehavior; } // more code

en tu código

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

Estoy tratando de deshabilitar el arrastre del usuario en BottomSheet . La razón por la que quiero desactivar es dos cosas. 1. ListView desplace hacia abajo, 2. No quiero que los usuarios descarten mediante el arrastre pero con un botón en BottomSheetView . Esto es lo que he hecho

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

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


En caso de que alguien pueda ayudar en el futuro, la mejor solución para mí fue crear un nuevo estilo y asignar:

<style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog"> <item name="android:windowCloseOnTouchOutside">false</item> </style>

y luego dentro de la clase BottomSheetDialogFragment anuló el método:

override fun getTheme(): Int = R.style.BottomSheetDialogTheme


Una muestra con BottomSheetDialogFragment. Funciona perfectamente

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


Agregue este código al objeto BottomSheetBehavior . El arrastre se desactivará. Funciona bien para mi.

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


Ahora ya no puede ser relevante, pero lo dejaré aquí:

import android.content.Context import android.util.AttributeSet import androidx.coordinatorlayout.widget.CoordinatorLayout import android.view.MotionEvent import android.view.View import com.google.android.material.bottomsheet.BottomSheetBehavior @Suppress("unused") class LockableBottomSheetBehavior<V : View> : BottomSheetBehavior<V> { constructor() : super() constructor(context: Context, attrs: AttributeSet) : super(context, attrs) var swipeEnabled = true override fun onInterceptTouchEvent( parent: CoordinatorLayout, child: V, event: MotionEvent ): Boolean { return if (swipeEnabled) { super.onInterceptTouchEvent(parent, child, event) } else { false } } override fun onTouchEvent(parent: CoordinatorLayout, child: V, event: MotionEvent): Boolean { return if (swipeEnabled) { super.onTouchEvent(parent, child, event) } else { false } } override fun onStartNestedScroll( coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int ): Boolean { return if (swipeEnabled) { super.onStartNestedScroll( coordinatorLayout, child, directTargetChild, target, axes, type ) } else { false } } override fun onNestedPreScroll( coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int ) { if (swipeEnabled) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type) } } override fun onStopNestedScroll( coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int ) { if (swipeEnabled) { super.onStopNestedScroll(coordinatorLayout, child, target, type) } } override fun onNestedPreFling( coordinatorLayout: CoordinatorLayout, child: V, target: View, velocityX: Float, velocityY: Float ): Boolean { return if (swipeEnabled) { super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY) } else { false } } }

Y úsalo en tu archivo xml:

app:layout_behavior="com.your.package.LockableBottomSheetBehavior"

Deshabilita todas las acciones de los usuarios, se puede usar cuando desee controlar BottomSheet solo mediante programación.


Ajustar el valor de peakHeight funcionó para mí.

Establezco la altura máxima como la altura de la hoja inferior si se expande.

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


Al principio, solo quiero agradecer a todos los que intentaron dar una respuesta. Solo estoy escribiendo esta respuesta resolviendo este problema como quiero. Voy a describir cómo lo hago paso a paso tomando ayuda de aquí.

Visualización: después de hacer clic en el botón Show BottomSheet , verá la segunda pantalla . Ahora verá que BottomSheet está bloqueado para arrastrarlo . Pero si hace clic en la Lista de países, la Hoja inferior se ocultará. Esta fue la descripción ahora vamos a profundizar en el Código.

  • Al principio, agregue la biblioteca de soporte de diseño a su archivo build.gradle :

    implementación ''com.android.support:design:28.0.0''

  • UserLockBottomSheetBehavior.java : Crédito: (Gracias, hombre)

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


Aquí hay una versión funcional de la solución superior en 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 } }

Entonces, cuando quieras usar:

val bottomSheetBehavior by lazy { CustomBottomSheetBehavior.from(bottom_sheet_main) }

bottom_sheet_main es la vista real que usa Kotlin Android Extensions .


Esta es básicamente la versión kotlin de la respuesta correcta en la parte superior:

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 }


He encontrado una solución asombrosa. El problema inicial fue una vez que bottomSheet iba a estado OCULTADO y luego no se mostraba en bottomSheetDialog.show (). Pero quería que el cuadro de diálogo fuera visible en el método show () y también quería permitir que el usuario lo deslice hacia abajo para que se sienta como la hoja inferior. A continuación se muestra lo que hice.

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


La forma fácil de bloquear el arrastre es establecer PeekHeight igual que la altura de la vista. Por ejemplo:

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


La respuesta aceptada no funciona en el primer dispositivo de prueba que uso. Y el rebote no es suave. Parece mejor establecer el estado en STATE_EXPANDED solo después de que un usuario suelte el arrastre. La siguiente es mi versión:

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


Muy bien, entonces la respuesta aceptada no funcionó para mí. Sin embargo, la respuesta de Виталий Обидейко inspiró mi solución final.

Primero, creé el siguiente BottomSheetBehavior personalizado. Anula todos los métodos que involucran el tacto y devuelve falso (o no hizo nada) si está bloqueado. De lo contrario, actúa como un BottomSheetBehavior normal. Esto deshabilita la capacidad del usuario para arrastrar hacia abajo y no afecta el cambio de estado en el código.

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

Aquí hay un ejemplo de cómo usarlo. En mi caso, lo necesitaba para que la hoja inferior se bloqueara cuando se expandía.

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

¡Espero que esto ayude a aclarar mucha confusión!


No necesita bloquear todos los eventos cuando la hoja inferior está deshabilitada. Solo puede bloquear el evento ACTION_MOVE. Es por eso que use un comportamiento de hoja inferior personalizado como este

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


Para bloquear el BottomSheet y evitar que el usuario lo deslice, esto es lo que hice

public void showBottomSheet() { bsb.setHideable(false); bsb.setState(BottomSheetBehavior.STATE_EXPANDED); } public void hideBottomSheet() { bsb.setHideable(true); bsb.setState(BottomSheetBehavior.STATE_COLLAPSED); }

Funciona bastante bien para mi.


Prueba esto.

1) Cree una hoja inferior y declare la variable en su clase java como

private BottomSheetBehavior sheetBehavior;

2) sheetBehavior = BottomSheetBehavior.from(bottomSheet);

3) En la función de devolución de llamada de la hoja inferior, agregue las siguientes líneas.

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


Respuesta tardía, pero esto es lo que funcionó para mí, que es un poco diferente a lo que otros han sugerido.

Puede intentar establecer la propiedad cancelable en falso, es decir

setCancelable(false);

y luego manejando manualmente los eventos donde desea cerrar el diálogo en el método 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(); } }); }

Esto funciona con un ListView dentro del fragmento de diálogo, que era donde me estaba quedando un poco atascado con otras soluciones.


Tengo el mismo problema en BottomSheetDialogFragment y aplico muchas soluciones usando el comportamiento del diálogo, pero ninguno de ellos resuelve mi problema y luego lo resolví, pero establecí setCancelable(false); en el momento de la inicialización del diálogo.

DialogEndRide dialogCompleteRide = new DialogEndRide(); dialogCompleteRide.setCancelable(false); dialogCompleteRide.show(getChildFragmentManager(), "");

Esto deshabilitará el gesto en BottomSheetDialogFragment y puede descartar el diálogo mediante programación mediante el dismiss(); función.


Terminé escribiendo una solución alternativa para abordar este caso de uso de deshabilitar dinámicamente el arrastre del usuario, mediante el cual BottomSheetBehavior se subclasifica para anular onInterceptTouchEvent e ignorarlo cuando un indicador personalizado (en este caso mAllowUserDragging) se establece en falso:

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

Y en tu diseño 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" />

Hasta ahora, esta es la solución de comportamiento más consistente para deshabilitar el arrastre del usuario en la hoja inferior a pedido.

Todas las otras soluciones que se basaban en disparar otra llamada setState en la devolución de llamada onStateChanged dieron como resultado que BottomSheet se pusiera en mal estado o causara problemas de UX importantes (en el caso de publicar la llamada setState en un Runnable).

Espero que esto ayude a alguien :)

Rayo


compruebe el estado en el método onStateChanged de setBottomSheetCallback si el estado es BottomSheetBehavior.STATE_DRAGGING luego cámbielo a BottomSheetBehavior.STATE_EXPANDED esta manera puede detener STATE_DRAGGING por usuario. como abajo

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

use el botón para abrir cerrar la hoja inferior como a continuación

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

no use setPeekHeight o la app:behavior_peekHeight

por encima puedes alcanzar tu objetivo


establezca bottomSheet onClickListener en nulo.

bottomSheet.setOnClickListener(null);

esta línea deshabilita todas las acciones sobre bottomSheet solamente y no afecta a la vista interna.


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