2

I have a ViewPager with a custom PagerAdapter that displays a set of fragments.

These fragments are (purposely) positioned on top of each other so that I can use a PageTransformer that makes it look as if the user is sliding the fragments from a stack (almost like a deck of cards).

The issue is that each fragment has their own Views/Widgets (e.g. a seekbar) which, due to the overlapping, are occupying the same coordinates and sometimes the touch event is caught by the fragment bellow the current one (e.g. the user adjusts a seekbar's position, but instead of updating the currently shown seekbar, it's the seekbar in the next fragment that's gets its progress updated).

I've come across this answer but it's not the same exact problem. Has anyone ever found a similar issue? What's the smartest way (except for the lazy solution: change the PageTransformer to one that doesn't overlap the fragments) of dealing with this issue?

EDIT:

In my Fragment class I have:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)        
{
    View rootView = inflater.inflate(R.layout.fragment, container, false);

    rootView.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return true;
        }
    });
}

as suggested by Zsombor Erdődy-Nagy, but this doesn't help: it's still possible for the widget bellow the current fragment to receive the event instead of the current one's.

I've also looked at this open issue, with no success.

Community
  • 1
  • 1
user1987392
  • 3,921
  • 4
  • 34
  • 59

3 Answers3

3

If you are still looking for the solution, than you should look at this:

Issue 58918.

Here you can find the answer to your problem. Quoting from the link:

If I remember right it was after 4.1 that the framework respects a custom child drawing order as implied Z-ordering for dispatching touch events. If your views overlap after this page transformation they may not receive touch events in the expected order on older platform versions. Check which view is receiving the touch events to be certain.

If this is what you are seeing you have a few options:

  • Enforce the desired ordering as you add/remove child views in your PagerAdapter
  • Remove the X translation applied by the PageTransformer when a page is no longer fully visible - i.e. the "position" parameter reports a full -1 or 1.

Example:

this.viewPager.setPageTransformer(true, new PageTransformer() {

        @Override
        public void transformPage(View page, float position) {
            float translationX;
            float scale;
            float alpha;

            if (position >= 1 || position <= -1) {
                // Fix for https://code.google.com/p/android/issues/detail?id=58918
                translationX = 0;
                scale = 1;
                alpha = 1;
            } else if (position >= 0) {
                translationX = -page.getWidth() * position;
                scale = -0.2f * position + 1;
                alpha = Math.max(1 - position, 0);
            } else {
                translationX = 0.5f * page.getWidth() * position;
                scale = 1.0f;
                alpha = Math.max(0.1f * position + 1, 0);
            }

            ViewHelper.setTranslationX(page, translationX);
            ViewHelper.setScaleX(page, scale);
            ViewHelper.setScaleY(page, scale);
            ViewHelper.setAlpha(page, alpha);
        }
});
user1987392
  • 3,921
  • 4
  • 34
  • 59
R4ng3LII
  • 457
  • 3
  • 8
  • In the meantime I've used a different PageTransformer (yes, lazy solution). I haven't really tested the solution in the provided link but it sure makes a lot of sense to me. Marking as accepted. – user1987392 Mar 17 '14 at 12:25
  • Perfect Solution !! Thanks – Jatin Jha Sep 05 '16 at 08:03
0

In this case all your fragments must have a background View that stops TochEvents propagating to fragments in the back.

I'm guessing that you already have opaque backgrounds for these fragments, or else the fragments in the back would show through the fragment currently on the top of the stack. So try setting a ClickListener for all your fragment's root ViewGroup instance that does nothing, it just catches the touch events.

Zsombor Erdődy-Nagy
  • 16,864
  • 16
  • 76
  • 101
0

In case anyone runs into this issue (which can happen not only with ViewPager), it is just a matter of adding this attribute to the layout at the top of your hierarchy:

android:clickable="true"

This way it will handle the clicks, not doing really anything with them, but at least avoiding them to reach the fragment in the background.

Bilthon
  • 2,461
  • 8
  • 36
  • 44