Android Button และการรับ Event ด้วย OnClick

Android Button และการรับ Event ด้วย OnClick Cover Image

วันนี้พอดีมีน้องคนหนึ่งสอบถามมาเกี่ยวกับ Button ก็เลยทำเป็นบทความมาให้ซะเลย วันนี้จะมาพูดถึงเรื่อง Button ใน Android ครับ เป็นการใช้งาน Button และการ implements OnClickListener เพื่อให้ Button รับค่าต่างๆจากผู้ใช้งาน

จริงๆเรื่องนี้ไม่ได้เป็นเรื่องที่ใหม่ หรือยุ่งยากอะไรเลย เพียงแต่ถ้าเป็นมือใหม่ หรือเพิ่งหัดเขียน Android ก็อาจจะงงอยู่บ้างเล็กน้อย

Button คืออะไร?

Button นั้นเป็น View ตัวนึง ที่ผู้ใช้สามารถกดหรือคลิกได้ Button นั้นเป็นได้ทั้งตัวอักษร หรือว่าจะเป็นรูปภาพ หรือแม้แต่จะเป็น Button ที่มีทั้งภาพและตัวอักษรในปุ่มเดียวกันก็ได้

Android Button รูปจาก developer.android.com

วิธีการสร้างปุ่ม Button ด้วย XML

การสร้างปุ่ม Button โดยใช้ไฟล์ xml มีโครงสร้างดังนี้

การสร้าง Button เฉพาะตัวอักษร ด้วยคลาส Button

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This is Button" />

การสร้าง Button ด้วยรูปภาพ โดยใช้คลาส ImageButton

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher" />

การสร้าง Button โดยใช้ทั้งตัวอักษรและรูปภาพ โดยเพิ่มแท็ก android:drawableLeft ในคลาส Button

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/I'm Button"
    android:drawableLeft="@drawable/ic_launcher" />

วิธีการสร้างปุ่ม Button ด้วย Java

หากเราต้องการสร้าง Button ในไฟล์ Java ก็สามารถทำได้เช่นกัน แต่ว่าแบบนี้ เป็นสร้างคลาสขึ้นมาเฉยๆนะครับ โดยปกติจำเป็นต้องมี Root Layout เช่น LinearLayout หรือ RelativeLayout แล้วถึงทำการ addView() Button ที่เราสร้างถึงจะแสดงครับ ฉะนั้นก็จำเป็นจะต้องมีไฟล์ xml ที่ข้างในมี LinearLayout หรือ RelativeLayout

ส่วนวิธีการสร้างก็ตามนี้

// Button เฉพาะอักษร
Button button = new Button(this);
button.setLayoutParams(new ActionBar.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT));
button.setText("This is Button");

// Button ด้วยรูปภาพ
ImageButton imageButton = new ImageButton(this);
imageButton.setLayoutParams(new ActionBar.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT));
imageButton.setImageResource(R.drawable.ic_launcher);

// Button ทั้งรูปและตัวอักษร
Button button2 = new Button(this);
button2.setLayoutParams(new ActionBar.LayoutParams(
        ViewGroup.LayoutParams.WRAP_CONTENT,
        ViewGroup.LayoutParams.WRAP_CONTENT));
button2.setText("I'm Button");
button2.setCompoundDrawables(getResources().
        getDrawable(R.drawable.ic_launcher), null, null, null);

Button และการ onClick

สำหรับวิธีการรับค่าจากผู้ใช้ เราจะใช้การรับ event แบบ onClick ซึ่งวิธีการรับ event นั้นทำได้หลายแบบครับ แบบหลักๆเลย คือ

  1. การรับ event ด้วยการใช้ attribute ของ Botton ชื่อว่า android:onClick
  2. ใช้ OnClickListener (การใช้แบบนี้ก็แบ่งเป็นย่อยๆได้อีก แล้วแต่ความสะดวกหรือจุดประสงค์ของงานนั้นๆ)

ตัวอย่างการใช้ Button

มาลองดูตัวอย่างการใช้งาน Button กันครับ ทดลองสร้างโปรเจ็คใหม่เลย เมื่อได้โปรเจ็คใหม่แล้ว ในที่นี้ผมจะอ้างอิง 2 ไฟล์คือ

  • MainActivity.java สำหรับเขียนโค๊ดต่างๆ
  • activity_main.xml สำหรับแสดง Layout

จุดประสงค์หลักของตัวอย่างนี้คือ ต้องการโชว์ตัวอย่างการรับ Event จาก Button วิธีมี 4 วิธี ดังนั้น ผมจะสร้างปุ่ม Button ทั้งหมด 4 ปุ่ม และตั้งชื่อเป็น button1 ถึง button4 (จริงๆ อันนี้เป็นตัวอย่างการตั้งชื่อที่ไม่ดีนะครับ ชื่อควรตั้งให้สื่อความหมายนะครับ) เลเอาท์จะได้ดังนี้

Button Layout

