Android之按钮点击事件(单击、双击、长按等)

在布局文件中添加按钮点击事件

在java文件中添加按钮点击事件

为多个按钮添加点击事件

按钮按下、释放事件

按钮长按事件

按钮长按时过滤掉单击事件

按钮双击事件

按钮双击时过滤掉单击事件

在布局文件中添加按钮点击事件
1、在xml文件中 为 Button 添加android:onclick属性

<Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="btn"
    android:textAllCaps="false"
    android:onClick="showMsg"/>

android:onclick属性的值"showMsg"即为用户点击屏幕按钮时触发方法的名字。
PS:Android系统会自动对Button中的所有英文字母转换成大写,android:textAllCaps属性的值设置为“false”可以禁用此设置。

2、在对应的.java文件中添加名为showMsg的方法

此方法需满足以下条件:

与xml布局文件中名称一致
是public函数
无返回值(void 类型)
参数唯一(为View类型,代表被点击的视图)
/** Called when the user clicks the Button named btn */
public void showMsg(View view){
Toast.makeText(MainActivity.this, “btn is clicked!”, Toast.LENGTH_SHORT).show();
}

在java文件中添加按钮点击事件

public class MainActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
         final Button btn = (Button) findViewById(R.id.btn);
         btn.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
             public void onClick(View v) {
    
    
                 // Perform action on click
                 Toast.makeText(MainActivity.this, "btn is clicked!", Toast.LENGTH_SHORT).show();
             }
         });
    }
}

setOnClickListener()方法为Button的点击事件注册了一个监听器,每当点击按钮时,就会执行监听器中的onClick()方法。

为多个按钮添加点击事件
处理多个按钮的点击事件时,可以使用上面的方式为每个按钮分别绑定事件监听器,也可以使用下面的方式定义一个实现监听器的类,当然,下面的方式结构更加清晰。

public class MainActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button btn = (Button) findViewById(R.id.btn);
        final Button btn2 = (Button) findViewById(R.id.btn2);
        final Button btn3 = (Button) findViewById(R.id.btn3);

        OnClick onClick = new OnClick();
        btn.setOnClickListener(onClick);
        btn2.setOnClickListener(onClick);
        btn3.setOnClickListener(onClick);
    }

    private class OnClick implements View.OnClickListener{
    
    
        @Override
        public void onClick(View v) {
    
    
            switch (v.getId()){
    
    
                case R.id.btn:
                    Log.d("btn listener:", "btn is clicked!");
                    break;
                case R.id.btn2:
                    Log.d("btn listener:", "btn2 is clicked!");
                    break;
                case R.id.btn3:
                    Log.d("btn listener:", "btn3 is clicked!");
                    break;
                default:
                    break;
            }
        }
    }
}

按钮按下、释放事件
一个按钮点击的完整过程是:pressed + released = clicked,所以当按下按钮并滑动到按钮之外的区域释放时,点击事件并不会触发。如果需要分别处理按钮的按下和释放事件则可以使用下面的方式。

public class MainActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        final Button btn = (Button) findViewById(R.id.btn);
        btn.setOnTouchListener(new View.OnTouchListener() {
    
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
    
    
                if(v.getId() == R.id.btn){
    
    
                    if(event.getAction() == MotionEvent.ACTION_DOWN){
    
    
                        Log.e("btn listener:", "btn is pressed!");
                    }
                    else if(event.getAction() == MotionEvent.ACTION_UP){
    
    
                        Log.e("btn listener:", "btn is released!");
                    }
                }
                return false;
            }
        });
    } 
}

按钮长按事件

public class MainActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                Log.d("btn listener:", "btn is clicked!");
            }
        });
        btn.setOnLongClickListener(new View.OnLongClickListener() {
    
    
            @Override
            public boolean onLongClick(View v) {
    
    
                Log.d("btn listener:", "btn is longClicked!");
                return false;
            }
        });
    }
}

