Lập trình Android – Bài 3: Bắt sự kiện click Button

Ngày trước khi mình học Android thì cũng rất chi là sốt ruột trong việc muốn biết làm sao để click Button mà TextView thay đổi chữ. Vì vậy bài này chúng ta sẽ tìm hiểu cách bắt sự kiện Button để thao tác với TextView và EditText. Chúng ta sẽ làm tiếp ở Project của bài 2 và nhiệm vụ là làm sao để khi click Button thì TextView hiển thị được dòng chữ mà chúng ta đã nhập ở EditText.

[qads]

Chúng ta xem lại giao diện hôm trước một chút như sau:
text-edit-button

Để có thể thao tác được với Button cũng như EditText và TextView thì chúng ta phải kết nối các phần tử này tới code java để code java thao tác được với chúng. Để kết nối được với java, mỗi phần tử này cần có 1 id. Các bạn có thể hiểu id là một mã số định danh cho mỗi phần tử. Chúng ta đặt id cho các phần tử ví dụ như với TextView như sau android:id=”@+id/tv”. Theo đó tv chính là định danh của TextView đó. Sau này các bạn nên đặt là tvName, tvPhone,… tv là viết tắt của TextView, Name là tên, Phone là điện thoại, tức là TextView để hiển thị tên và TextView để hiển thị điện thoại. Như vậy code giao diện của chúng ta sẽ như sau:

<?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.nguyenvanquan7826.tut2texteditbutton.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter text here" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click me" />

</LinearLayout>

Sau khi đã đặt được id của các thành phần, các bạn quay lại file MainActivity.java để bắt đầu thực hiện code.
Vì bài này chúng ta mới là bài đầu tiên động chạm đến code java nên mình giới thiệu qua một chút. Hiện tại code java của chúng ta như sau:

package com.nguyenvanquan7826.tut2texteditbutton;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

Không giống như trong Java đơn thuần mà các bạn đã học trước đó. Chúng ta sẽ không có hàm main để bắt đầu chương trình mà mỗi Activity sẽ bắt đầu khởi chạy bằng hàm onCreate. Tại đây:

  • super.onCreate(savedInstanceState); là lệnh gọi hàm onCreate của AppCompatActivity mà hiện tại đang kế thừa.
  • setContentView(R.layout.activity_main); là lệnh đặt giao diện của chúng ta là file activity_main.xml – chính là file xml chúng ta đã thao tác từ đầu tới giờ. Nếu các bạn tạo 1 file xml khác trong /res/layout thì chúng ta hoàn toàn có thể đặt nó làm giao diện cho Acitivity này bằng lệnh setContentView.

Bây giờ chúng ta bắt đầu vào phần chính là kết nối và xử lý giao diện. Để kết nối giao diện, chúng ta sẽ khai báo các biến có kiểu tương ứng với Button, EditText và TextView. Các bạn xem code sau:

package com.nguyenvanquan7826.tut2texteditbutton;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    /*
    * khai bao cac bien view
    * */
    private TextView tv;
    private EditText edit;
    private Button btn;

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

        // goi ham ket noi view
        connectView();
    }
    /*
    * ket noi cac thanh phan view
    * */
    private void connectView() {
        tv = (TextView) findViewById(R.id.tv);
        edit = (EditText) findViewById(R.id.edit);
        btn = (Button) findViewById(R.id.btn);
    }
}

Sau khi kháo báo các biến tương ứng mà chúng ta cần thao tác tại dòng 14, 15, 16, chúng ta gọi hàm connectView trong hàm onCreate. Hàm connectView là hàm mà chúng ta tự viết để kết nối tới giao diện. Để kết nối các phần tử chúng ta dùng hàm findViewById đối truyền vào là R.id.xyz trong đó xyz là id mà chúng ta đã đặt cho các phần tử ở trong file xml. Tuy nhiên hàm này sẽ trả về kiểu View (View là kiểu cha của tất cả các thành phần, tức là TextView, EditText, Button,… đều kế thừa từ View) nên chúng ta cần ép kiểu về kiểu chính xác của mỗi phần tử như trên.

Vậy là việc kết nối tới giao diện đã xong. Giờ chúng ta bắt đầu thực hiện việc bắt sự kiện cho Button bằng cách gọi hàm setOnClickListener. Chúng ta có nhiều cách bắt sự kiện, tuy nhiên tôi chỉ hướng dẫn các bạn 2 cách phổ biến nhất mà tôi cũng như mọi người thường xuyên sử dụng.

Cách 1: Bắt ngay tại trận

/*
* ket noi cac thanh phan view
* */
private void connectView() {
    tv = (TextView) findViewById(R.id.tv);
    edit = (EditText) findViewById(R.id.edit);
    btn = (Button) findViewById(R.id.btn);

    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            doClickButton();
        }
    });
}

private void doClickButton() {
    String text = edit.getText().toString().trim();
    tv.setText(text);
    edit.setText("");
}

