问题
I have a ViewPager on the root-level of an activity.
Each page of the pager contains a ListFragment (backed by a FragmentPagerAdapter).
Some of the list view items should contain additionally ViewPagers to support swiping the content of those items (e. g. a horizontal gallery inside a list item).
How can I nest view pagers? ViewPager -> ListView (in a page) -> ViewPager (inside a list item)
I can swipe between the ListFragments horizontally and I can swipe the whole list vertically, but I cannot swipe inside list items.
回答1:
I added an OnTouchListener
to the interior ViewPager
:
private OnTouchListener mSuppressInterceptListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(
event.getAction() == MotionEvent.ACTION_DOWN &&
v instanceof ViewGroup
) {
((ViewGroup) v).requestDisallowInterceptTouchEvent(true);
}
return false;
}
};
This just detects ACTION_DOWN touch events on the inner ViewPager
and prevents the outer one from intercepting it. Because it returns false, only the ACTION_DOWN event should be hit; all the other events will be ignored. You can add this listener to every element you want to "protect" from the outer ViewPager
's scrolling, though obviously if you want to pick up any other touch behaviour on those elements you'll need to deal with them inside the touch listener and possibly implement a better listener.
Credit to @Rodja who gave me the idea in the first place.
回答2:
While it's not the best interaction design, it is possible to implement this by overwriting the dispatchTouchEvent(MotionEvent ev) method of the root-level Activity and using requestDisallowInterceptTouchEvent(true) on the mainPager and the current ListView to prevent other scrolling. Look at this example:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Fragment listFragment = getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + R.id.pager + ":" + (mainPager.getCurrentItem()));
mainPager.getChildAt(mainPager.getCurrentItem());
if (listFragment == null)
return super.dispatchTouchEvent(ev);
ViewPager embeddedPager = (ViewPager) listFragment.getView().findViewById(R.id.videopager);
if (embeddedPager != null) {
int[] position = new int[2];
embeddedPager.getLocationOnScreen(position);
if (ev.getY() > position[1] && ev.getY() < position[1] + embeddedPager.getHeight()) {
mainPager.requestDisallowInterceptTouchEvent(true);
if (embeddedPager.getScrollX() % embeddedPager.getWidth() != 0) {
ListView listView = (ListView) listFragment.getView().findViewById(
android.R.id.list);
listView.requestDisallowInterceptTouchEvent(true);
}
}
}
return super.dispatchTouchEvent(ev);
}
回答3:
You can't really nest elements that need the same gestures to control them. Since the view pager is already capturing the horizontal motion, your nested elements will not get it. You could probably do a lot of work to get around this by managing focus and the like - but in the end your app will be confusing for users. Its really better to not nest elements that would use the same interaction... in this case two view pagers both watching for a side to side motion.
来源:https://stackoverflow.com/questions/10257176/nesting-android-viewpager-swiping-listitems-inside-a-listview-horizontally