我有父视图v扩展线性布局 . 而且一个是LinearLayout,二个是ScrollView .
我想让MyParent View截取垂直 MotionEvent.ACTION_MOVE (仅向下方向,子 scrollview.getScrollY()==0
)并在父级处理它,其他MotionEvent由子进程处理
这是MyView.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<LinearLayout
android:id="@+id/child_linear>
android:height="50dp"
android:width="50dp">
...something...
</LinearLayout>
<ScrollView
android:id="@+id/child_scrollview>
<LinearLayout/>
</LinearLayout>
</ScrollView>
</merge>
这是我的代码
public class MyCustomView extends LinearLayout{
public MyCustomView(Context context) {
super(context);
init();
}
private void init(){
setOrientation(LinearLayout.VERTICAL);
LayoutInflater inflater =
(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.MyView, this, true);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
final int action = event.getAction();
Log.d(log,"onInterceptTouchEvent : "+action);
if (action == MotionEvent.ACTION_CANCEL || action ==
MotionEvent.ACTION_UP) {
mIsBeingDragged = false;
return false;
}
if (action != MotionEvent.ACTION_DOWN && mIsBeingDragged) {
return true;
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (isReadyForPull()) {
final float y = event.getY(), x =
event.getX();
final float diff, oppositeDiff, absDiff;
diff = y - mLastMotionY;
oppositeDiff = x - mLastMotionX;
absDiff = Math.abs(diff);
ViewConfiguration config =
ViewConfiguration.get(getContext());
if (absDiff > config.getScaledTouchSlop() &&
absDiff > Math.abs(oppositeDiff) && diff >= 1f) {
mLastMotionY = y;
mLastMotionX = x;
mIsBeingDragged = true;
Log.d(log,"Flag setting");
}
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
mLastMotionY = mInitialMotionY = event.getY();
mLastMotionX = event.getX();
mIsBeingDragged = false;
}
break;
}
}
return mIsBeingDragged;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action=event.getAction();
Log.d(log,"onTouchEvent : "+action);
if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
Log.d(log,"ACTION MOVE RECEIVE");
if (mIsBeingDragged) {
mLastMotionY = event.getY();
mLastMotionX = event.getX();
pullEvent();
return true;
}
break;
}
case MotionEvent.ACTION_DOWN: {
if (isReadyForPull()) {
mLastMotionY = mInitialMotionY = event.getY();
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
if (mIsBeingDragged) {
mIsBeingDragged = false;
if (mState == State.RELEASE_TO_REFRESH ) {
setState(State.REFRESHING);
return true;
}
if (isRefreshing()) {
smoothScrollTo(-mHeaderHeight , null);
return true;
}
setState(State.RESET);
return true;
}
break;
}
}
return false;
}
isReadyForPull()
功能只检查这个
private boolean isReadyForPull(){
return mScrollView.getScrollY()==0;
}
我的代码效果很好 .
如果我向下移动我的子scrollview, onInterceptTouchEvent
首先得到 MotionEvent.ACTION_DOWN 并初始化值,然后按顺序 MotionEvent.ACTION_MOVE 将 mIsBeingDragged 标志设置为 true 并返回 true . 所以我可以在ParentView的 onTouchEvent
中处理事件 .
否则,如果我向上移动子滚动视图,则 onInterceptTouchEvent
返回false并且我的子滚动视图获取MotionEvent并向下滚动 .
这是预期的工作 . 好 .
但是,当我触摸我的孩子线性布局时,它不起作用!
如果我触摸并拖动我的孩子linearlayout,我的CustomView的 onInterceptTouchEvent
得到 MotionEvent.ACTION_DOWN ,但无法得到第二个 MotionEvent.ACTION_MOVE .
为什么这不仅适用于儿童线性布局?
注意:我测试了几次,并且知道(默认)可触摸视图或视图组(如按钮,滚动视图等)可以使用我的代码,而(默认)不可触摸的视图或小部件(如imageview,framelayout)不适用于我的码 .
2 回答
该解决方案与this答案有关,因为它是标准
MotionEvent
处理的结果 .在我的代码中,当我触摸子
LinearLayout
时,父CustomViewGroup
不拦截MotionEvent
,因为它返回false,但是我的孩子LinearLayout
也没有消耗MotionEvent
,所以MotionEvent
返回到父亲的onTouchEvent
,而不是onInterceptTouchEvent
.另一方面,当我触摸我的孩子
ScrollView
时,无论是启用还是禁用滚动,它都会消耗MotionEvent
.==> 我认为因为Android在原始版本被消耗或完成之前不再生成
MotionEvent
,所以父CustomViewGroup
没有通过onInterceptTouchEvent
获得ACTION_MOVE
MotionEvent
,当孩子不消耗时,它被管道传送到onTouchEvent
MotionEvent
.我找到了两个解决方案
解决方案一
强行让我
LinearLayout
消耗MotionEvent
. 只有当孩子LinearLayout
没有可触摸View
,ViewGroup
或Widget
时,此解决方案才可用 . 像这样:解决方案二
在
CustomViewGroup
的onTouchEvent
中处理从孩子返回的MotionEvent
. 像这样:(如果onTouchEvent
中的情况,只需添加其他内容) .虽然解决方案1是某些情况下的快速解决方案,但解决方案2是最灵活和最可靠的 .
有很好的答案
onInterceptTouchEvent only gets ACTION_DOWN