Android中ScrollView中的MotionEvent处理
我一直在试图弄清楚Android中ScrollView中MotionEvents的行为,但有些事情我搞不清楚 例如,我制作了一个活动,其中包含一个ScrollView,ScrollView中包含一个LinearLayout。我实现了自己的类来控制触摸相关功能:Android中ScrollView中的MotionEvent处理,android,touch,scrollview,motionevent,Android,Touch,Scrollview,Motionevent,我一直在试图弄清楚Android中ScrollView中MotionEvents的行为,但有些事情我搞不清楚 例如,我制作了一个活动,其中包含一个ScrollView,ScrollView中包含一个LinearLayout。我实现了自己的类来控制触摸相关功能: public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) {
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyInnerLayout inner = new MyInnerLayout(getApplicationContext());
MyLayout layout = new MyLayout(getApplicationContext());
layout.addView(inner,new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
setContentView(layout);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i("scrollview","activity dispatchTouchEvent "+ev.getAction());
return super.dispatchTouchEvent(ev);
};
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.i("scrollview","activity on touch "+ev.getAction());
return super.onTouchEvent(ev);
}
public class MyLayout extends ScrollView {
public MyLayout(Context context) {
super(context);
}
@Override
public boolean dispatchKeyEvent(KeyEvent ev) {
Log.i("scrollview","layout dispatchKeyEvent "+ev.getAction());
return super.dispatchKeyEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i("scrollview","layout onInterceptTouchEvent "+ev.getAction());
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.i("scrollview","layout on touch "+ev.getAction());
return false;
}
}
public class MyInnerLayout extends LinearLayout{
public MyInnerLayout(Context context) {
super(context);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i("scrollview","inner layout dispatchTouchEvent "+ev.getAction());
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i("scrollview","inner layout onInterceptTouchEvent "+ev.getAction());
return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.i("scrollview","inner layout on touch "+ev.getAction());
return true;
}
}
}
当我单击屏幕上的任意位置时,我会得到以下日志:
10-14 18:11:48.631: I/scrollview(14906): activity dispatchTouchEvent 0
10-14 18:11:48.631: I/scrollview(14906): layout onInterceptTouchEvent 0
10-14 18:11:48.631: I/scrollview(14906): layout on touch 0
10-14 18:11:48.631: I/scrollview(14906): activity on touch 0
10-14 18:11:48.647: I/scrollview(14906): activity dispatchTouchEvent 1
10-14 18:11:48.647: I/scrollview(14906): activity on touch 1
这意味着触摸事件没有进入scrollview内部的内部布局。
但是,当我将ScrollView更改为LinearLayout(只需在extends中更改它)时,事件将转到内部布局:
10-14 18:24:08.975: I/scrollview(15115): activity dispatchTouchEvent 0
10-14 18:24:08.975: I/scrollview(15115): layout onInterceptTouchEvent 0
10-14 18:24:08.975: I/scrollview(15115): inner layout dispatchTouchEvent 0
10-14 18:24:09.045: I/scrollview(15115): activity dispatchTouchEvent 1
10-14 18:24:09.045: I/scrollview(15115): layout onInterceptTouchEvent 1
10-14 18:24:09.045: I/scrollview(15115): inner layout dispatchTouchEvent 1
我查看了一下,它覆盖的唯一与触摸相关的方法是我自己覆盖的方法。因此,我不明白LinearLayout和ScrollView的行为之间有什么区别。也许您已经了解了上述行为的原因,但如果您不了解,原因如下 概述 onInterceptTouchEvent()称为自顶向下(从父视图到子视图),允许一个视图在由子视图处理之前拦截运动事件
onTouchEvent()
从上往下调用(从子对象到父对象),直到其中一个消耗完它,循环结束
ScrollView
截取MotionEvent
,检查在将视图传递给子视图之前是否应该滚动视图。如果要执行滚动,则会使用事件,并且子视图看不到任何内容
在LinearLayout
的情况下,没有理由在onInterceptTouchEvent()
期间使用事件,并且总是将事件传递给子视图
您的代码中发生了什么
由于MyInnerLayout
为空,ScrollView
始终使用MotionEvent
例如,如果将内部布局背景设置为:
MyInnerLayout inner = new MyInnerLayout(getApplicationContext());
inner.setBackground(getResources().getDrawable(R.drawable.ic_launcher));
MyLayout layout = new MyLayout(getApplicationContext());
您将看到,如果您触摸背景图像,事件将到达孩子。如果触摸背景图像外部,事件将被滚动视图
使用
希望这有帮助
尊敬。我在滚动视图上有带动画的视图。动画strat和stop等于运动事件(向下和向上)。我修复了相同的解决方案:
public class RootActivity extends Activity implements OnTouchListener {
private View tochedView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_root);
((View) findViewById(R.id.btnOther)).setOnTouchListener(this);
ScrollView scroll = (ScrollView) findViewById(R.id.scrollView);
scroll.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP && tochedView != null) {
Log.i("Touche", "ScrollView ACTION_UP");
Animation upAnim = AnimationUtils.loadAnimation(RootActivity.this, R.anim.btn_up_anim);
tochedView.startAnimation(upAnim);
tochedView = null;
return true;
}
return false;
}
});
}
private void animateView(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.i("Touche", "ACTION_DOWN");
Animation downAnim = AnimationUtils.loadAnimation(this, R.anim.btn_down_anim);
v.startAnimation(downAnim);
tochedView = v;
}
if (event.getAction() == MotionEvent.ACTION_UP && tochedView != null) {
Log.i("Touche", "ACTION_UP");
Animation upAnim = AnimationUtils.loadAnimation(this, R.anim.btn_up_anim);
v.startAnimation(upAnim);
tochedView = null;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
animateView(v, event);
}
}问题与触摸事件无关,而是与ScrollView和LinearLayout的布局参数不同:FILL\u PARENT在ScrollView中没有意义,相反,我必须将SetFillViewport设置为true:)谢谢。这是我读过的关于onInterceptTouchEvent()和onTouchEvent()的最好解释。非常感谢!