您的位置:首页 > 其它

横向ListView中嵌套ListView

2016-01-30 08:04 399 查看
最近有个需求,横向列表中,每项又是一个垂直列表。在HorizontalListView的Adapter中使用Listview后,HorizontalListView不能左右滑动。

1,解决这个问题,先来看几个基础的方法:,

View类中:

/**
* Pass the touch screen motion event down to the target view, or this
* view if it is the target.
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
*/
public boolean dispatchTouchEvent(MotionEvent event) {


@Override
public boolean onTouchEvent(MotionEvent event) {


/**
* {@inheritDoc}
*/
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {


ViewGroup类中:注意加粗有下划线的部分的内容

/**
* Implement this method to intercept all touch screen motion events.  This
* allows you to watch events as they are dispatched to your children, and
* take ownership of the current gesture at any point.
*
* <p>Using this function takes some care, as it has a fairly complicated
* interaction with {@link View#onTouchEvent(MotionEvent)
* View.onTouchEvent(MotionEvent)}, and using it requires implementing
* that method as well as this one in the correct way.  Events will be
* received in the following order:
*
* <ol>
* <li> You will receive the down event here.
* <li> The down event will be handled either by a child of this view
* group, or given to your own onTouchEvent() method to handle; this means
* you should implement onTouchEvent() to return true, so you will
* continue to see the rest of the gesture (instead of looking for
* a parent view to handle it).  Also, by returning true from
* onTouchEvent(), you will not receive any following
* events in onInterceptTouchEvent() and all touch processing must
* happen in onTouchEvent() like normal.
* <li> For as long as you return false from this function, each following
* event (up to and including the final up) will be delivered first here
* and then to the target's onTouchEvent().
* <li> If you return true from here, you will not receive any
* following events: the target view will receive the same event but
* with the action {@link MotionEvent#ACTION_CANCEL}, and all further
* events will be delivered to your onTouchEvent() method and no longer
* appear here.
* </ol>
*
* @param ev The motion event being dispatched down the hierarchy.
* <strong><u><span style="color:#ff0000;">@return Return true to steal motion events from the children and have
* them dispatched to this ViewGroup through onTouchEvent().
* The current target will receive an ACTION_CANCEL event, and no further
* messages will be delivered here.</span></u></strong>
*/
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}


2,测试代码

HorizontalListView每个item为ListView,ListView的每个Item为TextView,Touch事件分发过程为:

</pre><pre code_snippet_id="1570234" snippet_file_name="blog_20160130_7_9380784" name="code" class="html">--------- beginning of main
--------- beginning of system
D/DemoApp (20605): MyHorizontalListView dispatchTouchEvent:0
D/DemoApp (20605): MyHorizontalListView onInterceptTouchEvent:0
D/DemoApp (20605): MyListView dispatchTouchEvent:0
D/DemoApp (20605): MyListView onInterceptTouchEvent:0
D/DemoApp (20605): MyTextView dispatchTouchEvent:0
D/DemoApp (20605): MyTextView onTouchEvent:0
D/DemoApp (20605): MyListView onTouchEvent:0, gestureDealed:true
D/DemoApp (20605): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (20605): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (20605): MyListView dispatchTouchEvent:2
D/DemoApp (20605): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (20605): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (20605): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (20605): MyListView dispatchTouchEvent:2
D/DemoApp (20605): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (20605): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (20605): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (20605): MyListView dispatchTouchEvent:2
D/DemoApp (20605): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (20605): MyHorizontalListView dispatchTouchEvent:1
D/DemoApp (20605): MyHorizontalListView onInterceptTouchEvent:1
D/DemoApp (20605): MyListView dispatchTouchEvent:1
D/DemoApp (20605): MyListView onTouchEvent:1, gestureDealed:false


3,我们再来看View类中的方法:

<pre name="code" class="html">/**
* {@inheritDoc}
*/
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {

if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
// We're already in this state, assume our ancestors are too
return;
}

if (disallowIntercept) {
mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
} else {
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}

// Pass it up to our parent
if (mParent != null) {
mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}



当子类调用请求父类拦截时,主要最开始标红色部分的说明。在下一个Touch事件,父控件会直接交给自己的onTouchEvent处理。

4,所以,为了满足需求我们做如下改造:

自定义MyListView类,修改的地方为:定义手势检测,横向滑动不处理

private GestureDetector mGestureDetector;

/** 是否忽略该滑动事件,忽略则交给父控件处理 */
private boolean ignoreEvent = false;

/** 是否已经判断过滑动方向 */
private boolean checkedDirection = false;

private GestureDetector.OnGestureListener mOnGestureListener = new GestureDetector.SimpleOnGestureListener() {

@Override
public boolean onDown(MotionEvent e) {
ignoreEvent = false;
checkedDirection = false;
return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

if (!checkedDirection) {
checkedDirection = true;
if (Math.abs(velocityX) > Math.abs(velocityY)) {
ignoreEvent = true;
return false;
}
}
if(ignoreEvent){
return false;
}

return true;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

if (!checkedDirection) {
checkedDirection = true;
if (Math.abs(distanceX) > 3 && Math.abs(distanceX) > Math.abs(distanceY)) {
ignoreEvent = true;
return false;
}
}

if(ignoreEvent){
return false;
}

return true;
}
};


@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean gestureDealed = mGestureDetector.onTouchEvent(ev);
GyLog.d(TAG, "onTouchEvent:" + ev.getAction() +", gestureDealed:"+gestureDealed);

if(checkedDirection && ignoreEvent){
requestDisallowInterceptTouchEvent(!ignoreEvent);
}

if (!gestureDealed) {
return false;
}
return super.onTouchEvent(ev);
}

@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
GyLog.d(TAG, "requestDisallowInterceptTouchEvent:" + disallowIntercept);
super.requestDisallowInterceptTouchEvent(disallowIntercept);

ViewParent parent = getParent();
while (parent != null){
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
parent = parent.getParent();
}
}


