Android 中解决滑动的方案有2种:外部拦截法 和内部拦截法。
滑动冲突也存在2种场景: 横竖滑动冲突、同向滑动冲突。

所以我就写了4个例子来学习如何解决滑动冲突的,这四个例子分别为: 外部拦截法解决横竖冲突、外部拦截法解决同向冲突、内部拦截法解决横竖冲突、内部拦截法解决同向冲突。
先上效果图:

二、实战
1、外部拦截法,解决横竖冲突
思路是,重写父控件的onInterceptTouchEvent方法,然后根据具体的需求,来决定父控件是否拦截事件。如果拦截返回返回true,不拦截返回false。关于为什么返回true就代表拦截事件 。 如果父控件拦截了事件,则在父控件的onTouchEvent进行相应的事件处理。
我的这个例子,是一个横向滑动的ViewGroup里面包含了3个竖向滑动的ListView。下面我附上代码:
HorizontalEx.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
 * Created by blueberry on 2016/6/20.
 *
 * 解决交错的滑动冲突
 *
 * 外部拦截法
 */
public class HorizontalEx extends ViewGroup {
    private static final String TAG = "HorizontalEx";
    private boolean isFirstTouch = true;
    private int childIndex;
    private int childCount;
    private int lastXIntercept, lastYIntercept, lastX, lastY;
    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;
    public HorizontalEx(Context context) {
        super(context);
        init();
    }
    public HorizontalEx(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public HorizontalEx(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init() {
        mScroller = new Scroller(getContext());
        mVelocityTracker = VelocityTracker.obtain();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        childCount = getChildCount();
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        if (childCount == 0) {
            setMeasuredDimension(0, 0);
        } else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            width = childCount * getChildAt(0).getMeasuredWidth();
            height = getChildAt(0).getMeasuredHeight();
            setMeasuredDimension(width, height);
        } else if (widthMode == MeasureSpec.AT_MOST) {
            width = childCount * getChildAt(0).getMeasuredWidth();
            setMeasuredDimension(width, height);
        } else {
            height = getChildAt(0).getMeasuredHeight();
            setMeasuredDimension(width, height);
        }
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = 0;
        for (int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            child.layout(left + l, t, r + left, b);
            left += child.getMeasuredWidth();
        }
    }
    /**
     * 拦截事件
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            /*如果拦截了Down事件,则子类不会拿到这个事件序列*/
            case MotionEvent.ACTION_DOWN:
                lastXIntercept = x;
                lastYIntercept = y;
                intercepted = false;
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                    intercepted = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                final int deltaX = x - lastXIntercept;
                final int deltaY = y - lastYIntercept;
                /*根据条件判断是否拦截该事件*/
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
        }
        lastXIntercept = x;
        lastYIntercept = y;
        return intercepted;
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        mVelocityTracker.addMovement(event);
        ViewConfiguration configuration = ViewConfiguration.get(getContext());
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                /*因为这里父控件拿不到Down事件,所以使用一个布尔值,
                    当事件第一次来到父控件时,对lastX,lastY赋值*/
                if (isFirstTouch) {
                    lastX = x;
                    lastY = y;
                    isFirstTouch = false;
                }
                final int deltaX = x - lastX;
                scrollBy(-deltaX, 0);
                break;
            case MotionEvent.ACTION_UP:
                int scrollX = getScrollX();
                final int childWidth = getChildAt(0).getWidth();
                mVelocityTracker.computeCurrentVelocity(1000, configuration.getScaledMaximumFlingVelocity());
                float xVelocity = mVelocityTracker.getXVelocity();
                if (Math.abs(xVelocity) > configuration.getScaledMinimumFlingVelocity()) {
                    childIndex = xVelocity < 0 ? childIndex + 1 : childIndex - 1;
                } else {
                    childIndex = (scrollX + childWidth / 2) / childWidth;
                }
                childIndex = Math.min(getChildCount() - 1, Math.max(childIndex, 0));
                smoothScrollBy(childIndex * childWidth - scrollX, 0);
                mVelocityTracker.clear();
                isFirstTouch = true;
                break;
        }
        lastX = x;
        lastY = y;
        return true;
    }
    void smoothScrollBy(int dx, int dy) {
        mScroller.startScroll(getScrollX(), getScrollY(), dx, dy, 500);
        invalidate();
    }
    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mVelocityTracker.recycle();
    }
}

