MotionEvent handling in ScrollView in Android

放肆的年华 提交于 2019-11-29 04:51:56
Luis

Maybe you already figured out why the behaviour above, but just in case you don't, here goes the reason.

Overview

The onInterceptTouchEvent() are called top-down (from parent to child) enabling one view to intercept the motion event before being handled by a child.

The onTouchEvent() are called down-top (from child to parent) until one of them consum it and the cycle finishs.

A ScrollView intercepts MotionEvent to check if it should scroll the view before passing them to the child. If the scroll should to be perfomed, the event is consumed and child view sees nothing.

In the case of LinearLayout, there is no reason why the event should be consumed during onInterceptTouchEvent(), and is always passed to the child view.

What's happening in your code

Because MyInnerLayout is empty the ScrollView is always consuming the MotionEvent.

If, for example, you set the inner layout backgound like this:

    MyInnerLayout inner = new MyInnerLayout(getApplicationContext());
    inner.setBackground(getResources().getDrawable(R.drawable.ic_launcher));
    MyLayout layout = new MyLayout(getApplicationContext());

you will see that if you touch over the background image the event will reach the child. If you touch outside the background image, the event will be consumed by the ScrollView.

Hope this helps.

Regards.

I have views with animations on scroll view. Animations strat and stop equals of motion event (DOWN and UP). I fix the same solution:

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);
}

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!