MyHorizontalListView的改动:

/** 是否拦截touch事件 */
private boolean interceptTouchEvent = false;

@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
GyLog.d(TAG, "requestDisallowInterceptTouchEvent:" + disallowIntercept);

interceptTouchEvent = !disallowIntercept;

super.requestDisallowInterceptTouchEvent(disallowIntercept);
}


@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
GyLog.d(TAG, "onInterceptTouchEvent:"+ ev.getAction());

if(ev.getAction() == MotionEvent.ACTION_DOWN){
interceptTouchEvent = false;
}

return interceptTouchEvent;

//		return super.onInterceptTouchEvent(ev);
}


5,再来看Touch分发流程:

D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:0
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:0
D/DemoApp (28089): MyListView dispatchTouchEvent:0
D/DemoApp (28089): MyListView onInterceptTouchEvent:0
D/DemoApp (28089): MyTextView dispatchTouchEvent:0
D/DemoApp (28089): MyTextView onTouchEvent:0
D/DemoApp (28089): MyListView onTouchEvent:0, gestureDealed:true
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (28089): MyListView dispatchTouchEvent:2
D/DemoApp (28089): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (28089): MyListView dispatchTouchEvent:2
D/DemoApp (28089): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (28089): MyListView dispatchTouchEvent:2
D/DemoApp (28089): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (28089): MyListView dispatchTouchEvent:2
D/DemoApp (28089): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (28089): MyListView dispatchTouchEvent:2
D/DemoApp (28089): MyListView onTouchEvent:2, gestureDealed:false
D/DemoApp (28089): MyListView requestDisallowInterceptTouchEvent:false
D/DemoApp (28089): MyHorizontalListView requestDisallowInterceptTouchEvent:false
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onInterceptTouchEvent:2
D/DemoApp (28089): MyListView dispatchTouchEvent:3
D/DemoApp (28089): MyListView onTouchEvent:3, gestureDealed:false
D/DemoApp (28089): MyListView requestDisallowInterceptTouchEvent:false
D/DemoApp (28089): MyHorizontalListView requestDisallowInterceptTouchEvent:false
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:2
D/DemoApp (28089): MyHorizontalListView onTouchEvent:2
D/DemoApp (28089): MyHorizontalListView dispatchTouchEvent:1
D/DemoApp (28089): MyHorizontalListView onTouchEvent:1


冲突解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: