嵌套Android ViewPager,水平滑动ListView中的ListItems
我在活动的根级别上有一个ViewPager 寻呼机的每一页都包含一个ListFragment(由FragmentPagerAdapter支持) 一些列表视图项应该包含额外的ViewPager,以支持浏览这些项的内容(例如,列表项中的水平图库) 如何嵌套查看寻呼机?ViewPager->ListView(在页面中)->ViewPager(在列表项中)嵌套Android ViewPager,水平滑动ListView中的ListItems,android,listview,nested,android-viewpager,Android,Listview,Nested,Android Viewpager,我在活动的根级别上有一个ViewPager 寻呼机的每一页都包含一个ListFragment(由FragmentPagerAdapter支持) 一些列表视图项应该包含额外的ViewPager,以支持浏览这些项的内容(例如,列表项中的水平图库) 如何嵌套查看寻呼机?ViewPager->ListView(在页面中)->ViewPager(在列表项中) 我可以在列表片段之间水平滑动,也可以垂直滑动整个列表,但我不能在列表项内部滑动。您不能真正嵌套需要相同手势来控制它们的元素。因为视图寻呼机已经捕获了
我可以在列表片段之间水平滑动,也可以垂直滑动整个列表,但我不能在列表项内部滑动。您不能真正嵌套需要相同手势来控制它们的元素。因为视图寻呼机已经捕获了水平运动,所以嵌套元素将无法获取它。通过管理focus等,你可能需要做很多工作来解决这个问题,但最终你的应用程序会让用户感到困惑。最好不要嵌套使用相同交互的元素。。。在这种情况下,两个视图寻呼机都在观察侧向运动。虽然这不是最好的交互设计,但可以通过覆盖根级别活动的dispatchTouchEvent(MotionEvent ev)方法并使用RequestDisallowWinterCeptTouchEvent(true)来实现这一点在mainPager和当前ListView上,以防止其他滚动。看看这个例子:
@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);
}
@覆盖
公共布尔dispatchTouchEvent(MotionEvent ev){
Fragment listFragment=getSupportFragmentManager().findFragmentByTag(
android:switcher:“+R.id.pager+”:“+(mainPager.getCurrentItem());
mainPager.getChildAt(mainPager.getCurrentItem());
如果(listFragment==null)
返回超级dispatchTouchEvent(ev);
ViewPager embeddedPager=(ViewPager)listFragment.getView().findViewById(R.id.videopager);
if(embeddedPager!=null){
int[]位置=新int[2];
嵌入式寻呼机。getLocationOnScreen(位置);
if(ev.getY()>position[1]&&ev.getY()
我在内部ViewPager
中添加了一个ontouch监听器
:
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;
}
};
这只会检测内部ViewPager
上的操作下触事件,并防止外部的操作下触事件拦截它。因为它返回false,所以只应命中ACTION_DOWN事件;所有其他事件都将被忽略。您可以将此侦听器添加到您想要“保护”的每个元素中,使其免受外部ViewPager
滚动的影响,但显然,如果您想要在这些元素上拾取任何其他触摸行为,您需要在触摸侦听器中处理它们,并可能实现更好的侦听器
首先感谢@Rodja给了我这个想法。谢谢你——我稍微修改了这个想法,让你把代码放在
活动之外的其他地方#dispatchTouchEvent(MotionEvent)
功能,但我使用的想法基本上是你的:)哇。干净多了。谢谢到目前为止,这是最简单的解决方案。简直不敢相信它有多容易工作。非常感谢,安德鲁和罗贾!我面临着类似的问题,这让我可以左右滑动。如果我还想启用点击,然后打开所选视图,该怎么办?您可以编写自己的点击监听器,方法是先听ACTION_DOWN,然后听ACTION_UP;如果两者之间的所有动作和移动事件的总和小于系统触摸斜率(见下文),则称之为单击。具有触摸斜率、长按和一般任何您需要的常数。