Lập trình Android – Bài 7: Toast, CheckBox, RadioButton, Dialog

Trong bài này mình sẽ hướng dẫn các bạn thực hiện thao tác với một số đối tượng cơ bản khác trong Android. Để làm bài này có hứng thú và không quá đơn điệu, mình sẽ hướng dẫn các bạn làm một ứng dụng đăng ký học tại OTVINA Study với những nội dung cơ bản như hình sau:

[qads]

android-register-form

Nguyên lý sơ qua là thế này. Khi các bạn điền thông tin đầy đủ, chúng ta lấy toàn bộ thông tin và kiểm tra. Nếu lỗi ở đâu đó thì thông báo (bằng Toast) và bắt nhập lại. Nếu mọi thứ đều ổn thì hiển thị Dialog thông báo thành công! Giờ thì bắt đầu nào.

Trước tiên chúng ta thiết kế giao diện đã. Với giao diện không quá phức tạp và hầu như chỉ có 1 chiều (chiều dọc) thế này thì chúng ta nên chọn LinearLayout là hợp lý và dễ dàng xử lý nhất.
Ah trong này mình cũng muốn giới thiệu tới các bạn những đối tượng mới nhất tại thời điểm này nên chúng ta sẽ thêm một số thư viện nhé. Các bạn mở file build.gradle và thêm các thư viện ở dependencies

android-build-gradle

    compile 'com.android.support:design:24.0.0'
    compile 'com.wdullaer:materialdatetimepicker:2.3.0'

Thư viện thứ nhất là thư viện Android tạo ra nhằm làm đẹp một số View, trong này chúng ta dùng là EditText, Button.
Thư viện thứ 2 là thư viện do bên thứ 3 cung cấp giao diện chọn ngày tháng cho đẹp

Sau đó sẽ có 1 thông báo vàng vàng bên trên để báo cho bạn biết cần đồng bộ và cập nhật lại project. Các bạn click Sync Now

android-sync-project

Bây giờ mở file activity_main.xml ra và bắt đầu code

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="8dp">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:src="@drawable/logo" />

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/editName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/name" />
        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/editPhone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/phone"
                android:inputType="phone" />
        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/editEmail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/email"
                android:inputType="textEmailAddress" />
        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/editAddress"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/address" />
        </android.support.design.widget.TextInputLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <android.support.v7.widget.AppCompatButton
                android:id="@+id/btnBirthDay"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/birthday" />

            <RadioGroup
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="horizontal">

                <RadioButton
                    android:id="@+id/radMale"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:checked="true"
                    android:text="@string/male" />

                <RadioButton
                    android:id="@+id/radFeMale"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="@string/female" />
            </RadioGroup>
        </LinearLayout>

        <EditText
            android:id="@+id/editGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/group" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/course" />

        <CheckBox
            android:id="@+id/cbAndroid"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/android" />

        <CheckBox
            android:id="@+id/cbWeb"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/web" />

        <CheckBox
            android:id="@+id/cbIC3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/ic3" />

        <android.support.v7.widget.AppCompatButton
            android:id="@+id/btnOk"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/ok" />
    </LinearLayout>
</ScrollView>

android-register-form-pre

