Button點選事件的五種寫法
操作環境
Project:ButtonTest
IDE:Android Studio2.1
學習了幾個月的Android,覺得有必要複習一下前面學過的知識,哪怕再簡單的知識也是可以溫故而知新的。就從最簡單的按鈕點選事件開始吧。我總結了五種不同的寫法,如下:
- 匿名內部類
- 使用View.onClickListener
- 使用onClick屬性
- 自定義單擊事件監聽類
- 使用外部類。
我在佈局上按照不同的寫法放置了五個按鈕,點選不同的按鈕,就會把按鈕上的文字傳遞到頂部的TextView。下面是整體的UI介面:
這是我完成整個部落格之後的介面,由於我是邊寫邊執行邊截圖的,在下面你會看到按鈕是一個一個加上去的。
1. 匿名內部類
這個寫法用得非常多,只要呼叫setOnClickListener(),在裡面傳入匿名內部類就可以了使用介面中的onCLick方法了。
public class ButtonActivity extends AppCompatActivity {
private Button button1;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
textView = (TextView) findViewById(R.id.textView);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("匿名內部類");
}
});
}
}
完成效果:
2. 使用View.onClickListener 介面
我個人很喜歡這種寫法,只要讓Activity繼承View.OnClickListener介面,然後讓Button物件去呼叫setOnClickListener()方法,並在其中傳入this就可以了。在點選事件特別多的時候,這種寫法的優勢就出來了:在OnClick方法中使用switch語句,就可以在不同控制元件的的點選事件中來回切換,非常的簡潔和便利。
public class ButtonActivity extends AppCompatActivity implements View.OnClickListener{
private Button button1,button2;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
//初始化控制元件
textView = (TextView) findViewById(R.id.textView);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
//1.匿名內部類
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("匿名內部類");
}
});
//2.使用View.onClickListener介面
button2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
textView.setText("使用View.onClickListener介面");
}
}
3.使用onClick屬性
這種寫法簡單到有點不可思議,它是五種方法中唯一沒有在程式碼中繼承View.onClickListener介面的,我們所要做的只是在xml檔案中新增onClick屬性:
android:onClick="buttonClick"
然後回到程式碼中寫上下面的方法,方法名稱就是你在OnClick屬性中名字。
//3.使用onClick屬性
public void buttonClick(View v){
textView.setText("使用onClick屬性");
}
完成效果
如果你要設定的按鈕點選事件只有那麼一兩個,這種寫法無疑是非常省事的。但是如果你點選事件很多的話就要小心,因為不同按鈕的點選事件是根據OnClick中的內容確定的,所以在xml檔案中寫太多的OnClick屬性可能會弄混,到頭來你都不記得哪一個方法對應哪一個按鈕了。
那麼有沒有方法可以多個按鈕都同時使用這種寫法呢?答案是有的。你可以在多個Button的節點中使用OnClick屬性,比如android:onClick=”buttonClick”,這時你點選這些按鈕,呼叫的都是同一個buttonClick()方法。為了區分,這時候你就需要再給每一個按鈕設定資源id,然後通過switch語句進行判斷,寫法如下。
public void buttonClick(View v){
int id = v.getId();
switch (id) {
case R.id.bt1:
System.out.println("按鈕1");
break;
case R.id.bt2:
System.out.println("按鈕2");
break;
case R.id.bt3:
System.out.println("按鈕3");
break;
}
}
你可以自己設定多個按鈕,然後列印不同的日誌或者彈出不同的Toast來看看實現效果,這裡我就不實現了。
4.自定義單擊事件監聽類
自定義其實就是建立一個類,然後去繼承View.OnClickListener介面,然後去實現介面中的onClick()方法就可以了。
class MyClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
textView.setText("自定義單擊事件監聽類");
}
}
然後初始化Button按鈕並呼叫setOnClickListener()方法,注意了,這裡傳進去的引數就是我們新建的類MyClickListener的匿名物件。
button4 = (Button) findViewById(R.id.button4);
button4.setOnClickListener(new MyClickListener());
這種寫法應該比較冷門,反正我目前都沒有使用過,畢竟要建立一個類看起來有點畫蛇添足。
完成效果
5.使用外部類
第五種方法比較特別。它跟第四種很像,不同的是onClick()方法一共出現了兩次。那麼這有什麼用呢?我們來試一下就知道了。新建一個外部類OuterClass,自然我們也讓它繼承View.OnClickListener介面,同時也讓它列印一條log日誌,以便我們檢視它是否呼叫了:
//5.使用外部類
class OuterClassListener implements View.OnClickListener{
@Override
public void onClick(View v) {
Log.d("Tag", "父類中的onClick方法");
}
}
接下來的寫法是不是有點眼熟?不錯,跟匿名內部類一樣,只不過這裡的onClick方法編譯器不會自動幫我們生成,需要我們自己動手新增。另外,要注意加上 super.onClick(v)這一句,表示呼叫父類中的onClick方法。
//5.使用外部類
button5 = (Button) findViewById(R.id.button5);
button5.setOnClickListener(new OuterClassListener(){
@Override
public void onClick(View v) {
super.onClick(v);
textView.setText("使用外部類");
}
});
完成效果:
執行之後,點選按鈕,除了我們預期中的TextView的文字發生變化之後,還列印了一條log日誌:
這說明點選按鈕之後,父類和子類的onClick方法都呼叫了。那麼,這樣的寫法有什麼好處呢?這種寫法的好處在於當子類較多時,我們可以把子類的相同程式碼集中到父類中,這樣父類就可以批量實現你所需要的效果,避免了程式碼冗餘。
完整程式碼
最後貼上完整的程式碼吧。本人還在學習中,所以如果有錯誤的話還請大家多多指正。
activity_button.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.lin.mr.buttontest.ButtonActivity">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="接收傳過來的文字"
android:textSize="25sp" />
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="匿名內部類" />
<Button
android:layout_marginTop="10dp"
android:id="@+id/button2"
android:text="使用View.OnClickListener介面"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:onClick="buttonClick"
android:layout_marginTop="10dp"
android:id="@+id/button3"
android:text="使用onClick屬性"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:layout_marginTop="10dp"
android:id="@+id/button4"
android:text="自定義單擊事件監聽類"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:layout_marginTop="10dp"
android:id="@+id/button5"
android:text="使用外部類"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
ButtonActivity
package com.lin.mr.buttontest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class ButtonActivity extends AppCompatActivity implements View.OnClickListener{
private Button button1,button2,button4,button5;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
//初始化控制元件
textView = (TextView) findViewById(R.id.textView);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button4 = (Button) findViewById(R.id.button4);
button4.setOnClickListener(new MyClickListener());
//5.使用外部類
button5 = (Button) findViewById(R.id.button5);
button5.setOnClickListener(new OuterClassListener(){
@Override
public void onClick(View v) {
super.onClick(v);
textView.setText("使用外部類");
}
});
//1.匿名內部類
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("匿名內部類");
}
});
//2.使用View.onClickListener介面
button2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
textView.setText("使用View.onClickListener介面");
}
//3.使用onClick屬性
public void buttonClick(View v){
textView.setText("使用onClick屬性");
}
//4.自定義單擊事件監聽類
class MyClickListener implements View.OnClickListener{
@Override
public void onClick(View v) {
textView.setText("自定義單擊事件監聽類");
}
}
//5.使用外部類
class OuterClassListener implements View.OnClickListener{
@Override
public void onClick(View v) {
Log.d("Tag", "父類中的onClick方法");
}
}
}
補充知識:OnClick()方法中的引數
寫了這麼多種點選事件的寫法之後,有沒有發現onClick()方法中總是需要傳入一個引數呢?這個引數是什麼呢?乍一看,這應該是View的一個物件。我們在學習第3種寫法(使用onClick屬性)時提到了switch語句:
public void buttonClick(View v){
int id = v.getId();
switch (id) {
case R.id.bt1:
break;
case R.id.bt2:
break;
case R.id.bt3:
break;
}
}
注意到這一句:“int id = v.getId();”。v是View的物件,它通過getId()方法獲取到了Button的Id,然後將獲取到的id交給switch進行判斷,從而實現不同按鈕的點選事件。所以onClick()方法裡面的引數就是觸發點選方法執行的元件物件,在這裡,我們的元件毫無疑問就是Button按鈕了。