wake-up-neo.com

Deaktivieren des Benutzers beim Ziehen auf BottomSheet

Ich versuche, das Ziehen von Benutzern auf BottomSheet zu deaktivieren. Der Grund, warum ich deaktivieren möchte, ist zwei Dinge. 1. Es verhindert, dass ListView nach unten scrollen kann. 2. Ich möchte nicht, dass Benutzer das Ziehen mit Ziehen beenden, sondern mit einem Button auf BottomSheetView. Das habe ich getan

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

Das 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

Es kann jetzt nicht mehr relevant sein, aber ich werde es hier belassen:

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

Es deaktiviert alle Benutzeraktionen. Es kann verwendet werden, wenn BottomSheet nur programmgesteuert gesteuert werden soll. Sie können es bearbeiten und ein boolesches Flag für den Aufruf von super-Methoden anstelle von return false erstellen.

47

Überprüfen Sie den Status der onStateChanged-Methode von setBottomSheetCallback. Wenn der Status BottomSheetBehavior.STATE_DRAGGING ist, ändern Sie ihn in BottomSheetBehavior.STATE_EXPANDED. Auf diese Weise können Sie STATE_DRAGGING vom Benutzer stoppen. Wie unten

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

mit der Taste öffnen Sie das untere Blatt wie unten beschrieben

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

verwenden Sie nicht setPeekHeight oder app:behavior_peekHeight

auf obige Weise können Sie Ihr Ziel erreichen

45

Na gut, also hat die akzeptierte Antwort für mich nicht funktioniert. Die Antwort von Виталий Обидейко inspirierte meine endgültige Lösung.

Zuerst habe ich das folgende benutzerdefinierte BottomSheetBehavior erstellt. Es überschreibt alle Methoden, die die Berührung betreffen, und gibt falsch zurück (oder nichts getan), wenn es gesperrt ist. Ansonsten verhält es sich wie ein normales BottomSheetBehavior. Dadurch wird das Ziehen des Benutzers durch den Benutzer deaktiviert, und das Ändern des Status im Code wird nicht beeinflusst.

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;

    }
}

Hier ist ein Beispiel, wie man es benutzt. In meinem Fall brauchte ich es, damit das untere Blatt beim Erweitern gesperrt wurde.

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

Hoffe, das hilft, viel Verwirrung zu beseitigen!

28
James Davis

Am Ende habe ich eine Problemumgehung geschrieben, um den Anwendungsfall der dynamischen Deaktivierung des Ziehens von Benutzern zu beheben. BottomSheetBehavior ist eine Unterklasse, die onInterceptTouchEvent überschreibt und ignoriert, wenn ein benutzerdefiniertes Flag (in diesem Fall mAllowUserDragging) auf false gesetzt ist:

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

Und in deiner Layout-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" />

Bisher ist dies die konsistenteste Lösung, um das Ziehen von Benutzern auf dem unteren Blatt bei Bedarf zu deaktivieren.

Alle anderen Lösungen, die sich darauf stützten, einen anderen setState-Aufruf im onStateChanged-Callback abzufeuern, führten dazu, dass BottomSheet in einen fehlerhaften Zustand geriet oder erhebliche UX-Probleme verursachte (falls der setState-Aufruf in einer ausführbaren Datei veröffentlicht wurde).

Hoffe das hilft jemandem :)

Strahl

20
Ray W

Die akzeptierte Antwort funktioniert auf dem ersten von mir verwendeten Testgerät nicht. Und der Absprung ist nicht glatt. Es scheint besser, den Status auf STATE_EXPANDED zu setzen, nachdem ein Benutzer das Ziehen freigegeben hat. Folgendes ist meine 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

Fügen Sie diesen Code zu BottomSheetBehavior object hinzu. Ziehen wird deaktiviert .. __ Funktioniert gut für mich. 

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

Um das BottomSheet zu sperren und zu vermeiden, dass der Benutzer es auswischt, habe ich dies getan

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

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

Das funktioniert ganz gut für mich.

Die einfache Methode zum Sperren des Ziehens ist wie für Ansichtshöhe ..

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

Sie müssen nicht alle Ereignisse blockieren, wenn das unterste Blatt deaktiviert ist. Sie können nur das ACTION_MOVE-Ereignis blockieren. Verwenden Sie daher das Verhalten des benutzerdefinierten unteren Blattes

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

Späte Antwort, aber das hat bei mir funktioniert, was ein bisschen anders ist als das, was andere vorgeschlagen haben.