Trong code trên các bạn để ý một số điểm sau:

  • Do chúng ta có khá nhiều nội dung trong giao diện này nên với một số màn hình nhỏ sẽ không hiển thị hết các trường dữ liệu, vì vậy chúng ta dùng ScrollView, nó cho phép chúng ta kéo lên xuống giao diện được bao trong nó (ở đây là toàn bộ màn hình).
  • Đối tượng ImageView cho phép hiển thị một hình ảnh. Ở đây là ảnh logo.png, các bạn có thể download logo.png tại đây và cho vào thư mục /res/drawable.
  • android.support.design.widget.TextInputLayout kết hợp với EditText sẽ cho phép chúng ta tạo một hiệu ứng đẹp khi click vào EditText để nhập dữ liệu.
  • Trong các EditText thì có một số có thuộc tính android:inputType, nó giúp cho bàn phím hiện lên đúng kiểu. Ví dụ kiểu phone thì khi click vào EditText đó, bàn phím hiện lên gồm bàn phím số và các ký tự giống lúc bạn gọi điện.
  • RadioButton là đối tượng hình tròn, thường dùng để chọn một trong các lựa chọn, vì vậy chúng cần được nhóm vào bởi RadioGroup nếu không bạn có thể chọn nhiều lựa chọn cùng một lúc như CheckBox.
  • AppCompatButton là đối tượng kế thừa từ Button và có hiệu ứng đẹp hơn
  • Toàn bộ text trong các đối tượng mình đều lấy từ @string/abc tức là lấy từ file /res/values/string.xml. Chúng ta để các text trong này nhằm mục đích có thể dùng lại khi code bằng java (tức là chúng ta có thể gọi từ xml hoặc java) hoặc dùng trong đa ngôn ngữ sau này.

File /res/values/string.xml như sau:

<resources>
    <string name="app_name">TUT7CheckBoxRaidoToast</string>

    <string name="name">Họ và tên(*)</string>
    <string name="phone">Điện thoại(*)</string>
    <string name="email">Email(*)</string>
    <string name="address">Địa chỉ(*)</string>
    <string name="birthday">Ngày sinh</string>
    <string name="male">Nam</string>
    <string name="female">Nữ</string>
    <string name="group">Nhóm với ai (nếu có)</string>
    <string name="course">Khóa học</string>
    <string name="android">Android</string>
    <string name="web">Web</string>
    <string name="ic3">IC3</string>

    <string name="ok">Xong</string>
    <string name="cancel">Hủy</string>

    <string name="please_enter_name">Bạn chưa nhập tên</string>
    <string name="please_enter_phone">Bạn chưa nhập điện thoại</string>
    <string name="please_enter_email">Bạn chưa nhập email</string>
    <string name="please_enter_address">Bạn chưa nhập địa chỉ</string>
    <string name="please_enter_birthday">Bạn chưa chọn ngày sinh</string>
    <string name="please_enter_course">Bạn chưa chọn khóa học</string>

    <string name="success">Thành công</string>
    <string name="notify_thanks">Cảm ơn bạn đã đăng ký khóa học {0}.\nChúng tôi sẽ gửi đến bạn những thông tin mới nhất sắp tới</string>

</resources>

Copy file logo.png vào /res/drawable
android-register-form-add-logo

Vậy là xong. Giờ chuyển sang code java thôi.

package com.nguyenvanquan7826.tut7checkboxraidotoast;

import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatButton;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Toast;

