Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android中ScrollView中的MotionEvent处理_Android_Touch_Scrollview_Motionevent - Fatal编程技术网

Android中ScrollView中的MotionEvent处理

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) {

我一直在试图弄清楚Android中ScrollView中MotionEvents的行为,但有些事情我搞不清楚

例如,我制作了一个活动,其中包含一个ScrollView,ScrollView中包含一个LinearLayout。我实现了自己的类来控制触摸相关功能:

    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()的最好解释。非常感谢!