我有一个包含两个片段的ViewPager,每个片段都包含带有可滑动列表项的列表视图。为了方便用户滑动,我希望如果用户在第一个片段中向左滑动,则由列表视图拾取滑动。如果用户在第二个片段中向右滑动,则由列表视图拾取滑动。由于只有两个片段,因此在列表视图中拾取滑动是有意义的,而不是viewpager,因为在这两个片段之后没有更多片段可以滚动到它们。
那么,是否可以拦截触摸,并根据显示的浏览器页面和滑动方向将其传递给列表视图?
以下是我正在使用的可转换列表视图库:https://github.com/timroes/EnhancedListView
答案 0 :(得分:4)
我认为您可以自定义ViewPager
并控制ListView
canScroll
方法中ViewPager
滑动的行为。
我试了一个样本,似乎工作正常。您可以使用此自定义ViewPager
。
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context context) {
super(context);
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ViewPager) {
if (getChildAt(getCurrentItem()) != null) {
//get the ListView of current Fragment
EnhancedListView enhancedListView = (EnhancedListView) getChildAt(getCurrentItem()).findViewById(R.id.list);
//If the user is in first page and tries to swipe left, enable the ListView swipe
if (getCurrentItem() == 0 && dx > 0) {
enhancedListView.enableSwipeToDismiss();
}
//If the user is in second page and tries to swipe right, enable the ListView swipe
else if (getCurrentItem() == 1 && dx < 0) {
enhancedListView.enableSwipeToDismiss();
}
//Block the ListView swipe there by enabling the parent ViewPager swiping
else {
enhancedListView.disableSwipeToDismiss();
}
}
}
return super.canScroll(v, checkV, dx, x, y);
}
}
此外,您还必须在EnhancedListView
库中进行一些更改。因为在canScroll
事件之后调用ACTION_DOWN
方法,如果我们在canScroll
方法中启用了滑动 - 它会跳过为ACTION_DOWN
事件定义的逻辑,并且可能会导致意外行为。因此,仅当触摸事件为ACTION_MOVE
时才会阻止滑动。这些是onTouchEvent
库EnhancedListView
中的更改。
//EnhancedListView class
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!mSwipeEnabled && (ev.getAction() == MotionEvent.ACTION_MOVE)) {
return super.onTouchEvent(ev);
}
.....
我不确定这是否是问题的完美解决方案,但它工作得很好。
如果问题或答案不明确,以下是示例应用的一些屏幕截图。
应用由ViewPager
和两个片段页面组成。每个页面都有EnhanedListView(提供“滑动到解除/删除”功能)。由于可以刷换父ViewPager
和子列表项,因此会导致冲突。默认情况下,子ListItem会抓取滑动,这会阻止父ViewPager
滑动。
必需的解决方案:
如果用户在第一页并向右滑动,则应刷一下列表项。
如果用户在第二页并向左滑动,则应刷一下列表项。
在其他情况下,应刷过ViewPager
。
更新:要修复SwipeRefreshLayout
的错误,以下是自定义ViewPager
代码的细微更改。
public class ScrollLock extends ViewPager {
public ScrollLock(Context context) {
super(context);
}
public ScrollLock(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v instanceof ViewPager) {
if (getChildAt(getCurrentItem()) != null) {
//set it so it does not swipe to refresh while swiping away a list item
SwipeRefreshLayout swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe);
//get the ListView of current Fragment
EnhancedListView enhancedListView = (EnhancedListView) getChildAt(getCurrentItem()).findViewById(R.id.listView1);
//If the user is in first page and tries to swipe left, enable the ListView swipe
if (getCurrentItem() == 0 && dx > 0) {
enhancedListView.enableSwipeToDismiss();
swipeLayout.setEnabled(false);
return true;
}
//If the user is in second page and tries to swipe right, enable the ListView swipe
else if (getCurrentItem() == 1 && dx < 0) {
enhancedListView.enableSwipeToDismiss();
swipeLayout.setEnabled(false);
return true;
}
//Block the ListView swipe there by enabling the parent ViewPager swiping
else {
enhancedListView.disableSwipeToDismiss();
}
}
}
return super.canScroll(v, checkV, dx, x, y);
}
}