โค๊ด activity_main.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:text="Button1"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button2"
        android:layout_below="@+id/button1"
        android:layout_marginTop="32dp"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button3"
        android:layout_below="@+id/button2"
        android:layout_marginTop="32dp"/>

    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button4"
        android:layout_below="@+id/button3"
        android:layout_marginTop="32dp"/>

</RelativeLayout>

วิธีที่ 1: android:onClick

วิธีแรก ใช้การกำหนด attribute ฉะนั้น button1 ให้ทำการเพิ่ม android:onClick เข้าไปด้วย จะได้เป็นแบบนี้

<Button
    android:id="@+id/button1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:onClick="showMessage"
    android:text="Button1"/>

showMessage นั้นคือชื่อเมธอด ที่เราจะต้องไปกำหนดในคลาส ฉะนั้นเปิดคลาส MainActivity แล้วก็ประกาศเมธอดขึ้นมาใหม่ โดยให้ชื่อเดียวกัน จะได้ดังนี้

public void showMessage(View view) {
    Toast.makeText(this, "Button1 Clicked!", Toast.LENGTH_SHORT).show();
}

โดยเงื่อนไขการสร้างเมธอดแบบนี้คือ ต้องเป็น public ต้อง return void และสุดท้ายต้องรับ parameter เป็น View (มันก็คือ View นั้นๆที่ถูกคลิ๊ก ซึ่ง Button มันก็คือ View ตัวหนึ่งใน Android นั่นเอง)

เมื่อสั่งรันโปรแกรม หากกดที่ปุ่ม Button1 ก็จะโชว์ข้อความว่า “Button1 Clicked!”

วิธีที่ 2: Implements View.OnClickListener

ตัวอย่างวิธีที่สอง จะใช้ Button2 วิธีนี้จะใช้การ implements View.OnClickListener ฉะนั้นตรงส่วน xml ก็ไม่มีการเปลี่ยนแปลง จะแก้ไขเฉพาะในไฟล์ MainActivity

ที่คลาส MainActivity ทำการ implements View.OnClickListener จากนั้นก็ทำการ override เมธอด onClick ดังนี้ (ViewOnClickListener อยู่ใน android.view.View)

public class MainActivity extends ActionBarActivity implements View.OnClickListener {

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

    }

    public void showMessage(View view) {
        Toast.makeText(this, "Button1 Clicked!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        Toast.makeText(this, "Button2 Clicked!", Toast.LENGTH_SHORT).show();
    }
}

จากนั้นเราจำเป็นที่จะต้องทำการสร้าง Button โดยเชื่อมกับ button2 ใน xml จากนั้นก็เรียกเมธอด setOnClickListener ดังนี้

Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(this);

setOnClickListener(this) : this นั้นหมายถึง View.OnClickListener ที่ได้ implements มา ไม่ใช่ Activity หรือ Context นะครับ ฉะนั้นอย่าสับสน

วิธีที่ 3: Annonymous Inner Class

ตัวอย่างวิธีที่สาม จะใช้ Button3 จริงๆ มันก็คือการ setOnClickListener แบบตัวอย่างที่ 2 แต่ต่างกันแค่ ไม่ได้ implements View.OnClickListener แต่เป็นการส่งสร้าง inner class ส่งไปแทนที่ this ดังตัวอย่างนี้

Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(getApplicationContext(),
                "Button3 Clicked!", Toast.LENGTH_SHORT).show();
    }
});

จุดสังเกต จากที่เราต้อง implements ตรงคลาสเลย เราก็มาทำการสร้าง new Interface แทน เป็นแบบ Anonymous คือไม่มีชื่อ

วิธีที่ 4 : ตั้งชื่อ View.OnClickListener

ตัวอย่างวิธีที่สี่ จะใช้ Button4 ส่วนการทำงาน ก็เหมือนกับวิธีที่ 2 และ 3 เลย ต่างกันแค่วิธีส่งเจ้า View.OnClickListener นั้นเอง สำหรับวิธีนี้ คือการตั้งชื่อให้มันเลย ฉะนั้น ก็ทำการสร้าง interface ชื่อว่า Button4OnClick แบบนี้

View.OnClickListener Button4OnClick = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(getApplicationContext(), 
                "Button4 Clicked!", Toast.LENGTH_SHORT).show();
    }
};

ส่วนปุ่ม Button4 ก็ setOnClickListener โดยใช้ Button4OnClick แบบนี้

Button button4 = (Button) findViewById(R.id.button4);
button4.setOnClickListener(Button4OnClick);

ลองรันโปรแกรม ทดสอบดูแต่ละปุ่มครับ สำหรับโค๊ดทั้งหมด ดูได้ที่ gist นี้ครับ

Chai

Chai Phonbopit : Developer แห่งหนึ่ง • ผู้ชายธรรมดาๆ ที่ชื่นชอบ Node.js, JavaScript และ Open Source มีงานอดิเรกเป็น Acoustic Guitar และ Football

บทความล่าสุด