Hao
Hao

Reputation: 422

Snackbar's swipe to dismiss freezes app

Quick context:

I have a single FragmentActivity which hosts all the view components I display throughout my app, in particular a CoordinatorLayout view which is used for any snackbars I make to achieve the swipe-to-dismiss effect.

Activity xml

  <android.support.design.widget.CoordinatorLayout
    android:id="@+id/cl_snackbar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Activity class

@BindView(R.id.cl_snackbar) View snackBar;

/**
 * To allow for use of a snackbar throughout the app's fragments
 */
public View getSnackBar() {
    return snackBar;
}

Fragment class

@Nullable private View snackBar;

//This is done in fragment's onCreateView()
if (getActivity() instanceof ParentActivity) snackBar = ((ParentActivity) getActivity()).getSnackBar();

//This is done in a method
if (snackBar != null) Snackbar.make(snackBar, "Working", Snackbar.LENGTH_LONG).show();

This functionality has worked perfectly for the past year but I recently updated my Android support library to 27.0.0 from 26.1.0 and the swipe-to-dismiss effect now completely freezes the app. It becomes unresponsive. In the logcat I get the following warning:

E/ViewDragHelper: Ignoring pointerId=0 because ACTION_DOWN was not received for this pointer before ACTION_MOVE. It likely happened because  ViewDragHelper did not receive all the events in the event stream.
E/ViewDragHelper: Ignoring pointerId=-1 because ACTION_DOWN was not received for this pointer before ACTION_MOVE. It likely happened because  ViewDragHelper did not receive all the events in the event stream.
E/ViewDragHelper: Ignoring pointerId=-1 because ACTION_DOWN was not received for this pointer before ACTION_MOVE. It likely happened because  ViewDragHelper did not receive all the events in the event stream.
E/ViewDragHelper: Ignoring pointerId=-1 because ACTION_DOWN was not received for this pointer before ACTION_MOVE. It likely happened because  ViewDragHelper did not receive all the events in the event stream.

I've checked throughout the diff changes in Android 27.0.0, but I don't see any changes to do with any of the support classes involved. Can anyone provide assistance or any hints as to what's suddenly gone wrong?

Upvotes: 3

Views: 1285

Answers (2)

Sam
Sam

Reputation: 1029

I had a similar same issue in a CoordinatorLayout with an inner SwipeRefreshLayout where the swipe-to-dismiss stopped working, and threw an error in the LogCat but did not crash:

E/ViewDragHelper: Ignoring pointerId=0 because ACTION_DOWN was not received for this pointer before ACTION_MOVE. It likely happened because  ViewDragHelper did not receive all the events in the event stream.

This same error came up for pointerId=-1 as well.

My layout for the activity is:

<!-- cl_main is the SnackBar's host View -->
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/cl_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/main_include_all_items"/>
    </android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>

I thought that perhaps the SwipeRefreshLayout was intercepting the swipe from reaching the CoordinatorLayout.

I resolved this/worked around it (mostly) by upgrading both the compileSdkVersion and targetSdkVersion in build.gradle to 28 and the dependencies in build.gradle to 28.0.0; after doing so, the swipe-to-dismiss of the Snackbar now works.

It still does throw the same error as before, but, like before, does not crash the application.

Upvotes: 0

Alexander Bratusenko
Alexander Bratusenko

Reputation: 192

Deleting swipe-to-dismiss behaviour should fix the problem:

    snackBar.addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
        override fun onShown(transientBottomBar: Snackbar) {
            val layoutParams = transientBottomBar.view.layoutParams as? CoordinatorLayout.LayoutParams
            layoutParams?.let { it.behavior = null }
        }
    })

In case you need to save behaviour you should copy behaviour and insert both requestDisallowInterceptTouchEvent(true) before handling a touch event and requestDisallowInterceptTouchEvent(false) after that.

Upvotes: 2

Related Questions