zoukankan      html  css  js  c++  java
  • 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


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

  • 相关阅读:
    (转) qt: usb热插拔(linux);
    Qt: usb热插拔检测(windows);
    C++: 模板函数定义与声明分离;
    bootstrap: 内联表单;
    thinkphp5: 循环输出表格,并固定表格单元宽度(过长省略号)
    响应式菜单栏: bootstrap + jQuery
    Qt: 数据库操作;
    qt: 获取sql数据表的所有的字段;
    Qt: 非阻塞时间延迟;
    egg中使用jwt
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4882023.html
Copyright © 2011-2022 走看看