Sie könnten versuchen, die cancelable-Eigenschaft auf false zu setzen, d. H.

setCancelable(false);

und behandeln Sie dann manuell die Ereignisse, bei denen Sie den Dialog in der setupDialog-Methode abbrechen möchten.

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

Dies funktioniert mit einer ListView innerhalb des Dialogfragments, bei der ich bei anderen Lösungen ein wenig hängen blieb.

2
chrisw

Ich habe eine erstaunliche Lösung gefunden. Das anfängliche Problem war, als bottomSheet in den HIDDEN-Status ging, dann wurde es nicht in bottomSheetDialog.show () .. angezeigt. Aber ich wollte, dass das Dialogfeld in der show () -Methode sichtbar wird, und der Benutzer sollte es auch ermöglichen, es zu streichen nach unten, so dass es sich anfühlt wie unteres Blatt. Unten ist was ich getan habe ..

    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

Dies ist im Grunde die Kotlin-Version der richtigen Antwort oben:

    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. Kopieren Sie BottomSheetDialog in Ihr Projekt und benennen Sie sie in MyBottomSheetDialog um.
  2. getBottomSheetBehavior zu MyBottomSheetDialog hinzufügen
  3. verwenden Sie stattdessen MyBottomSheetDialogBottomSheetDialog
  4. bottomSheetBehavior.setBottomSheetCallback

code wie folgt

public class MyBottomSheetDialog extends AppCompatDialog {

    // some code

    public BottomSheetBehavior<FrameLayout> getBottomSheetBehavior() {
        return mBehavior;
    }

    // more code

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

Hier ist eine funktionierende Version der Top-Lösung in 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
    }
}

Dann wann immer Sie möchten:

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

Der bottom_sheet_main ist die tatsächliche Ansicht mit Kotlin Android Extensions .

1
Rodrigo Queiroz

setzen Sie bottomSheet onClickListener auf null.

bottomSheet.setOnClickListener(null);

diese Zeile deaktiviert alle Aktionen nur für bottomSheet und wirkt sich nicht auf die Innenansicht aus.

1

Ein Beispiel mit BottomSheetDialogFragment. Das funktioniert einwandfrei.

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

Ich habe das gleiche Problem in BottomSheetDialogFragment und wende viele Lösungen unter Verwendung des Dialogverhaltens an, aber keines davon löst mein Problem, und dann habe ich es behoben, aber setCancelable(false); zum Zeitpunkt der Initialisierung des Dialogs festgelegt.

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

Dadurch wird die Geste in BottomSheetDialogFragment deaktiviert, und Sie können den Dialog mit der Funktion dismiss(); programmgesteuert schließen.

0
rana_sadam

Das Anpassen des peakHeight-Werts hat für mich funktioniert.

Ich habe die Peakhöhe als Höhe der unteren Platte festgelegt, wenn sie erweitert wird.

    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_

Für den Fall, dass vielleicht jemand in der Zukunft helfen kann, war die beste Lösung für mich die Erstellung eines neuen Stils und das Zuweisen von:

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

und dann in der BottomSheetDialogFragment-Klasse die Methode überschreiben:

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

Versuche dies.

1) Erstellen Sie ein unteres Blatt und deklarieren Sie die Variable in Ihrer Java-Klasse wie folgt

private BottomSheetBehavior sheetBehavior;

2) sheetBehavior = BottomSheetBehavior.from(bottomSheet);

3) Fügen Sie im unteren Bereich der Callback-Funktion die folgenden Zeilen hinzu.

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

Zuerst möchte ich mich bei allen bedanken, die versucht haben, eine Antwort zu geben. Ich schreibe nur diese Antwort, indem ich dieses Problem so löse, wie ich es möchte. Ich werde beschreiben, wie ich das Schritt für Schritt mache, indem ich von hier aus Hilfe nehme.

Visualisierung: Nach Anklicken des Buttons Show BottomSheet erscheint der zweite Bildschirm . Jetzt sehen Sie, dass BottomSheet nur für das Ziehen gesperrt ist . Wenn Sie jedoch auf die Länderliste klicken, wird das BottomSheet ausgeblendet. Dies war die Beschreibung. Lassen Sie uns nun in den Code eintauchen.

  • Fügen Sie zunächst die Design-Support-Bibliothek zu Ihrer build.gradle-Datei hinzu:

    implementierung 'com.Android.support:design:28.0.0'

  • UserLockBottomSheetBehavior.Java : Bildnachweis: James Davis (Dankeschön)

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