调用代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<code class="hljs lasso"> @Override
    public void showOutHVData(List<string> data1, List<string> data2, List<string> data3) {
        ListView listView1 = new ListView(getContext());
        ArrayAdapter<string> adapter1 = new ArrayAdapter<string>(getContext(), android.R.layout.simple_list_item_1, data1);
        listView1.setAdapter(adapter1);
        ListView listView2 = new ListView(getContext());
        ArrayAdapter<string> adapter2 = new ArrayAdapter<string>(getContext(), android.R.layout.simple_list_item_1, data2);
        listView2.setAdapter(adapter2);
        ListView listView3 = new ListView(getContext());
        ArrayAdapter<string> adapter3 = new ArrayAdapter<string>(getContext(), android.R.layout.simple_list_item_1, data3);
        listView3.setAdapter(adapter3);
        ViewGroup.LayoutParams params
                = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        mHorizontalEx.addView(listView1, params);
        mHorizontalEx.addView(listView2, params);
        mHorizontalEx.addView(listView3, params);
    }

其实外部拦截的主要思想都在于对onInterceptTouchEvent的重写。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<code class="hljs java">@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            /*如果拦截了Down事件,则子类不会拿到这个事件序列*/
            case MotionEvent.ACTION_DOWN:
                lastXIntercept = x;
                lastYIntercept = y;
                intercepted = false;
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                    intercepted = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                final int deltaX = x - lastXIntercept;
                final int deltaY = y - lastYIntercept;
                /*根据条件判断是否拦截该事件*/
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;
        }
        lastXIntercept = x;
        lastYIntercept = y;
        return intercepted;
    }</code>

这几乎是一个实现外部拦截事件的模板,这里一定不要在ACTION_DOWN 中返回 true,否则会让子VIew没有机会得到事件,因为如果在ACTION_DOWN的时候返回了 true,同一个事件序列ViewGroup的disPatchTouchEvent就不会在调用onInterceptTouchEvent方法了,如果不明白可以参考我的上一遍文章。
还有就是 在ACTION_UP中返回false,因为如果父控件拦截了ACTION_UP,那么子View将得不到UP事件,那么将会影响子View的 Onclick方法等。但这对父控件是没有影响的,因为如果是父控件子ACITON_MOVE中 就拦截了事件,他们UP事件必定也会交给它处理,因为有那么一条定律叫做:父控件一但拦截了事件,那么同一个事件序列的所有事件都将交给他处理。这条结论在我的上一篇文章中已经分析过。
最后就是在 ACTION_MOVE中根据需求决定是否拦截

2、内部拦截法,解决横竖冲突
内部拦截主要依赖于父控件的 requestDisallowInterceptTouchEvent方法,关于这个方法我的上篇文章其实已经分析过。他设置父控件的一个标志(FLAG_DISALLOW_INTERCEPT)
这个标志可以决定父控件是否拦截事件,如果设置了这个标志则不拦截,如果没设这个标志,它就会调用父控件的onInterceptTouchEvent()来询问父控件是否拦截。但这个标志对Down事件无效。
可以参考一下源码:
ViewGroup#dispatchTouchEvent

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<code class="hljs coffeescript">   // Handle an initial down.
            if (actionMasked == MotionEvent.ACTION_DOWN) {
                // Throw away all previous state when starting a new touch gesture.
                // The framework may have dropped the up or cancel event for the previous gesture
                // due to an app switch, ANR, or some other state change.
                cancelAndClearTouchTargets(ev);
                //清楚标志
                resetTouchState();
            }
            // Check for interception.
            final boolean intercepted;
            if (actionMasked == MotionEvent.ACTION_DOWN
                    || mFirstTouchTarget != null) {
                    //标志
                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
                if (!disallowIntercept) {
                    intercepted = onInterceptTouchEvent(ev);
                    ev.setAction(action); // restore action in case it was changed
                } else {
                    intercepted = false;
                }
            } else {
                // There are no touch targets and this action is not an initial down
                // so this view group continues to intercept touches.
                intercepted = true;
            }