Các bạn viết btn.setOnClickListener và viết tiếp trong ngoặc tròn là new OnC thì hộp thoại gợi ý sẽ hiện ra và bạn chọn cái đầu tiên là View.OnClickListener nó là 1 interface nên sẽ tự động sinh ra code của hàm onClick cho bạn.
setOnClickListener-button

Tức là khi bạn click vào Button thì hệ thống sẽ gọi hàm onClick, giờ ta chỉ việc là gì chúng ta muôn, mà tại đây là lấy text ở EditText ra đặt lên TextView. Chúng ta viết hàm doClickButton và gọi nó trong onClick. Trong hàm doClickButton, chúng ta thấy có 3 dòng.

  • Dòng đầu tiên chính là lấy text của EditText ra gán cho biến String text (hàm toString là biến cái chúng ta lấy ra thành chuỗi, hàm trim là để xóa ký tự trắng ở đầu và cuối nếu có). Như vậy chúng ta lấy text của EditText bằng hàm getText();
  • Dòng thứ hai là đặt text chúng ta đã lấy được vào TextView bằng hàm setText(text)
  • Dòng thứ ba, chúng ta xóa text trong EditText.

Bây giờ các bạn chạy và hưởng thành quả thôi.
event-click-button

Cách 2: Bắt cho nhiều Button cùng lúc

Nếu các bạn để ý, thì với cách 1, mỗi button chúng ta sẽ có 1 đoạn bắt sự kiện riêng cho nó. Như vậy trong trường hợp nhiều Button (Như VD làm các máy tính cầm tay) thì code sẽ rất dài dòng và bất tiện. Vì vậy cách 2 sẽ phù hợp cho những trường hợp như thế. Các bạn sửa lại code của cách băt sự kiện như sau.

/*
* ket noi cac thanh phan view
* */
private void connectView() {
    tv = (TextView) findViewById(R.id.tv);
    edit = (EditText) findViewById(R.id.edit);
    btn = (Button) findViewById(R.id.btn);

    btn.setOnClickListener(this);
}

Tức là chúng ta không tạo new OnClickListener nữa mà truyền vào là this cho hàm setOnClickListener. Tuy nhiên hiện tại các bạn sẽ thấy lỗi. Hãy đưa con trỏ chuột vào chữ this, chỗ mà bị lỗi ấy, rồi ấn Alt + Enter các bạn sẽ thấy hộp thoại gợi ý hiện ra:
implement-onlick-button

Các bạn chọn cái dòng thứ 2 là Make MainAcitvity implement View.OnClickListener, hộp thoại sau hiện ra, các bạn chọn Ok.
implement-method-onclick

Đợi chút hệ thống sẽ thực hiện sinh code và bạn sẽ thấy hàm onClick tự sinh ra và ở ngang hàng với hàm onCreate, bên trên dòng class thì có thêm implements View.OnClickListener. Ở đây chúng ta hiểu là toàn bộ class MainAcitivty là một interface View.OnClickListener nên nó có hàm onClick để thực thi việc bắt sự kiện cho toàn bộ button (hoặc view nào đó) có gọi setOnClickListener(this); Do vậy chúng ta có thể bắt sự kiện cho rất nhiều button cùng lúc. Để phân biệt được chúng ta click vào button nào thì ở hàm onClick có 1 biến View, nó chính là cái để chúng ta phân biệt. Giả sử chúng ta thêm 1 button nữa vào giao diện để xóa text trong EditText thì code của chúng ta sẽ như sau:

Code giao diện

<?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.nguyenvanquan7826.tut2texteditbutton.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter text here" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click me" />

    <Button
        android:id="@+id/btnClear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Clear" />

</LinearLayout>

Code Java.

package com.nguyenvanquan7826.tut2texteditbutton;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    /*
    * khai bao cac bien view
    * */
    private TextView tv;
    private EditText edit;
    private Button btn;
    private Button btnClear;

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

        // goi ham ket noi view
        connectView();
    }

    /*
    * ket noi cac thanh phan view
    * */
    private void connectView() {
        tv = (TextView) findViewById(R.id.tv);
        edit = (EditText) findViewById(R.id.edit);
        btn = (Button) findViewById(R.id.btn);
        btnClear = (Button) findViewById(R.id.btnClear);

        // set on click
        btn.setOnClickListener(this);
        btnClear.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn:
                doClickButton();
                break;
            case R.id.btnClear:
                doClickButtonClear();
                break;
        }
    }

    private void doClickButton() {
        String text = edit.getText().toString().trim();
        tv.setText(text);
        edit.setText("");
    }

    private void doClickButtonClear() {
        edit.setText("");
    }

}

Hôm nay chúng ta dừng lại tại đây. Rất mong các bạn có thể hiểu và thực hành tốt việc bắt sự kiện cho button cũng như việc thao tác đặt text, lấy text từ TextView và EditText.