Ashlok
Ashlok

Reputation: 191

Disable NestedScrollview scroll

Design of my app

Screen - 1

    <NestedScrollview>
       <LinearLayout orientation:horizontal">
          <RecyclerView-1>
          <Framelayout>(contains Recyclerview-2)
    </NestedScroll>

Screen - 2

     <NestedScrollview>
         <LinearLayout orientation:horizontal">
         <RecyclerView-1>
         <Framelayout> (fragment changed, contains Recyclerview-3)
     </NestedScroll>

Now if user is on screen 1, then both the recyclerview will scroll simultaneously, but on screen 2 if user scrolls RV1 then only RV1 will scroll similarly if RV3 is scrolled then RV3 will be scrolled. Tried all sort of stop scroll, but unable to stop scroll of nested scrollview.

Upvotes: 18

Views: 21815

Answers (3)

albnok
albnok

Reputation: 530

Adjusted @Andrew Weiss' Kotlin answer with non-null and other Lint warnings:

class LockableNestedScrollView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
NestedScrollView(context, attrs, defStyleAttr) {

constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context) : this(context, null)

var scrollable = true

@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(motionEvent: MotionEvent): Boolean {
    return super.onTouchEvent(motionEvent) && scrollable
}

override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
    return super.onInterceptTouchEvent(ev) && scrollable
}

override fun performClick(): Boolean {
    return super.performClick() && scrollable
}

}

Upvotes: 0

Andrew Weiss
Andrew Weiss

Reputation: 71

The same solution in Kotlin

class LockableNestedScrollView(
    context: Context,
    attrs: AttributeSet?,
    defStyleAttr: Int,
): NestedScrollView(context, attrs, defStyleAttr) {

    constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0)
    constructor(context: Context): this(context, null)

    private var scrollable = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return scrollable && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return scrollable && super.onInterceptTouchEvent(ev)
    }

    fun setScrollingEnabled(enabled: Boolean) {
        scrollable = enabled
    }
}

Upvotes: 7

oscarif
oscarif

Reputation: 439

You must to create a new class that do nothing on touch and scroll events:

public class LockableNestedScrollView extends NestedScrollView {
    // by default is scrollable
    private boolean scrollable = true;

    public LockableNestedScrollView(@NonNull Context context) {
        super(context);
    }

    public LockableNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public LockableNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return scrollable && super.onTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return scrollable && super.onInterceptTouchEvent(ev);
    }

    public void setScrollingEnabled(boolean enabled) {
        scrollable = enabled;
    }
}

Next in your layout you change the NestedScroll by your new class:

    <your.package.name.path.LockableNestedScrollView>
       <LinearLayout 
          orientation:"horizontal"
          android:id="@+id/scroll_name">
          <RecyclerView-1>
          <Framelayout>(contains Recyclerview-2)
    </your.package.name.path.LockableNestedScrollView>

Finally in your activity:

LockableNestedScrollView myScrollView = (LockableNestedScrollView) findViewById(R.id.scroll_name);
myScrollView.setScrollingEnabled(false);

I hope it helps someone else.

Upvotes: 39

Related Questions