import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Context context;

    private EditText editName;
    private EditText editPhone;
    private EditText editEmail;
    private EditText editAddress;
    private EditText editGroup;

    private AppCompatButton btnBirthDay;

    private RadioButton radMale;
    private RadioButton radFemale;

    private CheckBox cbAndroid;
    private CheckBox cbWeb;
    private CheckBox cbIC3;

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

        context = this;

        connectView();
    }

    private void connectView() {
        editName = (EditText) findViewById(R.id.editName);
        editPhone = (EditText) findViewById(R.id.editPhone);
        editEmail = (EditText) findViewById(R.id.editEmail);
        editAddress = (EditText) findViewById(R.id.editAddress);
        editGroup = (EditText) findViewById(R.id.editGroup);

        btnBirthDay = (AppCompatButton) findViewById(R.id.btnBirthDay);
        btnBirthDay.setOnClickListener(this);
        findViewById(R.id.btnOk).setOnClickListener(this);

        radMale = (RadioButton) findViewById(R.id.radMale);
        radFemale = (RadioButton) findViewById(R.id.radFeMale);

        cbAndroid = (CheckBox) findViewById(R.id.cbAndroid);
        cbWeb = (CheckBox) findViewById(R.id.cbWeb);
        cbIC3 = (CheckBox) findViewById(R.id.cbIC3);
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        switch (id) {
            case R.id.btnBirthDay:
                selectBirthDay();
                break;
            case R.id.btnOk:
                ok();
                break;
        }
    }

    private void selectBirthDay() {
        int defaultYear = 1990;
        int defaultMonth = 0;
        int defaultDate = 1;
        // create and setting Datapicker
        DatePickerDialog dpd = DatePickerDialog.newInstance(
                new DatePickerDialog.OnDateSetListener() {
                    @Override
                    public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {

                        Calendar calendar = Calendar.getInstance();
                        // set select date for calendar
                        calendar.set(year, monthOfYear, dayOfMonth);

                        // config string format to show date
                        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

                        // set date for button birthday
                        btnBirthDay.setText(sdf.format(calendar.getTime()));
                    }
                },
                defaultYear,
                defaultMonth,
                defaultDate
        );
        dpd.setOkText(context.getResources().getString(R.string.ok));
        dpd.setCancelText(context.getResources().getString(R.string.cancel));

        // show datepicker
        dpd.show(getFragmentManager(), "DatePickerDialog");
    }

    private void ok() {
        // get data
        String name = editName.getText().toString().trim();
        String phone = editPhone.getText().toString().trim();
        String email = editEmail.getText().toString().trim();
        String address = editAddress.getText().toString().trim();
        String group = editGroup.getText().toString().trim();

        String birthDay = btnBirthDay.getText().toString().trim();
        String sex = radMale.isChecked() ? getString(context, R.string.male) : getString(R.string.female);
        String course = "";
        if (cbAndroid.isChecked()) {
            if (course.length() > 0) {
                course += ", ";
            }
            course += getString(R.string.android);
        }
        if (cbWeb.isChecked()) {
            if (course.length() > 0) {
                course += ", ";
            }
            course += getString(R.string.web);
        }
        if (cbIC3.isChecked()) {
            if (course.length() > 0) {
                course += ", ";
            }
            course += getString(R.string.ic3);
        }


        // check data
        if (TextUtils.isEmpty(name)) {
            editName.requestFocus();
            Toast.makeText(context, getString(R.string.please_enter_name), Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(phone)) {
            editPhone.requestFocus();
            Toast.makeText(context, getString(R.string.please_enter_phone), Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(email)) {
            editEmail.requestFocus();
            Toast.makeText(context, getString(R.string.please_enter_email), Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(address)) {
            editAddress.requestFocus();
            Toast.makeText(context, getString(R.string.please_enter_address), Toast.LENGTH_SHORT).show();
            return;
        }

        if (birthDay.equals(getString(R.string.birthday))) {
            Toast.makeText(context, getString(R.string.please_enter_birthday), Toast.LENGTH_SHORT).show();
            return;
        }

        if (TextUtils.isEmpty(course)) {
            Toast.makeText(context, getString(R.string.please_enter_course), Toast.LENGTH_SHORT).show();
            return;
        }

        // if all is ok, we process data and show dialog to notify

        String notifyThanks = getString(context, R.string.notify_thanks);
        notifyThanks = completeString(notifyThanks, new String[]{course});

        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle(R.string.success)
                .setMessage(notifyThanks)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // do something
                    }
                })
                .create()
                .show();
    }

    public static String getString(Context context, int id) {
        return context.getResources().getString(id);
    }

    public static String completeString(String source, String[] item) {
        for (int i = 0; i < item.length; i++) {
            source = source.replace("{" + i + "}", item[i]);
        }
        return source;
    }
}

Trong code trên, các bạn thấy có 1 bến Context, hãy hiểu nó là 1 biến ngữ cảnh. Mọi hành động xảy ra đều cần một ngữ cảnh nhất định. Ví dụ, để hiển thị 1 Toast (một thông báo nhanh) thì cũng cần đến ngữ cảnh (context). Trong nhiều bài hướng dẫn các, các bạn có thể thấy họ viết là this hoặc MainActivity.this, thì chúng đều được cả vì ở đây mình đã gán context = this rồi.
Tuy code có nhiều điểm mới lạ nhưng mình đã chú thích và cũng khá dễ đọc, các bạn đọc và sẽ hiểu code rất nhanh thôi!

Kết quả:

android-register-form-ok