Android onTouch、OnLongClick、onClick和ScrollView滑动事件冲突

        为了实现近期录制的长按,松开手指,结束录制功能。在项目,难道你去走一走会头晕,书写demo为了下一个梳理。

顺便研究android事件调用机制。

  先上效果界面:

布局

   

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:layout_centerInParent="true"
        android:background="@drawable/microp_btn_normal" />

</RelativeLayout>

代码:

package com.example.androidtest;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.app.Activity; 
import android.app.Dialog;
import android.content.Intent;

public class MainActivity extends Activity {

	private Button btn;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btn = (Button) findViewById(R.id.btn);
		
		btn.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View arg0, MotionEvent arg1) {
				Log.d("TAG", "onTouch is called.............");
				return false;
			}
		});
		
		btn.setOnLongClickListener(new OnLongClickListener() {
			
			@Override
			public boolean onLongClick(View arg0) { 
				Log.d("TAG", "onLongClick is called.............");
				return false;
			}
		});
		
		btn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) { 
				Log.d("TAG", "onClick is called.............");
			}
		});
	}

	
}

在代码中。我们监听了onTouch、onLongClick、onClick事件,当中onTouch和OnLongClick有返回值,onClick没有返回值。

现执行以上代码,长按button。我们能够看到调用顺序为

onTouch->onLongClick->onClick

现将OnTouch的返回值改为true,可发现onLongClick和onClick事件没有调用。

说明onTouch返回true,兴许事件没有传递。


接下来我们看下onTouch详细触发了哪些事件(仅仅长按)

btn.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View arg0, MotionEvent arg1) {
				//Log.d("TAG", "onTouch is called.............");
				switch (arg1.getAction()) {
				case MotionEvent.ACTION_DOWN:
					Log.d("TAG", "ACTION_DOWN.............");
					break;
				case MotionEvent.ACTION_MOVE:
					Log.d("TAG", "ACTION_MOVE.............");
					break;
				case MotionEvent.ACTION_CANCEL:
					Log.d("TAG", "ACTION_CANCEL.............");
					break;
				case MotionEvent.ACTION_UP:
					Log.d("TAG", "ACTION_UP.............");
					break;
				default:
					break;
				}
				return false;
			}
		});

看下日志截图

我仅仅是按住,并未滑动。

我们将onLongClick返回true。能够预见,onClick事件不会被触发。

但ACTION_UP呢?

经验证ACTION_UP被触发了。

接下来我们换下布局文件:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
	<View android:layout_width="match_parent"
	    android:layout_height="1000dp"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn" 
        android:layout_gravity="center_horizontal"
        android:background="@drawable/microp_btn_normal" />

</LinearLayout>
</ScrollView>

意图非常easy,让我们的button在滚动栏的底部,日志截图


  这时,我们的ACTION_UP没被触发,最后触发的是ACTION_CANCLE,并且我按了好几次才让它触发onLongClick事件。大多数仅仅触发了DOWN/MOVE/CANCLE事件。

我怀疑是ScrollView滑动事件与onTouch事件冲突

在onTouch加上一句防冲突代码

btn.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View arg0, MotionEvent arg1) {
				//Log.d("TAG", "onTouch is called.............");
				arg0.getParent().requestDisallowInterceptTouchEvent(true);//通知父控件勿拦截本控件touch事件
				switch (arg1.getAction()) {
				case MotionEvent.ACTION_DOWN:
					Log.d("TAG", "ACTION_DOWN.............");
					break;
				case MotionEvent.ACTION_MOVE:
					Log.d("TAG", "ACTION_MOVE.............");
					break;
				case MotionEvent.ACTION_CANCEL:
					Log.d("TAG", "ACTION_CANCEL.............");
					break;
				case MotionEvent.ACTION_UP:
					Log.d("TAG", "ACTION_UP.............");

					btn.setBackgroundResource(R.drawable.microp_btn_normal);
					break;
				default:
					break;
				}
				return false;
			}
		});

arg0.getParent().requestDisallowInterceptTouchEvent(true);//通知父控件勿拦截本控件touch事件

这样我们就和我们预期一样。


总结:

由于我的长按录制音频在ScrollView中,没有做onTouch冲突处理,所以出现非常多莫名其妙的问题。

如今要实现我们的要求,仅仅要在onLongClick中录制,ACTION_UP结束就可以。

demo下载:http://download.csdn.net/detail/msl0903/7224487


版权声明:本文博主原创文章。博客,未经同意不得转载。

posted @ 2015-10-15 12:13  blfshiye  阅读(731)  评论(0编辑  收藏  举报