</code>

那么我们如果想使用 内部拦截法拦截事件。
第一步:
a、我们要重写父控件的onInterceptTouchEvent,在ACTION_DOWN的时候返回false,负责的话子View调用requestDisallowInterceptTouchEvent也将无能为力。
b、还有就是其他事件的话都返回true,这样就把能否拦截事件的权利交给了子View。

第二步:
在子View的dispatchTouchEvent中 来决定是否让父控件拦截事件。
a. 先要在MotionEvent.ACTION_DOWN:的时候使用mHorizontalEx2.requestDisallowInterceptTouchEvent(true);,负责的话,下一个事件到来时,就交给父控件了。
b. 然后在MotionEvent.ACTION_MOVE: 根据业务逻辑决定是否调用mHorizontalEx2.requestDisallowInterceptTouchEvent(false);来决定父控件是否拦截事件。
上代码:
HorizontalEx2.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * Created by blueberry on 2016/6/20.
 * <p/>
 * 内部拦截
 * 和 ListViewEx配合使用
 */
public class HorizontalEx2 extends ViewGroup {
    private int lastX, lastY;
    private int childIndex;
    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;
    public HorizontalEx2(Context context) {
        super(context);
        init();
    }
    public HorizontalEx2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public HorizontalEx2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init() {
        mScroller = new Scroller(getContext());
        mVelocityTracker = VelocityTracker.obtain();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int childCount = getChildCount();
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        if (childCount == 0) {
            setMeasuredDimension(0, 0);
        } else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            height = getChildAt(0).getMeasuredHeight();
            width = childCount * getChildAt(0).getMeasuredWidth();
            setMeasuredDimension(width, height);
        } else if (widthMode == MeasureSpec.AT_MOST) {
            width = childCount * getChildAt(0).getMeasuredWidth();
            setMeasuredDimension(width, height);
        } else {
            height = getChildAt(0).getMeasuredHeight();
            setMeasuredDimension(width, height);
        }
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int leftOffset = 0;
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            child.layout(l + leftOffset, t, r + leftOffset, b);
            leftOffset += child.getMeasuredWidth();
        }
    }
    /**
     * 不拦截Down事件,其他一律拦截
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
                return true;
            }
            return false;
        } else {
            return true;
        }
    }
    private boolean isFirstTouch = true;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        mVelocityTracker.addMovement(event);
        ViewConfiguration configuration = ViewConfiguration.get(getContext());
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isFirstTouch) {
                    isFirstTouch = false;
                    lastY = y;
                    lastX = x;
                }
                final int deltaX = x - lastX;
                scrollBy(-deltaX, 0);
                break;
            case MotionEvent.ACTION_UP:
                isFirstTouch = true;
                int scrollX = getScrollX();
                mVelocityTracker.computeCurrentVelocity(1000, configuration.getScaledMaximumFlingVelocity());
                float mVelocityX = mVelocityTracker.getXVelocity();
                if (Math.abs(mVelocityX) > configuration.getScaledMinimumFlingVelocity()) {
                    childIndex = mVelocityX < 0 ? childIndex + 1 : childIndex - 1;
                } else {
                    childIndex = (scrollX + getChildAt(0).getWidth() / 2) / getChildAt(0).getWidth();
                }
                childIndex = Math.min(getChildCount() - 1, Math.max(0, childIndex));
                smoothScrollBy(childIndex*getChildAt(0).getWidth()-scrollX,0);
                mVelocityTracker.clear();
                break;
        }
        lastX = x;
        lastY = y;
        return true;
    }
    private void smoothScrollBy(int dx, int dy) {
        mScroller.startScroll(getScrollX(), getScrollY(), dx, dy,500);
        invalidate();
    }
    @Override
    public void computeScroll() {
        if(mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            postInvalidate();
        }
    }
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mVelocityTracker.recycle();
    }
}

ListViewEx.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<code class="hljs java">
/**
 * Created by blueberry on 2016/6/20.
 * 内部拦截事件
 */
