Aby*_*yss 2 java eclipse layout android view
我有父视图v扩展线性布局.孩子一个是LinearLayout,孩子二个是ScrollView.
我要让MyParent查看拦截垂直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>
Run Code Online (Sandbox Code Playgroud)
这是我的代码如下
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;
}
Run Code Online (Sandbox Code Playgroud)
isReadyForPull() 功能只检查这个
private boolean isReadyForPull(){
return mScrollView.getScrollY()==0;
}
Run Code Online (Sandbox Code Playgroud)
我的代码效果很好.
如果我向下移动我的孩子滚动视图,onInterceptTouchEvent首先得到MotionEvent.ACTION_DOWN和初始化值,并获得顺序MotionEvent.ACTION_MOVE所以设置mIsBeingDragged标志真实,并返回真.所以,我可以处理我的事件ParentView的onTouchEvent.
否则,如果我动起来的孩子滚动视图,然后onInterceptTouchEvent返回false和我的孩子滚动视图获取MotionEvent和向下滚动.
这是预期的工作.好.
但是,当我触摸我的孩子线性布局时,它不起作用!
如果我触摸并拖动我的孩子的LinearLayout,我CustomView的onInterceptTouchEvent获得MotionEvent.ACTION_DOWN,但不能得到第二MotionEvent.ACTION_MOVE.
为什么这不仅适用于儿童线性布局?
注意:我测试了几次,并且知道(默认)可触摸视图或视图组(如按钮,滚动视图等)可以使用我的代码,而(默认)不可触摸的视图或小部件(如imageview,framelayout)不适用于我的码.
解决方案与此答案有关,因为它是标准MotionEvent处理的结果.
在我的代码中,当我触摸孩子时LinearLayout,父母CustomViewGroup不会拦截MotionEvent它,因为它返回false,但我的孩子LinearLayout不消耗MotionEvent任何一个,所以MotionEvent它返回到父亲onTouchEvent,而不是onInterceptTouchEvent.
另一方面,当我触摸我的孩子时ScrollView,它会消耗MotionEvent是否启用滚动.
==>我认为因为Android不会再生成一个MotionEvent,直到原来的一个被消费或完成,所以父母CustomViewGroup没有得到ACTION_MOVE MotionEvent通过onInterceptTouchEvent,onTouchEvent当一个孩子没有消费时,安装它是通过管道传输的MotionEvent.
我发现了两个解决方案
强行让我LinearLayout消耗掉MotionEvent.此解决方案仅在儿童LinearLayout无法触摸时可用View,ViewGroup或者Widget.像这样:
LinearLayout mLinearLayout = (LinearLayout)findViewById(R.id.child_linear);
mLinearLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Run Code Online (Sandbox Code Playgroud)
过程中,MotionEvent从一个孩子在我回来CustomViewGroup的onTouchEvent.像这样:(如果情况允许,只需添加其他内容onTouchEvent).
case MotionEvent.ACTION_MOVE: {
if (mIsBeingDragged) {
mLastMotionY = event.getY();
mLastMotionX = event.getX();
pullEvent();
return true;
}
else 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;
}
}
break;
}
Run Code Online (Sandbox Code Playgroud)
虽然解决方案1是某些情况下的快速解决方案,但解决方案2是最灵活和最可靠的.
| 归档时间: |
|
| 查看次数: |
7175 次 |
| 最近记录: |