Menu
Menu

Reputation: 685

Disable scrolling on specific area in ViewPager

I have a ViewPager so inside this view pager I have different fragments so in first fragment I have a TouchImageView which contain 360 degree rotatable image. When I'm swiping left or right for the Touchimageview so back viewpager event also triggering means viewpager is scrolling so I want to disable viewpager touch event for this imageview area.

Eg: ViewPager -> Fragment -> TouchImageView

I have gone through several answers about disable to onInterceptTouchEvent() and onTouchEvent() based on need but its disabled complete view of the fragment.

Any help would be greatly appreciated!

ViewPager.java

public class MyCardViewPager extends ViewPager {

private boolean isScrollingEnabled = true;

public MyCardViewPager(@Nonnull Context context, @Nonnull AttributeSet attrs) {
    super(context, attrs);
}

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

@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
    return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (isScrollingEnabled) {
        return super.onInterceptTouchEvent(ev);
    }

    return false;
}

@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (isScrollingEnabled) {
        return super.onTouchEvent(ev);
    }
    return false;
}

public void enableScroll(boolean enable) {
    isScrollingEnabled = enable;
}

}

Fragment.java

@Override
        public View onCreateView(@Nonnull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    myCardViewPager = new MyCardViewPager(context);
    myCardViewPager.enableScroll(false);
    imageViewSwipeListener();
    }

    private void imageViewSwipeListener() {
        position = 18;
        objectList();
        imageview.setOnTouchListener(new OnSwipeTouchListener(getActivity()) {
            @Override
            public void onSwipeRight() {
                super.onSwipeRight();
                position += 1;
                if (position == 36) {
                    position = 0;
                }
                imageview.setImageResource(objectList.get(position));
            }

            @Override
            public void onSwipeLeft() {
                super.onSwipeLeft();
                position -= 1;
                if (position == -1) {
                    position = 35;
                }
                imageview.setImageResource(objectList.get(position));
              }
        });
    }

OnSwipeTouchListener class

open class OnSwipeTouchListener(ctx: Context) : View.OnTouchListener {

private val gestureDetector: GestureDetector

companion object {

    private val SWIPE_THRESHOLD = 100
    private val SWIPE_VELOCITY_THRESHOLD = 100
}

init {
    gestureDetector = GestureDetector(ctx, GestureListener())
}

override fun onTouch(v: View, event: MotionEvent): Boolean {
    return gestureDetector.onTouchEvent(event)
}

private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {


    override fun onDown(e: MotionEvent): Boolean {
        return true
    }

    override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
        var result = false
        try {
            val diffY = e2.y - e1.y
            val diffX = e2.x - e1.x
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight()
                    } else {
                        onSwipeLeft()
                    }
                    result = true
                }
            } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                if (diffY > 0) {
                    onSwipeBottom()
                } else {
                    onSwipeTop()
                }
                result = true
            }
        } catch (exception: Exception) {
            exception.printStackTrace()
        }
        return result
    }
}

open fun onSwipeRight() {}

open fun onSwipeLeft() {}

open fun onSwipeTop() {}

open fun onSwipeBottom() {}

}

Upvotes: 0

Views: 281

Answers (1)

snachmsm
snachmsm

Reputation: 19223

swipeTouch = new OnSwipeTouchListener(getActivity()) {...};
imageview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        swipeTouch.onTouchEvent(motionEvent);
        imageview.onTouchEvent(motionEvent);
        return true;
    }
});

first line in this method is just passing every MotionEvent motionEvent to same View, which is default behavior without setting custom touch listener. BUT onTouchEvent method returns boolean indicating that this View consumed passed event. if default onTouchEvent returns false then same event is passed to views parent, if it also wont consume it then, again, is passed up in hierarchy until some of parenting Views (ViewGroups) will return true confirming it can handle this event.

your imageview is probably some custom/lib class, which occasionally (always?) return false allowing to dispatch touch events up in hierarchy to ViewPager, which can handle this touch and return true. thats why in above snippet onTouch method is returning true always when touch occurs on imageview - this touch is still passed to this View, but even if it isn't handled return true prevents dispatching same event up to parents

Upvotes: 0

Related Questions