39

Is it possible to disable SwipeRefreshLayout drag animation on swipe down without class customization?

Alexander Zhak
  • 9,140
  • 4
  • 46
  • 72

3 Answers3

76

Try calling:

setEnabled(false)

on your SwipeRefreshLayout view.

carloshwa
  • 1,254
  • 2
  • 11
  • 12
  • 1
    No, this would fully disable the control, not only animation. It's not what was needed – Alexander Zhak Jan 12 '15 at 07:07
  • 7
    Calling this disables the gesture, but still allows you to show the refreshing animation programmatically with: `setRefreshing(true)` – carloshwa Feb 02 '15 at 01:02
  • @AlexanderZhak This didn't disable inner `ListView` for me. I still can click on items in the list view, swipe them to side, etc. and `ListView` behaves as if there is no `SwipeRefreshLayout`. – Lahiru Chandima Feb 20 '16 at 13:07
  • Perfect. After this, swipe down animation is gone, "onRefresh()" is not triggering and everything inside of SwipeRefreshLayout works as before. All I needed. – VoW Jul 20 '16 at 19:28
  • If you had issues with calling `setRefreshing(true)` from onCreate(), version 24.2.0 of the Support Library fixes a bug: https://code.google.com/p/android/issues/detail?id=77712 – carloshwa Aug 17 '16 at 18:37
  • Glad to hear they fixed it. – Alexander Zhak Oct 21 '16 at 07:22
  • great...save my time. – Patel Vicky Dec 15 '17 at 09:50
12

Well, disabling SwipeLayoutAnimanion appeared to be a rather simple task, but it involves replication of android.support.v4.widget.SwipeRefreshLayout class inside one's project.

Diving in source code will reveal, that SwipeRefreshLayout consists of three classes:

All three classes should be included in the project. Then SwipeRefreshLayout can be customized as follows:

Add a new public method which will control either layout should follow the swipe down gesture or not:

private boolean mLayoutMovementEnabled = true;

public void setLayoutMovementEnabled(boolean enabled) {
    mLayoutMovementEnabled = enabled;
}

All related computations are performed inside onTouchEvent(). To disable layout following the movement,

updateContentOffsetTop((int) (offsetTop)); string should be changed to

if (mLayoutMovementEnabled) updateContentOffsetTop((int) (offsetTop));

The complete modified routine is below.

@Override
public boolean onTouchEvent(MotionEvent event) {
    final int action = event.getAction();
    boolean handled = false;
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            mCurrPercentage = 0;
            mDownEvent = MotionEvent.obtain(event);
            mPrevY = mDownEvent.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            if (mDownEvent != null && !mReturningToStart) {
                final float eventY = event.getY();
                float yDiff = eventY - mDownEvent.getY();
                if (yDiff > mTouchSlop) {
                    // User velocity passed min velocity; trigger a refresh
                    if (yDiff > mDistanceToTriggerSync) {
                        // User movement passed distance; trigger a refresh
                        startRefresh();
                        handled = true;
                        break;
                    } else {
                        // Just track the user's movement
                        setTriggerPercentage(
                                mAccelerateInterpolator.getInterpolation(
                                        yDiff / mDistanceToTriggerSync));
                        float offsetTop = yDiff;
                        if (mPrevY > eventY) {
                            offsetTop = yDiff - mTouchSlop;
                        }
                        if (mLayoutMovementEnabled) updateContentOffsetTop((int) (offsetTop));
                        if (mPrevY > eventY && (mTarget.getTop() < mTouchSlop)) {
                            // If the user puts the view back at the top, we
                            // don't need to. This shouldn't be considered
                            // cancelling the gesture as the user can restart from the top.
                            removeCallbacks(mCancel);
                        } else {
                            updatePositionTimeout();
                        }
                        mPrevY = event.getY();
                        handled = true;
                    }
                }
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if (mDownEvent != null) {
                mDownEvent.recycle();
                mDownEvent = null;
            }
            break;
    }
    return handled;
}
Alexander Zhak
  • 9,140
  • 4
  • 46
  • 72
8

One simple way to disable the swipe is to set the distance to trigger sync to some value too high to be reached.

mSwipeLayout.setDistanceToTriggerSync(999999);
  • 1
    It seems like behavior of SwipeRefreshLayout.setEnabled() has changed and this is actually the only working solution right now - if I want to still display the progress indicator, but disable the gesture. – petrnohejl Oct 05 '17 at 23:15