PS:上面的代码运行后会先打印btn listener:: btn is longClicked!,然后打印btn listener:: btn is clicked!,因为按钮长按时仍然会触发点击事件。如果只需要处理长按事件的话则不需考虑这一点,如果要在同一个按钮单击或长按时处理不同的内容,则需在长按时过滤掉单击事件。

按钮长按时过滤掉单击事件

btn.setOnLongClickListener(new View.OnLongClickListener(){
    
    
    @Override
    public boolean onLongClick(View v){
    
    
        Log.d("btn listener:","btn is longClicked!");
        return true;
    }
});

将此处长按事件的返回值改为true即可过滤掉单击事件。
这里涉及到事件传播的问题,当处理事件的返回值为false时表示该事件未完全处理完毕,事件会继续向下传播。

按钮双击事件

public class MainActivity extends AppCompatActivity {
    
    

    private static final long CLICK_INTERVAL_TIME = 300;
    private static long lastClickTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    

                //获取系统当前毫秒数,从开机到现在的毫秒数(手机睡眠时间不包括在内)
                long currentTimeMillis = SystemClock.uptimeMillis();
                //两次点击间隔时间小于300ms代表双击
                if (currentTimeMillis - lastClickTime < CLICK_INTERVAL_TIME) {
    
    
                    Log.d("btn listener:", "btn is doubleClicked!");
                    return;
                }
                lastClickTime = currentTimeMillis;
                Log.d("btn listener:", "btn is clicked!");
            }
        });
    }
}

PS:使用System.currentTimeMillis()获取系统当前毫秒数,是从1970年1月1日UTC到现在的毫秒数,如果系统时间被修改,此毫秒数会不正确。
PS:上面的代码运行后会先打印btn listener:: btn is clicked!,然后打印btn listener:: btn is doubleClicked!,因为按钮双击时仍然会先触发单击事件。如果只需要处理双击事件的话则不需考虑这一点,如果要在同一个按钮单击或双击时处理不同的内容,则需在双击时过滤掉单击事件。

按钮双击时过滤掉单击事件
双击时过滤单击事件的思路可参考以前在Qt中的应用(QML之MouseArea双击时过滤掉单击事件):在按钮点击时开启定时器,判断300ms内有没有第二次点击,有的话表示双击,没有的话表示单击。这里使用Handler的postDelayed()方法来处理延时。

 public class MainActivity extends AppCompatActivity {
    
    
    private int clickNum = 0;
    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Button btn = (Button) findViewById(R.id.btn);
        final Button btn2 = (Button) findViewById(R.id.btn2);
        btn.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                clickNum++;
                handler.postDelayed(new Runnable() {
    
    
                    @Override
                    public void run() {
    
    
                        if (clickNum == 1) {
    
    
                            Log.d("btn listener:", "btn is clicked!");
                        }else if(clickNum==2){
    
    
                            Log.d("btn listener:", "btn is doubleClicked!");
                        }
                        //防止handler引起的内存泄漏
                        handler.removeCallbacksAndMessages(null);
                        clickNum = 0;
                    }
                },300);
            }
        });
    }
}

PS:Handler的removeCallbacksAndMessages(null)方法会移除所有的callbacks和messages,可有效避免Handler引起的内存泄漏。removeCallbacks(Runnable r) 方法可以移除即将发布到消息队列中的Runnable对象,终止延时。

long[] mHits =new long[2];
@OnClick(R.id.google_btn)
public void  clickGoogle_btn(){
    
    
    //实现数组的位移操作,点击一次,左移一位,末尾补上当前开机时间(cpu时间)
    System.arraycopy(mHits,1,mHits,0,mHits.length-1);
    mHits[mHits.length-1]=SystemClock.uptimeMillis();

    if(500>(SystemClock.uptimeMillis()-mHits[0])){
    
    
        //此处执行双击事件
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25749749/article/details/131867362