I am using the support
- FloatingActionButton
- Snackbar
- CoordinatorLayout
I need the CoordinatorLayout so that if SnackBar is shown the FloatingActionButton moves up to make room for the Snackbar. For better understanding check this video.
I am using SnackBar for double-back to exit the application, but the SnackBar can be dismissed.
Is there a way to disable the dismiss on the SnackBar?
Snackbar snackbar = Snackbar.make(view, R.string.press_back_again_to_exit, Snackbar.LENGTH_SHORT);
snackbar.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v)
{
}
});
snackbar.setActionTextColor(getResources().getColor(R.color.white));
View view = snackbar.getView();
view.setBackgroundColor(getResources().getColor(R.color.orange_warning));
snackbar.show();
Layout
<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.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:fitsSystemWindows="true">
<com.sothree.slidinguppanel.SlidingUpPanelLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:umanoFadeColor="@android:color/transparent"
sothree:umanoPanelHeight="100dp"
sothree:umanoShadowHeight="4dp">
<!-- Toolbar and main content -->
<LinearLayout
android:id="@+id/toolbar_and_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/toolbar"/>
<!-- Your content layout -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>
<!-- Sliding up panel layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/darker_grey"
android:orientation="vertical">
...
</LinearLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
<!-- Navigation drawer -->
<ExpandableListView
android:id="@+id/lv_left_drawer"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/white"
android:childDivider="@android:color/transparent"
android:clickable="true"
android:divider="@color/divider_color"
android:dividerHeight="0.6dp"
android:fadeScrollbars="true"
android:groupIndicator="@null"
android:listSelector="@drawable/button_drawer_child_selector"
android:scrollbarSize="0dp"/>
</android.support.v4.widget.DrawerLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:layout_marginBottom="@dimen/floating_action_button_margin"
android:layout_marginRight="@dimen/floating_action_button_margin"
android:src="@drawable/ic_add"
android:visibility="invisible"
app:backgroundTint="@color/orange"
app:borderWidth="0dp"
app:elevation="6dp"
app:fabSize="normal"/>
</android.support.design.widget.CoordinatorLayout>
P.S.
I am aware of this GitHub library, that has this functionality, but is there a 'native' way to do it?
You can alter the duration of Snackbar to be shown. It will be similar to disable dismiss.
int LENGTH_INDEFINITE Show the Snackbar indefinitely.
Check docs.
if it does not work
For this then there is only one way, Implement Your custom Snackbar and override dismiss()
method and in that do nothing. :) As dismiss()
is a public API.
The answer about just using LENGTH_INDEFINITE
is not sufficient.
It is only non-dismissable when the Snackbar is no child of CoordinatorLayout
.
When it is a child, you can still swipe away the SnackBar.
What you can do in that case is listen for the dismiss swipe and simply re-show the Snackbar.
public void showAnnoyingSnackBar(View root, String text) {
Snackbar.make(root, text, Snackbar.LENGTH_INDEFINITE)
.setCallback(new Snackbar.Callback() {
@Override public void onDismissed(Snackbar snackbar, int event) {
// recursively call this method again when the snackbar was dismissed through a swipe
if (event == DISMISS_EVENT_SWIPE) showAnnoyingSnackBar(root, text);
}
})
.show();
}
I noticed that when show() method is called, SnackbarLayout is not fully initialised yet.
To lock dissmiss we have to clear behavior after SnackbarLayout initialisation. the best place to do this is for example in OnPreDrawListener of SnackbarLayout
final Snackbar snack = Snackbar.make(getView(), "I can't be dissmiss", Snackbar.LENGTH_INDEFINITE);
snack.show();
snack.getView().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
snack.getView().getViewTreeObserver().removeOnPreDrawListener(this);
((CoordinatorLayout.LayoutParams) snack.getView().getLayoutParams()).setBehavior(null);
return true;
}
});
Snackbar now has actual support disabling swipe to dismiss using the setBehavior method. The great thing here is that before you would always lose some behaviors which are now preserved. You'll also want to use Snackbar.LENGTH_INDEFINITE
Note that the package moved so you have to import the "new" Snackbar in the snackbar package.
Snackbar.make(view, stringId, Snackbar.LENGTH_INDEFINITE)
.setBehavior(new NoSwipeBehavior())
.show();
class NoSwipeBehavior extends BaseTransientBottomBar.Behavior {
@Override
public boolean canSwipeDismissView(View child) {
return false;
}
}
I was successful in disabling the swipe-sideways-to-dismiss snackbars with the following hack (after calling snackbar.show())
((android.support.design.widget.CoordinatorLayout.LayoutParams) snackbar.getView().getLayoutParams()).setBehavior(null);
来源:https://stackoverflow.com/questions/32183509/snackbar-with-coordinatorlayout-disable-dismiss