-
TextView的滑动和RecyclerView冲突
-
问题描述:RecycleView中使用了TextView,而TextView大小有限,要求文本支持滚动,此时会与Recycler的滑动冲突;
-
问题解决:监听TextView文本的滚动事件,如果是TextView需要滚动时,禁止父控件(RecyclerView)的滑动,否则允许父控件滑动;
tvContent.setMovementMethod(ScrollingMovementMethod.getInstance());
tvContent.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return false;
}
});
-
Scrollview的滑动和RecyclerView冲突
-
问题描述:一个比较长的界面一般都是Scrollview嵌套RecyclerView来解决.不过这样的UI并不是我们开发人员想看到的,实际上嵌套之后.因为Scrollview和RecyclerView都是滑动控件.会有一点滑动上的冲突.导致滑动起来有些卡顿.
-
问题解决:禁止RecycleView的滑动,我们重写一下LayoutManager就行了;
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false) {
@Override
public boolean canScrollVertically() {
return false;
}
};
recyclerview.setLayoutManager(linearLayoutManager);
recyclerview.setAdapter(tempCommonAdapter);
-
ViewPager和 SwipeRefreshLayout冲突
-
问题描述: 当 SwipeRefreshLayout 中有 ViewPager 控件, 两者的滑动会相互冲突. 具体表现为 ViewPager 的左右滑动不顺畅, 容易被 SwipeRefreshLayout 拦截(即出现刷新的 View ).
-
问题解决: ViewPager 本身是处理了滚动事件的冲突, 它在横向滑动时会调用 requestDisallowInterceptTouchEvent() 方法使父控件不拦截当前的 Touch 事件序列. 但是 SwipeRefreshLayout 的 requestDisallowInterceptTouchEvent() 方法置空了, 所以仍然会拦截当前的 Touch 事件序列.
1. //非法按键
2. private static final int INVALID_POINTER = -1;
3.
4. //dispatch方法记录第一次按下的x
5. private float mInitialDisPatchDownX;
6.
7. //dispatch方法记录第一次按下的y
8. private float mInitialDisPatchDownY;
9.
10. //dispatch方法记录的手指
11. private int mActiveDispatchPointerId = INVALID_POINTER;
12.
13. //是否请求拦截
14. private boolean hasRequestDisallowIntercept = false;
15.
16. @Override
17. public void requestDisallowInterceptTouchEvent(boolean b) {
18. hasRequestDisallowIntercept = b;
19. // Nope.
20. }
21.
22. @Override
23. public boolean dispatchTouchEvent(MotionEvent ev) {
24. switch (ev.getAction()) {
25. case MotionEvent.ACTION_DOWN:
26. mActiveDispatchPointerId = MotionEventCompat.getPointerId(ev, 0);
27. final float initialDownX = getMotionEventX(ev, mActiveDispatchPointerId);
28. if (initialDownX != INVALID_POINTER) {
29. mInitialDisPatchDownX = initialDownX;
30. }
31. final float initialDownY = getMotionEventY(ev, mActiveDispatchPointerId);
32. if (mInitialDisPatchDownY != INVALID_POINTER) {
33. mInitialDisPatchDownY = initialDownY;
34. }
35. break;
36. case MotionEvent.ACTION_MOVE:
37. if (hasRequestDisallowIntercept) {
38. //解决viewPager滑动冲突问题
39. final float x = getMotionEventX(ev, mActiveDispatchPointerId);
40. final float y = getMotionEventY(ev, mActiveDispatchPointerId);
41. if (mInitialDisPatchDownX != INVALID_POINTER && x != INVALID_POINTER &&
42. mInitialDisPatchDownY != INVALID_POINTER && y != INVALID_POINTER) {
43. final float xDiff = Math.abs(x – mInitialDisPatchDownX);
44. final float yDiff = Math.abs(y – mInitialDisPatchDownY);
45. if (xDiff > mTouchSlop && xDiff * 0.7f > yDiff) {
46. //横向滚动不需要拦截
47. super.requestDisallowInterceptTouchEvent(true);
48. } else {
49. super.requestDisallowInterceptTouchEvent(false);
50. }
51. } else {
52. super.requestDisallowInterceptTouchEvent(false);
53. }
54. }
55. break;
56. case MotionEvent.ACTION_UP:
57. case MotionEvent.ACTION_CANCEL:
58. if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
59. hasRequestDisallowIntercept = false;
60. }
61. break;
62. }
63.
64. return super.dispatchTouchEvent(ev);
65. }
66.
67. private float getMotionEventY(MotionEvent ev, int activePointerId) {
68. final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
69. if (index < 0) {
70. return -1;
71. }
72. return MotionEventCompat.getY(ev, index);
73. }
74.
75. private float getMotionEventX(MotionEvent ev, int activePointerId) {
76. final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
77. if (index < 0) {
78. return -1;
79. }
80. return MotionEventCompat.getX(ev, index);
81. }
-
RecyclerView嵌套ViewPager的冲突
-
问题描述: 当用户滑动 RecyclerView 后放开手指, RecyclerView 会继续滑动并处于 Fling 状态. 此时用户重新触摸屏幕, RecyclerView 滑动停止, 但是无法左右滑动 ViewPager , 只能上下滑动 RecyclerView . 当用户重新触摸屏幕, 此时 RecyclerView 的 onInterceptTouchEvent() 方法还是返回了 true , 所以 ViewGroup 还是继续拦截了事件, 导致 ViewPager 无法处理.
-
问题解决: 如果是 Fling 状态的 RecyclerView , 在处理 ACTION_DOWN 事件时, 应该与 IDLE 状态下保持一致. Fling 状态下处理 ACTION_DOWN , onInterceptTouchEvent() 方法应该返回 false.
1. @Override
2. public boolean onInterceptTouchEvent(MotionEvent e) {
3. //isScrolling 为 true 表示是 Fling 状态
4. boolean isScrolling = getScrollState() == SCROLL_STATE_SETTLING;
5. boolean ans = super.onInterceptTouchEvent(e);
6. if (ans && isScrolling && e.getAction() == MotionEvent.ACTION_DOWN) {
7. //先调用 onTouchEvent() 使 RecyclerView 停下来
8. onTouchEvent(e);
9. //反射恢复 ScrollState
10. try {
11. Field field = RecyclerView.class.getDeclaredField(“mScrollState”);
12. field.setAccessible(true);
13. field.setInt(this, SCROLL_STATE_IDLE);
14. } catch (NoSuchFieldException e1) {
15. e1.printStackTrace();
16. } catch (IllegalAccessException e1) {
17. e1.printStackTrace();
18. }
19. return false;
20. }
21. return ans;
22. }