0

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() {}

}

Menu
  • 677
  • 1
  • 12
  • 30
  • show what you have tried so far, mentioned methods are good clues, but may be improperly implemented. it would be easier to catch a bug in existing code rather that writing whole feature from scratch – snachmsm Jul 20 '21 at 11:25
  • sure @snachmsm I'll add my code – Menu Jul 20 '21 at 11:29

1 Answers1

0
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

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • I have customized OnSwipeTouchListener class which is added to the imageview – Menu Jul 20 '21 at 11:54
  • how can I do it in my OnSwipeTouchListener class ? – Menu Jul 20 '21 at 11:58
  • you can have only one touch listener, but still you may have one listener grouping and calling some other. I've edited my answer, check out – snachmsm Jul 20 '21 at 12:04
  • tried the same way now my imageview touchevent is gone ....touchevent only working for view pager – Menu Jul 20 '21 at 12:11
  • maybe your custom `OnSwipeTouchListener` swallows `MotionEvent` and you should call `imageview.onTouchEvent(motionEvent)` at first? now i'm not shure what behavior you want to achieve, don't have more ideas... maybe post `imageview` class code + try to use your current code (as in question), but `return true` in `onTouch(v: View, event: MotionEvent)`, still calling `gestureDetector.onTouchEvent(event)` before – snachmsm Jul 20 '21 at 16:36
  • As clearly metioned in my question I want to disable view pager events for its child view(imageview) only for specific area. I have tried your suggestion so now unable to do touch event for child view ie imageview – Menu Jul 21 '21 at 18:54