public class ListViewEx extends ListView {
    private int lastXIntercepted, lastYIntercepted;
    private HorizontalEx2 mHorizontalEx2;
    public ListViewEx(Context context) {
        super(context);
    }
    public ListViewEx(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public ListViewEx(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public HorizontalEx2 getmHorizontalEx2() {
        return mHorizontalEx2;
    }
    public void setmHorizontalEx2(HorizontalEx2 mHorizontalEx2) {
        this.mHorizontalEx2 = mHorizontalEx2;
    }
    /**
     * 使用 outter.requestDisallowInterceptTouchEvent();
     * 来决定父控件是否对事件进行拦截
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mHorizontalEx2.requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:
                final int deltaX = x-lastYIntercepted;
                final int deltaY = y-lastYIntercepted;
                if(Math.abs(deltaX)>Math.abs(deltaY)){
                    mHorizontalEx2.requestDisallowInterceptTouchEvent(false);
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        lastXIntercepted = x;
        lastYIntercepted = y;
        return super.dispatchTouchEvent(ev);
    }
}
</code>

调用代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<code class="hljs lasso"> @Override
    public void showInnerHVData(List<string> data1, List<string> data2, List<string> data3) {
        ListViewEx listView1 = new ListViewEx(getContext());
        ArrayAdapter<string> adapter1 = new ArrayAdapter<string>(getContext(), android.R.layout.simple_list_item_1, data1);
        listView1.setAdapter(adapter1);
        listView1.setmHorizontalEx2(mHorizontalEx2);
        ListViewEx listView2 = new ListViewEx(getContext());
        ArrayAdapter<string> adapter2 = new ArrayAdapter<string>(getContext(), android.R.layout.simple_list_item_1, data2);
        listView2.setAdapter(adapter2);
        listView2.setmHorizontalEx2(mHorizontalEx2);
        ListViewEx listView3 = new ListViewEx(getContext());
        ArrayAdapter<string> adapter3 = new ArrayAdapter<string>(getContext(), android.R.layout.simple_list_item_1, data3);
        listView3.setAdapter(adapter3);
        listView3.setmHorizontalEx2(mHorizontalEx2);
        ViewGroup.LayoutParams params
                = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        mHorizontalEx2.addView(listView1, params);
        mHorizontalEx2.addView(listView2, params);
        mHorizontalEx2.addView(listView3, params);
    }

android滑动冲突的解决方案相关推荐

  1. Android滑动冲突的完美解决方案

    一.Android滑动冲突的完美解决方案 在Android开发中滑动冲突可以说是比较常见的一类问题,也是比较让人头疼的一类问题,两个原本完美的控件,组合在一起之后,忽然发现整个世界都不好了.滑动冲突主 ...

  2. 每日一问:Android 滑动冲突,你们都是怎样处理的

    坚持原创日更,短平快的 Android 进阶系列,敬请直接在微信公众号搜索:nanchen,直接关注并设为星标,精彩不容错过. 在 Android 开发中,滑动冲突总是我们一个无法避免的话题.而对于解 ...

  3. Android滑动冲突解决方法

    Android滑动冲突解决方法 滑动冲突 首先讲解一下什么是滑动冲突.当你需要在一个ScrollView中嵌套使用ListView或者RecyclerView的时候你会发现只有ScrollView能够 ...

  4. Android滑动冲突解决方法(二)

    之前的一遍学习笔记主要就Android滑动冲突中,在不同方向的滑动所造成冲突进行了了解,这种冲突很容易理解,当然也很容易解决.今天,就同方向的滑动所造成的冲突进行一下了解,这里就先以垂直方向的滑动冲突 ...

  5. 关于Android滑动冲突的解决方法(二)

    之前的一遍学习笔记主要就Android滑动冲突中,在不同方向的滑动所造成冲突进行了了解,这种冲突很容易理解,当然也很容易解决.今天,就同方向的滑动所造成的冲突进行一下了解,这里就先以垂直方向的滑动冲突 ...

  6. 一种嵌套滑动冲突的解决方案

    非嵌套滑动 | 嵌套滑动 相比起非嵌套滑动的自定义分发事件的方案,嵌套滑动冲突有比较成熟的 Google 解决方案:NestedScrolling . 三层嵌套的滑动冲突 UI 层级如下: 最外层(底 ...

  7. Android滑动冲突解决方式(下拉刷新上拉加载更多,适配RecyclerView/ListView/ScrollView)

    一.Android事件的分发机制 这里需要了解下Andorid事件的分发机制.事件分发一般是针对一组事件,即ACTION_DOWN > ACTION_UP 或 ACTION_DOWN > ...

  8. android 滑动冲突

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 通过move事件的 拦截. 在滑动组件中,重写 在拦截触摸事件的时候  这个方法, 然后 ...

  9. Android View的事件分发机制和滑动冲突解决方案

    这篇文章会先讲Android中View的事件分发机制,然后再介绍Android滑动冲突的形成原因并给出解决方案.因水平有限,讲的不会太过深入,只希望各位看了之后对事件分发机制的流程有个大概的概念,并且 ...

最新文章

  1. Asp.Net Core 视图整理(一)
  2. python怎样画立体图形-用python来画出高光谱遥感影像的3D立体图
  3. android动态jar,Android动态加载Jar(包含第三方依赖Jar)
  4. leetcode 之Single Number(13)
  5. Kibana:数据分析的可视化利器
  6. Linux环境下Protobuf完整安装和使用教程
  7. 洛谷——P1151 子数整数
  8. 关于加载表格及模态框数据回填的Bug
  9. 3D Segmentation with Exponential LogarithmicLoss for Highly Unbalanced Object Sizes-MICCAI2018【论文理解】
  10. WinForm timer 控件
  11. cef 加载flash 弹框_cef 3.2357之后加载flash的方法
  12. 目的路径太长如哈删除_win7系统删除文件夹提示“无法访问此文件夹 路径太长”如何解决...
  13. 在Android浏览器下字体偏上的问题
  14. 关于使用NLPIR-ICTCLAS分词系统
  15. arp 已知mac找ip_求救:通过MAC码找到对应的IP地址.
  16. 日知录(九):PR视频剪辑Creo
  17. 软件资产管理重在license
  18. 有哪些好用的国产婴儿润肤霜?纽强怎么样?
  19. 如何做好团队测试建设
  20. 小数化分数(C++)

热门文章

  1. java fx svg 图像 缩放 控件,支持调整SVG图像大小!Aspose.Imaging v19.11新功能示例演示!...
  2. 再谈多态——向上映射及VMT/DMT
  3. 如何安装打印机驱动程序
  4. 超全的 100 个 Pandas 函数汇总,建议收藏
  5. 计算机无法连接网络错误651,宽带连接错误651怎么解决?
  6. 小白之路由浅入深之------day05
  7. Phonetic symbol 辅音 - 清辅音 -- /f/
  8. 笔试中怎么答产品设计类题目
  9. 毫米波雷达相关知识调研
  10. zii.widgets.jui.CJuiDatePicker