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
版权声明:本文博主原创文章。博客,未经同意不得转载。