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]
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
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
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>
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
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ả:
day la loi j` a Error:Execution failed for task ‘:app:processDebugManifest’.
> Manifest merger failed : uses-sdk:minSdkVersion 9 cannot be smaller than version 14 declared in library [com.wdullaer:materialdatetimepicker:2.3.0] G:\Bai7NVQ\app\build\intermediates\exploded-aar\com.wdullaer\materialdatetimepicker\2.3.0\AndroidManifest.xml
Suggestion: use tools:overrideLibrary=”com.wdullaer.materialdatetimepicker” to force usage
Cấu hình phiên bản của bạn không hợp lý. Bạn tạo project và chọn minSDK là 14 nhé, là cho android 4 trở lên đó
qua hay
anh oi minh` muon lay day or mon or year ra thi` lam the nao` a, em khong muon lay het ca chuoi String VD 01/12/2000 chi muon lay 01
Trong cái hàm lấy dữ liệu ngày tháng năm, họ trả về từng cái đó, year, dayofmonth, hourofday.
e đặt L o g sau dong btnBirthDay.setText(sdf.format(calendar.getTime())); thì tháng toàn bị sai 1 đơn vị , còn năm và ngày thì đúng. không hiểu tại sao khi show lên button lại đúng đc nhỉ
Trong java tháng được tính từ 0-11 nhé. Show lên đúng vì chúng ta đã có format chuẩn rồi nên vậy đó.
thaks anh
cho mình hỏi đoạn context = this, trong trường hợp này this đại diện cho đối tượng nào
Nó chính là Activiy hiện tại nhé.
Error:(1, 0) Gradle DSL method not found: ‘compile()’
Possible causes:The project ‘checkAndRadio’ may be using a version of the Android Gradle plug-in that does not contain the method (e.g. ‘testCompile’ was added in 1.1.0).
Upgrade plugin to version 2.3.3 and sync projectThe project ‘checkAndRadio’ may be using a version of Gradle that does not contain the method.
Open Gradle wrapper fileThe build file may be missing a Gradle plugin.
Apply Gradle plugin
lỗi gì v a
Chắc cái phiên bản android studio của bạn khác nên nó báo trong cái build.grade. Nó bảo update để khắc phục đó.
Phần Code java ở trên anh chưa khai báo Button Ok hả anh
Không cần nhé.