在佈局文件中添加按鈕點擊事件
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對象,終止延時。