You are on page 1of 58

TRƯỜNG ĐẠI HỌC NAM CẦN THƠ

LẬP TRÌNH
THIẾT BỊ DI ĐỘNG
(GIÁO TRÌNH THỰC HÀNH)

Mai Yến Trinh

Vĩnh Long, 2022


GIỚI THIỆU CHUNG VỀ MÔN HỌC
1. Giới thiệu sơ lược nội dung môn học
Sau khi học xong môn học, sinh viên có khả năng:
 Sử dụng thành thạo các view cơ bản, nâng cao trong Android Studio.
 Thiết kế giao diện và xử lý sự kiện cơ bản của một số view phổ biến.
 Xây dựng ứng trên môi trường Android Studio.
2. Giới thiệu ngôn ngữ và môi trường lập trình
 Ngôn ngữ lập trình: Java, XML.
 Môi trường lập trình: Android Studio.
3. Hình thức đánh giá
 Kiểm tra hoặc làm đồ án môn học.
 Điểm cộng: dành cho sinh viên làm tốt những bài tập nâng cao theo yêu cầu ngay tại
buổi học.
 Điểm trừ: vắng, đi trễ, mất trật tự, …
4. Tài liệu tham khảo
[1] Lê Hoàng Sơn, Giáo trình lập trình Android, NXB Xây dựng, 2015.
[2] Trương Thị Ngọc Phượng, Giáo trình lập trình Android, NXB Thời đại, 2014.
[3] Android Developers, Google, https://developer.android.com, ngày truy cập
7/7/2022.

1
MỤC LỤC
PHẦN 1. CÁC VIEW CƠ BẢN ..............................................................................................3
1.1. Mục tiêu thực hành ........................................................................................................3
1.2. Kỹ năng đạt được ..........................................................................................................3
1.3. Nội dung thực hành .......................................................................................................3
Bài 1. Thiết kế giao diện ứng dụng Đăng nhập............................................................3
Bài 2. Thiết kế giao diện ứng dụng thực hiện 4 phép toán cơ bản tổng, hiệu, tích,
thương...........................................................................................................................5
Bài 3. Thiết kế giao diện quản lý Thông tin cá nhân .................................................12
Bài 4. Thiết kế giao diện Cập nhật thông tin cá nhân. ...............................................21
Bài 5. Thiết kế giao diện ứng dụng Giải phương trình bậc hai ..................................22
PHẦN 2. CÁC ĐIỀU KHIỂN NÂNG CAO ..........................................................................23
2.1. Mục tiêu thực hành ......................................................................................................23
2.2. Kỹ năng đạt được ........................................................................................................23
2.3. Nội dung thực hành .....................................................................................................23
Bài 1. Thiết kế giao diện ứng dụng Quản lý Nhân viên .............................................23
Bài 2. Thiết kế giao diện Đăng nhập hệ thống ...........................................................33
Bài 3. Viết chương trình Quản lý Sản Phẩm ..............................................................38
Bài 4. Cài đặt ứng dụng Ghi chú Công việc ..............................................................45

2
PHẦN 1. CÁC VIEW CƠ BẢN
1.1. Mục tiêu thực hành
 Cung cấp kiến thức cơ bản về XML.
 Hướng dẫn tạo ứng dụng trong Android Studio.
 Giới thiệu và hướng dẫn cài đặt một số view cơ bản.
1.2. Kỹ năng đạt được
 Biết cách tạo một dự án Android Studio.
 Biết cách thiết kế giao diện ứng dụng bằng XML.
 Cài đặt được một số chương trình đơn giản.
1.3. Nội dung thực hành
Bài 1. Thiết kế giao diện ứng dụng Đăng nhập

Hình 1-1: Giao diện Đăng nhập

Mục tiêu: giới thiệu các view TableLayout, LinearLayout, TextView, EditText, Button.
Hướng dẫn:
Bước 1: Tạo dự án mới và đặt tên DangNhap.
Bước 2: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
Chiều rộng của view bằng view
layout_height "match_parent"
cha.
Chiều cao của view bằng view
layout_width "match_parent"
1 TableLayout cha.
background "#E1F2FA" Màu nền xanh của view
Độ rộng cột 1 dãn ra lớn nhất có
stretchColumns "1"
thể.
2 TableRow Tạo dòng trong TableLayout
3 TextView text "ĐĂNG NHẬP" Chuỗi văn bản hiển thị

3
(ĐĂNG layout_span "2" Trộn 2 ô liền nhau thành một
NHẬP) textStyle "bold" Kiểu chữ
textSize "20sp" Cỡ chữ
Vị trí của chuỗi văn bản trong
gravity "center"
TextView.

layout_marginTop "10dp" Khoảng cách cạnh trên của


TextView so với view cha
"Tài khoản","Mật
text Chuỗi văn bản hiển thị
TextView khẩu"
4 (Tài khoản, textStyle "bold" Kiểu chữ
Mật khẩu) Khoảng cách cạnh trái của
Layout_marginLeft "10dp"
TextView so với view cha
EditText id "@+id/edtTaiKhoan" Tên biến đại diện của view
5
(Tài khoản) inputType "text" Kiểu nhập liệu dạng chuỗi.
EditText id "@+id/edtMatKhau" Tên biến đại diện của view
6
(Mật khẩu) inputType "textPassword" Kiểu nhập liệu dạng Password
orientation "horizontal" Các view con được xếp theo
chiều ngang.
7 LinearLayout
gravity "center" Vị trí của các view con trong
TextView
"@+id/btnOK"
id Tên biến đại diện của view
"@+id/btnCancel"
Button
8 layout_width "wrap_content" Chiều rộng của view
(OK, Cancel)
layout_height "wrap_content" Chiều cao của view
text "OK", "Cancel" Chuỗi văn bản hiển thị
Bước 3: Code thiết kế giao diện
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="1"
android:background="#E1F2FA"
xmlns:android="http://schemas.android.com/apk/res/android" >

<!-- Dòng 1 -->


<TableRow>
<TextView
android:text="ĐĂNG NHẬP"
android:textSize="20dp"
android:textStyle="bold"
android:layout_span="2"
android:gravity="center"
android:layout_marginTop="10dp"/>
</TableRow>

<!-- Dòng 2 -->


<TableRow>
4
<TextView
android:text="Tài khoản:"
android:textStyle="bold"
android:layout_marginLeft="10dp"/>
<EditText
android:id="@+id/edtTaiKhoan"
android:inputType="text"/>
</TableRow>

<!-- Dòng 3 -->


<TableRow>
<TextView
android:text="Mật khẩu:"
android:textStyle="bold"
android:layout_marginLeft="10dp"/>
<EditText
android:id="@+id/edtMatKhau"
android:inputType="textPassword"/>
</TableRow>

<!--Dòng 4: Tự hiểu là tạo ra 1 TableRow -->


<LinearLayout
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/btnOK"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

android:text="OK"/>
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel"/>
</LinearLayout>
</TableLayout>

Bài 2. Thiết kế giao diện ứng dụng thực hiện 4 phép toán cơ bản tổng, hiệu, tích,
thương

Hình 1-2: Giao diện Phép toán cơ bản


5
Yêu cầu:
- Số a, Số b: cho phép nhập dữ liệu dạng số nguyên có dấu và số thập phân.
- Kết quả: chỉ hiển thị thông tin, không cho phép chỉnh sửa.
- Viết sự kiện cho 4 nút +, -, x, ÷
Mục tiêu: giới thiệu TextInputLayout, TextInputEditText, style và các phép toán cơ bản.
Hướng dẫn:
Bước 1: Tạo dự án mới và đặt tên PhepTinh.
Bước 2: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
layout_height "match_parent" Chiều rộng của view
layout_width "match_parent" Chiều cao của view
orientation "vertical" Các view con được xếp
1 LinearLayout theo chiều dọc.
Khoảng cách các cạnh
layout_margin "10dp" của view so với view
cha.
layout_width "match_parent" Chiều rộng của view
bằng view cha.
Chiều cao của view
TextInputLayout layout_height "wrap_content" bằng với nội dung
2 (Số a, Số b, Kết view.
quả) textColorHint "#3F51B5" Màu cho Hint
"@style/ThemeOverlay.
style Material3.AutoCompleteTextView. Kiểu dáng
OutlinedBox" cho TextInputLayout

id "@+id/textEditSoA" Tên biến đại diện của


view
layout_width "match_parent" Chiều rộng của view
layout_height "wrap_content" Chiều cao của view
TextInputEditText
hint "Số a:" Gán chuỗi sẽ xuất hiện
3 (Số a, Số b, Kết nếu view rỗng
quả)
Nhập dữ liệu dạng số
inputType "numberSigned|numberDecimal" nguyên có dấu và số
thập phân.
Vô hiệu hóa chỉnh sửa
focusable "false" (Kết quả)
của view Kết quả
layout_width "match_parent" Chiều rộng của view.
layout_height “wrap_content" Chiều cao của view.
4 LinearLayout
orientation "horizontal" Các view con được xếp
theo chiều ngang.

6
gravity "center" Vị trí của các view con
trong view.
"@+id/buttonTong"
"@+id/buttonHieu" Tên biến đại diện của
id "@+id/buttonTich" view.
"@+id/buttonThuong"
layout_width "wrap_content" Chiều rộng của view
layout_height "wrap_content" Chiều cao của view
Button
5 "@drawable/ic_tong"
(+, -, x, /) "@drawable/ic_hieu"
drawableLeft Gán ảnh từ Drawable
"@drawable/ic_tich" vào biên trái của view
"@drawable/ic_thuong"
Khoảng cách của chuỗi
paddingLeft "30dp" văn bản với cạnh trái
của view
Bước 3: Viết code thiết kế giao diện trong file activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Tạo TextInputLayout nhập số a -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#3F51B5"
style="@style/ThemeOverlay.Material3.AutoCompleteTextView.OutlinedBox">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditSoA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Số a:"
android:inputType="numberSigned|numberDecimal"/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Tạo TextInputLayout nhập số b -->


<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#3F51B5"
style="@style/ThemeOverlay.Material3.AutoCompleteTextView.OutlinedBox">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditSoB"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Số b:"
android:inputType="numberSigned|numberDecimal"/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Tạo TextInputLayout hiển thị kết quả -->


<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#3F51B5"
7
style="@style/ThemeOverlay.Material3.AutoCompleteTextView.OutlinedBox">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditKetQua"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Kết quả:"
android:focusable="false"
android:inputType="numberSigned|numberDecimal"/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Tạo Lin chứa các nút tính-->


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/buttonTong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_tong"
android:paddingLeft="35dp"/>
<Button
android:id="@+id/buttonHieu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_hieu"
android:paddingLeft="35dp"/>
<Button
android:id="@+id/buttonTich"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_tich"
android:paddingLeft="35dp"/>
<Button
android:id="@+id/buttonThuong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_thuong"
android:paddingLeft="30dp"/>
</LinearLayout>
</LinearLayout>

Bước 4: Viết code sự kiện cho các nút lệnh


Tập tin MainActivity.java:
- Viết hàm addViews() để truy xuất các view trong activity_main.xml.
public class MainActivity extends AppCompatActivity {
TextInputEditText edtSoA,edtSoB,edtKetQua;
Button btnTong, btnHieu, btnTich, btnThuong;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("Phép Tính"); //Thay đổi tiêu đề Activity
addViews();
}
private void addViews() {
edtSoA = findViewById(R.id.textEditSoA);

8
edtSoB = findViewById(R.id.textEditSoB);
edtKetQua = findViewById(R.id.textEditKetQua);
btnTong = findViewById(R.id.buttonTong);
btnHieu = findViewById(R.id.buttonHieu);
btnTich = findViewById(R.id.buttonTich);
btnThuong = findViewById(R.id.buttonThuong);
}
}

- Viết hàm addEvents() chứa các sự kiện nhấn nút Tổng, Hiệu, Tích, Thương
public class MainActivity extends AppCompatActivity {

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

addEvents();
}

private void addEvents() {


btnTong.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
float soA =
Float.parseFloat(edtSoA.getText().toString());
float soB =
Float.parseFloat(edtSoB.getText().toString());
float tong = soA + soB;

edtKetQua.setText(String.valueOf(tong));
}
});

btnHieu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
float soA =
Float.parseFloat(edtSoA.getText().toString());
float soB =
Float.parseFloat(edtSoB.getText().toString());
float hieu = soA - soB;
edtKetQua.setText(String.valueOf(hieu));
}
});
}
}

- Sinh viên bổ sung thêm code cho sự kiện của nút Tích, Thương.
Bước 5: Kết quả thực hiện chương trình

9
Hình 1-3: Kết quả thực hiện Phép toán

Bước 6: Cải tiến code giao diện. Định nghĩa style chứa các thuộc tính và giá trị của
TextInputLayout, TextInputEditText, Button.
- Trong res/values, định nghĩa style:
+ Chọn new/xml/Values XML File, tạo tập tin styles.xml
+ Trong style.xml, định nghĩa các style có tên style_TextInputLayout
style_TextInputEditText, style_Button.
<resources>
<!-- parent: kế thừa từ 1 style có sẵn -->
<style name="style_TextInputLayout" parent = "@style/ThemeOverlay.
Material3.AutoCompleteTextView.OutlinedBox">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColorHint">#3F51B5</item>
</style>

<style name="style_TextInputEditText">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:inputType">numberSigned|numberDecimal</item>
</style>

<style name="style_Button">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingLeft">35dp</item>
</style>
</resources>

- Cập nhật code thiết kế giao diện trong file activity_main.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Tạo TextInputLayout nhập số a -->
<com.google.android.material.textfield.TextInputLayout
style="@style/style_TextInputLayout">

<com.google.android.material.textfield.TextInputEditText

10
android:id="@+id/textEditSoA"
android:hint="Số a:"
style="@style/style_TextInputEditText"/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Tạo TextInputLayout nhập số b -->


<com.google.android.material.textfield.TextInputLayout
style="@style/style_TextInputLayout">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditSoB"
android:hint="Số b:"
style="@style/style_TextInputEditText"/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Tạo TextInputLayout hiển thị kết quả -->


<com.google.android.material.textfield.TextInputLayout
style="@style/style_TextInputLayout">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditKetQua"
android:hint="Kết quả:"
android:focusable="false"
style="@style/style_TextInputEditText"/>
</com.google.android.material.textfield.TextInputLayout>

<!-- Tạo Lin chứa các nút tính-->


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/buttonTong"
android:drawableLeft="@drawable/ic_tong"
style="@style/style_Button"/>
<Button
android:id="@+id/buttonHieu"
android:drawableLeft="@drawable/ic_hieu"
style="@style/style_Button"/>
<Button
android:id="@+id/buttonTich"
android:drawableLeft="@drawable/ic_tich"
style="@style/style_Button"/>
<Button
android:id="@+id/buttonThuong"
android:drawableLeft="@drawable/ic_thuong"
style="@style/style_Button"/>
</LinearLayout>
</LinearLayout>

11
Bài 3. Thiết kế giao diện quản lý Thông tin cá nhân

Hình 1-4: Giao diện Thông tin cá nhân

Yêu cầu:
- Tên người không để trống.
- Chứng minh nhân dân chỉ được nhập kiểu số và phải có đúng 9 chữ số.
- Bằng cấp mặc định sẽ chọn là Đại học.
- Sở thích phải chọn ít nhất 1 chọn lựa.
- Khi nhấn gửi thông tin, hiển thị toàn bộ thông tin cá nhân lên TextInputEditText.
Mục tiêu: giới thiệu ScrollView, RadioGroup, RadioButton, CheckBox và cách hiển thị
thông báo lỗi trong TextInputLayout.
Hướng dẫn:
Bước 1: Tạo dự án mới và đặt tên QLyThongTinCaNhan.
Bước 2: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

12
Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
layout_height "match_parent" Chiều rộng của view
layout_width "match_parent" Chiều cao của view

orientation "vertical" Các view con được xếp


1 LinearLayout
theo chiều dọc.
Khoảng cách các cạnh
layout_margin "10dp" của view so với view
cha.
layout_width "match_parent" Chiều rộng của view
layout_height "wrap_content" Chiều cao của view
"Thông tin cá nhân"
text "Bằng cấp" Chuỗi văn bản hiển thị
"Sở thích"
TextView textAllCaps "true" (Thông tin cá nhân) Chuyển chữ hoa
(Thông tin cá nhân, textColor "#ffffff"
2 Màu chữ trắng
Bằng cấp, Sở thích)
"25dp" (Thông tin cá nhân)
textSize Cỡ chữ
"18dp" (Bằng cấp, sở thích)
textStyle "bold" Kiểu chữ đậm

gravity "center" Vị trí của chuỗi văn bản


trong view
"#3F51B5" (Thông tin cá nhân)
background Màu nền xanh
"#2196F3"(Bằng cấp, sở thích)
layout_width "match_parent" Chiều rộng của view
3 ScrollView
layout_height "match_parent" Chiều cao của view
"@+id/textLayoutHoTen" Tên biến đại diện của
id
"@+id/textLayoutCMND" view.
layout_width "match_parent" Chiều rộng của view.

layout_height "wrap_content" Chiều cao của view bằng


với nội dung view.
TextInputLayout
4 (Họ tên, CMND) errorEnabled "true" Hiển thị dòng thông báo
lỗi
"@drawable/ic_hoten" Hiển thị biểu tượng bên
startIconDrawable
"@drawable/ic_cmnd" trái view
"@style/ThemeOverlay.
style Material3.AutoCompleteTextView. Kiểu dáng
OutlinedBox" cho TextInputLayout
"@+id/textEditHoTen" Tên biến đại diện của
id
"@+id/textEditCMND" view.
layout_width "match_parent" Chiều rộng của view
layout_height "wrap_content" Chiều cao của view
TextInputEditText
hint "Họ tên", "CMND" Gán chuỗi sẽ xuất hiện
5
(Họ tên, CMND) nếu view rỗng
"text" (Họ tên) Nhập dữ liệu chuỗi.
inputType
"number" (CMND)
Nhập dữ liệu số.

maxLength "9" (CMND) Giới hạn độ dài tối đa


chuỗi văn bản của view

13
layout_width "match_parent" Chiều rộng của view.
layout_height “wrap_content" Chiều cao của view.

6 RadioGroup orientation "horizontal" Các view con được xếp


theo chiều ngang.

gravity "center" Vị trí của các view con


trong view.
"@+id/radioTrungCap"
id "@+id/radioCaoDang"
"@+id/radioDaiHoc"
layout_width "wrap_content"
layout_height "wrap_content"
"Trung cấp"
text "Cao đẳng"
RadioButton "Đại học"
7 (Trung cấp, Cao
đẳng, Đại học) Khoảng cách cạnh trái
layout_marginLeft "20dp" (Cao đẳng) của RadioButton Cao
Đẳng so với view cha.

layout_marginRigh Khoảng cách cạnh phải


"20dp" (Cao đẳng) của RadioButton Cao
t
Đẳng so với view cha.

checked "true" (Đại học) RadioButton Đại học


đang được chọn
"@+id/checkboxDocSach"
id "@+id/checkboxNgheNhac"
"@+id/checkboxXemPhim"
layout_width "wrap_content"
layout_height "wrap_content"
"Đọc sách"
CheckBox text "Nghe nhạc"
(Đọc sách, "Xem phim"
8 Nghe nhạc, Khoảng cách cạnh trái
Xem phim) layout_marginLeft "20dp" (Nghe nhạc) của CheckBox Nghe
nhạc so với view cha

layout_marginRigh Khoảng cách cạnh phải


"20dp" (Nghe nhạc) của CheckBox Nghe
t
nhạc so với view cha

checked "true" (Nghe nhạc) CheckBox Nghe nhạc


đang được chọn
id "@+id/buttonGui"
layout_width "wrap_content"
Button
9 layout_height "wrap_content"
(Gửi thông tin)
text "Gửi thông tin"
layout_gravity "center"
"@+id/textEditBoSung"
id
"@+id/textEditHienThi"
TextInputEditText layout_width "match_parent"
(Thông tin bổ sung, layout_height "wrap_content"
10
THÔNG TIN CÁ "Thông tin bổ sung"
hint
NHÂN) "THÔNG TIN CÁ NHÂN"

inputType "textMultiLine" Nhập dữ liệu chuỗi trên


nhiều dòng

14
"2" (Thông tin bổ sung) Số dòng hiển thị của
lines
"5" (Thông tin cá nhân) view
Vô hiệu hóa chỉnh sửa
focusable "false" (Thông tin cá nhân) của view Thông tin cá
nhân

Bước 3: Viết code thiết kế giao diện trong file activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Thông tin cá nhân"
android:textAllCaps="true"
android:textColor="#ffffff"
android:textSize="25dp"
android:textStyle="bold"
android:gravity="center"
android:background="#3F51B5"/>

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textLayoutHoTen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true"
app:startIconDrawable="@drawable/ic_hoten"
style="@style/Widget.MaterialComponents.
TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditHoTen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Họ tên"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textLayoutCMND"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_columnWeight="3"
app:errorEnabled="true"
app:startIconDrawable="@drawable/ic_cmnd"
style="@style/Widget.MaterialComponents.
TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditCMND"
15
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="CMND"
android:inputType="number"
android:maxLength="9"/>
</com.google.android.material.textfield.TextInputLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bằng cấp"
android:textColor="#ffffff"
android:textSize="18dp"
android:textStyle="bold"
android:gravity="center"
android:background="#2196F3"/>

<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<RadioButton
android:id="@+id/radioTrungCap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Trung cấp"/>
<RadioButton
android:id="@+id/radioCaoDang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cao đẳng"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"/>
<RadioButton
android:id="@+id/radioDaiHoc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Đại học"/>
</RadioGroup>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sở thích"
android:textColor="#ffffff"
android:textSize="18dp"
android:textStyle="bold"
android:gravity="center"
android:background="#2196F3"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<CheckBox
android:id="@+id/checkboxDocSach"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Đọc sách"/>
<CheckBox

16
android:id="@+id/checkboxNgheNhac"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nghe nhạc"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:checked="true"/>
<CheckBox
android:id="@+id/checkboxXemPhim"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Xem phim"/>
</LinearLayout>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.
TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditBoSung"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Thông tin bổ sung"
android:inputType="textMultiLine"
android:lines="2"/>
</com.google.android.material.textfield.TextInputLayout>

<Button
android:id="@+id/buttonGui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gửi thông tin"
android:layout_gravity="center"/>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.
TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditHienThi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="THÔNG TIN CÁ NHÂN"
android:inputType="textMultiLine"
android:lines="5"
android:focusable="false" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

Bước 4: Viết code sự kiện cho các nút lệnh


 Tập tin MainActivity.java:
- Viết hàm addViews() để truy xuất các view trong activity_main.xml.
public class MainActivity extends AppCompatActivity {
TextInputLayout txtLayoutCMND, txtLayoutHoTen;

17
TextInputEditText edtHoTen, edtCMND, edtBoSung, edtHienThi;
RadioButton radTrungCap, radCaoDang, radDaiHoc;
CheckBox chkDocSach, chkXemPhim, chkNgheNhac;
Button btnGui;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addViews();
}
private void addViews() {
txtLayoutHoTen = findViewById(R.id.textLayoutHoTen);
txtLayoutCMND = findViewById(R.id.textLayoutCMND);
edtHoTen = findViewById(R.id.textEditHoTen);
edtCMND = findViewById(R.id.textEditCMND);
edtBoSung = findViewById(R.id.textEditBoSung);
edtHienThi = findViewById(R.id.textEditHienThi);
radTrungCap = findViewById(R.id.radioTrungCap);
radCaoDang = findViewById(R.id.radioCaoDang);
radDaiHoc = findViewById(R.id.radioDaiHoc);
chkDocSach = findViewById(R.id.checkboxDocSach);
chkXemPhim = findViewById(R.id.checkboxXemPhim);
chkNgheNhac = findViewById(R.id.checkboxNgheNhac);
btnGui = findViewById(R.id.buttonGui);
}
}

- Viết hàm addEvents() chứa các sự kiện

public class MainActivity extends AppCompatActivity {

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

addEvents();
}

boolean kiemTraHoTen = false;


boolean kiemTraCMND = false;

private void addEvents() {

// 1. Sự kiện xảy ra khi nội dung trong view Họ Tên thay đổi
edtHoTen.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(s.length()==0) {
txtLayoutHoTen.setError("Họ tên không được rỗng");
//edtHoTen.setCursorVisible(false);
kiemTraHoTen = false;
}
else {

18
txtLayoutHoTen.setError(null);
kiemTraHoTen = true;
}
}
@Override
public void afterTextChanged(Editable s) {
}
});

// 2. Sự kiện xảy ra khi nội dung trong view CMND thay đổi
edtCMND.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (s.length()<9) {
txtLayoutCMND.setError("CMND phải đủ 9 số");
edtCMND.setFocusable(true);
kiemTraCMND = false;
}
else {
txtLayoutCMND.setError(null);
kiemTraCMND = true;
}
}
@Override
public void afterTextChanged(Editable s){
}
});

// 3. Sự kiện xảy ra khi người dùng click vào nút Gửi thông tin
btnGui.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

// Lấy giá trị họ tên và cmnd


String ten = edtHoTen.getText().toString().trim();
String cmnd = edtCMND.getText().toString().trim();

if(kiemTraHoTen == false || kiemTraCMND == false)


return;

// Lấy giá trị bằng cấp


String bang = "";
if(radTrungCap.isChecked())
bang = radTrungCap.getText().toString();
else if(radCaoDang.isChecked())
bang = radCaoDang.getText().toString();
else
bang = radCaoDang.getText().toString();

// Lấy giá trị sở thích


String soThich = "";
if(chkDocSach.isChecked()) {
if (soThich.length() > 0)
soThich += ", ";
soThich += chkDocSach.getText().toString();
}
if(chkNgheNhac.isChecked()) {
if (soThich.length() > 0)

19
soThich += ", ";
soThich += chkNgheNhac.getText().toString();
}
if(chkXemPhim.isChecked()) {
if (soThich.length() > 0)
soThich += ", ";
soThich += chkXemPhim.getText().toString();
}
if(soThich=="")
{
Toast.makeText(MainActivity.this,
"Vui lòng chọn sở thích", Toast.LENGTH_LONG).show();
return;
}
// Lấy giá trị thông tin bổ sung
String boSung = edtBoSung.getText().toString();

// Hiển thị thông tin


edtHienThi.setText(ten + "\n" + cmnd + "\n" + bang +
"\n" + soThich + "\n" + boSung);
}
});
}
}

Bước 5: Kết quả thực hiện chương trình

Hình 1.5: Kết quả thực hiện giao diện Quản lý Thông tin cá nhân

20
Bài 4. Thiết kế giao diện Cập nhật thông tin cá nhân.

Hình 1-6: Giao diện Cập nhật thông tin cá nhân

Yêu cầu:
- Tên người không để trống.
- Chứng minh nhân dân chỉ được nhập dạng số và phải có đúng 9 chữ số.
- Điện thoại chỉ được nhập dạng số và có độ dài tối đa là 12 số.
- Khi nhấn nút Cập nhật, hiển thị toàn bộ thông tin cá nhân lên TextView.
- Khi nhấn nút Làm lại, xóa trống các view và đặt con trỏ vào view Họ tên.
- Khi nhấn vào nút Thoát, hiển thị thông báo nếu chọn “Có” thì thoát khỏi ứng dụng,
chọn “Không” thì đóng hộp thoại thông báo và không thoát ứng dụng.

21
Bài 5. Thiết kế giao diện ứng dụng Giải phương trình bậc hai

Hình 1-7: Giao diện Giải phương trình bậc hai

Yêu cầu:
- Số a, Số b, Số c: cho phép nhập dữ liệu dạng số nguyên có dấu và số thập phân.
- Kết quả: chỉ hiển thị thông tin, không cho phép chỉnh sửa.
- Viết sự kiện cho nút Giải, Tiếp tục, Thoát

22
PHẦN 2. CÁC ĐIỀU KHIỂN NÂNG CAO
2.1. Mục tiêu thực hành
 Giới thiệu và hướng dẫn cài đặt một số view nâng cao.
 Giới thiệu về CSDL SQLite và hướng dẫn cài đặt ứng dụng có lưu trữ CSDL với
SQLite.
2.2. Kỹ năng đạt được
 Sinh viên áp dụng cài đặt được một số chương trình cơ bản.
 Biết cách cài đặt ứng dụng có lưu trữ dữ liệu với SQLite.
2.3. Nội dung thực hành

Bài 1. Thiết kế giao diện ứng dụng Quản lý Nhân viên

Hình 2-1: Giao diện Quản lý Nhân viên

Mô tả:
 Nút “Nhập”: thêm dữ liệu nhập vào ListView.
 Khi click item trên ListView hiển thị thông tin tương ứng lên các view nhập liệu.
 Click image sửa: sửa nhân viên được chọn trên ListView.
 Click image xóa: xóa nhân viên được chọn trên ListView.
Mục tiêu: giới thiệu ListView, Custom ListView, ImageView và thêm, sửa, xóa thông tin
nhân viên.

23
Hướng dẫn:
Bước 1: Tạo dự án mới và đặt tên QLyNhanVien.
Bước 2: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
layout_height "match_parent" Chiều rộng của view
layout_width "match_parent" Chiều cao của view
orientation "vertical" Các view con được xếp
1 LinearLayout theo chiều dọc.
Khoảng cách các cạnh
layout_margin "10dp" của view so với view
cha.
layout_width "match_parent" Chiều rộng của view
layout_height "wrap_content" Chiều cao của view
"QUẢN LÝ NHÂN VIÊN"
text Chuỗi văn bản hiển thị
TextView "Danh sách nhân viên"
(Quản lý nhân textColor "#ffffff" Màu chữ trắng
2 viên, Danh sách
textSize "20dp" (Quản lý nhân viên) Cỡ chữ
nhân viên)
textStyle "bold" Kiểu chữ đậm
gravity "center" Vị trí của chuỗi văn bản
trong view
background "#445FF8" Màu nền xanh
layout_width "match_parent" Chiều rộng của view.
Chiều cao của view
TextInputLayout layout_height "wrap_content" bằng với nội dung
3 (Mã nhân viên, view.
Tên nhân viên)
"@style/ThemeOverlay.
style Material3.AutoCompleteTe Kiểu dáng
xtView.OutlinedBox" cho TextInputLayout
"@+id/textEditMaNV" Tên biến đại diện của
id
"@+id/textEditTenNV" view.
layout_width "match_parent" Chiều rộng của view
TextInputEditText
layout_height "wrap_content" Chiều cao của view
4 (Mã nhân viên,
"Mã nhân viên", Gán chuỗi sẽ xuất hiện
Tên nhân viên) hint
"Tên nhân viên" nếu view rỗng
Nhập dữ liệu chuỗi.
inputType "text"
Nhập dữ liệu số.
layout_width "match_parent" Chiều rộng của view.
layout_height “wrap_content" Chiều cao của view.
5 RadioGroup
orientation "horizontal" Các view con được xếp
theo chiều ngang.
RadioButton "@+id/radioNam"
6 id
(Nam, Nữ) "@+id/radioNu"

24
layout_width "wrap_content"
layout_height "wrap_content"
"Nam"
text
"Nữ"
Khoảng cách cạnh trái
layout_marginLeft "10dp" (Nam) của RadioButton Nam
so với view cha.
Khoảng cách cạnh phải
layout_marginRight "10dp" (Nam) của RadioButton Nam
so với view cha.
checked "true" (Nam) RadioButton Nam đang
được chọn
id "@+id/buttonNhap"
layout_width "wrap_content"
Button
7 layout_height "wrap_content"
(Nhập)
text "Nhập"
layout_gravity "center"
"@+id/imageSua"
id
"@+id/imageXoa"
ImageView layout_width "wrap_content"
8 (Sửa, Xóa) layout_height "wrap_content"
"@drawable/ic_sua"
src Ảnh cần hiển thị
"@drawable/ic_xoa"
id "@+id/listViewNhanVien"
layout_width "match_parent"
9 ListView layout_height "wrap_content"

listSelector "#D1E6F3" Màu lựa chọn từng


dòng
Bước 3: Viết code thiết kế giao diện trong file activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="QUẢN LÝ NHÂN VIÊN"
android:textColor="#ffffff"
android:textSize="20dp"
android:textStyle="bold"
android:gravity="center"
android:background="#445FF8"/>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

25
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditMaNV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mã nhân viên"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditTenNV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tên nhân viên"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>

<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Giới tính:"
android:paddingLeft="17dp"
android:textColor="#676565"
android:textSize="15dp"/>
<RadioButton
android:id="@+id/radioNam"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nam"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:checked="true"/>
<RadioButton
android:id="@+id/radioNu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nữ"/>
</RadioGroup>

<Button
android:id="@+id/buttonNhap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nhập"
android:layout_gravity="center"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Danh sách nhân viên:"
android:textColor="#ffffff"

26
android:textStyle="bold"
android:background="#445FF8"
android:layout_weight="2"
android:layout_gravity="center"/>
<ImageView
android:id="@+id/imageSua"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_sua" />
<ImageView
android:id="@+id/imageXoa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_xoa" />
</LinearLayout>

<ListView
android:id="@+id/listViewNhanVien"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="#D1E6F3"/>
</LinearLayout>

Bước 4: Tạo class NhanVien.java


public class NhanVien implements Serializable {
private String ma;
private String ten;
private boolean nam;

public NhanVien() {
}

public NhanVien(String ma, String ten, boolean nam) {


this.ma = ma;
this.ten = ten;
this.nam = nam;
}

public String getMa() {


return ma;
}

public void setMa(String ma) {


this.ma = ma;
}

public String getTen() {


return ten;
}

public void setTen(String ten) {


this.ten = ten;
}

public boolean isNam() {


return nam;
}

public void setNam(boolean nam) {


this.nam = nam;
}

27
@Override
public String toString() {
String gt = "";
if(this.nam)
gt = "Nam";
else
gt = "Nữ";
return ma + " - " + ten + " - " + gt;
}
}

Bước 5: Viết code sự kiện cho các nút lệnh


Tập tin MainActivity.java:
- Viết hàm addViews() để truy xuất các view trong activity_main.xml và tạo đối
tượng ArrayAdapter để liên kết giữa ListView và danh sách dữ liệu.
public class MainActivity extends AppCompatActivity {
TextInputEditText edtMa, edtTen;
RadioButton radNam, radNu;
Button btnNhap;
ImageView imgXoa, imgSua;
ListView lvNhanVien;

//Khai báo đối tượng listNhanVien và adapter


ArrayList<NhanVien> listNhanVien;
ArrayAdapter<NhanVien> adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addViews();
}
private void addViews() {
edtMa = findViewById(R.id.textEditMaNV);
edtTen = findViewById(R.id.textEditTenNV);
radNam = findViewById(R.id.radioNam);
radNu = findViewById(R.id.radioNu);
btnNhap = findViewById(R.id.buttonNhap);
lvNhanVien = findViewById(R.id.listViewNhanVien);
imgSua = findViewById(R.id.imageSua);
imgXoa = findViewById(R.id.imageXoa);

// Khởi tạo listNhanVien và adapter


listNhanVien = new ArrayList<NhanVien>();
adapter = new ArrayAdapter<NhanVien>(MainActivity.this,
android.R.layout.simple_list_item_1, listNhanVien);
lvNhanVien.setAdapter(adapter);
}
}

- Viết hàm addEvents() chứa các sự kiện:


+ Sự kiện click nút Nhập
+ Sự kiện click item trên ListView
+ Sự kiện click image sửa
+ Sự kiện click image xóa

28
public class MainActivity extends AppCompatActivity {

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

addEvents();
}

//Khai báo biến viTri để lưu lại vị trí item được chọn trên ListView
int viTri = -1;

private void addEvents() {


// Sự kiện click nút Nhập
btnNhap.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NhanVien nv = new NhanVien();
nv.setMa(edtMa.getText().toString());
nv.setTen(edtTen.getText().toString());
nv.setNam(radNam.isChecked());
listNhanVien.add(nv);
adapter.notifyDataSetChanged();
}
});

// Sự kiện click item trên ListView


lvNhanVien.setOnItemClickListener(new

AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView,
View view, int i, long l) {
edtMa.setText(listNhanVien.get(i).getMa());
edtTen.setText(listNhanVien.get(i).getTen());
if (listNhanVien.get(i).isNam())
radNam.setChecked(true);
else
radNu.setChecked(true);
viTri = i;
}
});

// Sự kiện click imgSua


imgSua.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NhanVien nv = new NhanVien();
nv.setMa(edtMa.getText().toString());
nv.setTen(edtTen.getText().toString());
nv.setNam(radNam.isChecked());

// Cập nhật lại nv tại viTri được chọn trong listNhanVien.


listNhanVien.set(viTri,nv);
// Cập nhật lại adapter
adapter.notifyDataSetChanged();
}
});

// Sự kiện click imgXoa “X”


imgXoa.setOnClickListener(new View.OnClickListener() {
@Override

29
public void onClick(View view) {
listNhanVien.remove(viTri);
adapter.notifyDataSetChanged();
}
});
}
}

Bước 6: Hiển thị danh sách Nhân viên lên Custom ListView

Hình 2-2: Giao diện Custom ListView Nhân viên

Bước 6.1. Thiết kế giao diện để hiển thị từng nhân viên trong ListView.
Trong res/layout, tạo file xml:
- Chọn new/XML/Layout XML File, đặt tên layout_item_nhanvien.xml
- Thiết kế giao diện như hình:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageItemHinh"
android:layout_width="50dp"
android:layout_height="50dp"
30
android:src="@drawable/ic_nam"/>
<TextView
android:id="@+id/textViewItemHoTen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:layout_gravity="center"/>
</LinearLayout>

Bước 6.2. Tạo class NhanVienAdapter.java


public class NhanVienAdapter extends ArrayAdapter<NhanVien> {
Activity context;
int resource;

public NhanVienAdapter(@NonNull Activity context, int resource,


@NonNull List<NhanVien> objects) {
super(context, resource, objects);
this.context=context;
this.resource=resource;
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
View viewItem;
if(convertView == null) {
LayoutInflater in = this.context.getLayoutInflater();
viewItem = in.inflate(this.resource,null);
}
else
viewItem = convertView;

// Truy xuất các view trong activity_item_nhanvien.xml


ImageView imgHinh = viewItem.findViewById(R.id.imageItemHinh);
TextView txtHoTen = viewItem.findViewById(R.id.textViewItemHoTen);

// Lấy Nhân viên trong list Nhân viên tại vị trí position
NhanVien nv = getItem(position);
if(nv.isNam())
imgHinh.setImageResource(R.drawable.ic_nam);
else
imgHinh.setImageResource(R.drawable.ic_nu);
txtHoTen.setText(nv.getMa()+ " - " + nv.getTen());

return viewItem;
}
}

Bước 6.3. Cập nhật MainActivity.java


public class MainActivity extends AppCompatActivity {
TextInputEditText edtMa, edtTen;
RadioButton radNam, radNu;
Button btnNhap;
ImageView imgXoa, imgSua;
ListView lvNhanVien;

//Khai báo danh sách listNhanVien và adapter


ArrayList<NhanVien> listNhanVien;
//ArrayAdapter<NhanVien> adapter;
31
NhanVienAdapter nhanVienAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addViews();
addEvents();
}
private void addViews() {
edtMa = findViewById(R.id.textEditMaNV);
edtTen = findViewById(R.id.textEditTenNV);
radNam = findViewById(R.id.radioNam);
radNu = findViewById(R.id.radioNu);
btnNhap = findViewById(R.id.buttonNhap);
lvNhanVien = findViewById(R.id.listViewNhanVien);
imgSua = findViewById(R.id.imageSua);
imgXoa = findViewById(R.id.imageXoa);

// Khởi tạo listNhanVien và adapter


listNhanVien = new ArrayList<NhanVien>();
//adapter = new ArrayAdapter<NhanVien>(MainActivity.this,
android.R.layout.simple_list_item_1, listNhanVien);
//lvNhanVien.setAdapter(adapter);

nhanVienAdapter = new NhanVienAdapter(MainActivity.this,


R.layout.activity_item_nhanvien,listNhanVien);
lvNhanVien.setAdapter(nhanVienAdapter);

}
//Khai báo biến viTri để lưu lại vị trí item được chọn trên ListView
int viTri = -1;
private void addEvents() {
btnNhap.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NhanVien nv = new NhanVien();
nv.setMa(edtMa.getText().toString());
nv.setTen(edtTen.getText().toString());
nv.setNam(radNam.isChecked());
listNhanVien.add(nv);

//adapter.notifyDataSetChanged();
nhanVienAdapter.notifyDataSetChanged();
}
});

lvNhanVien.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView,
View view, int i, long l) {
edtMa.setText(listNhanVien.get(i).getMa());
edtTen.setText(listNhanVien.get(i).getTen());
if (listNhanVien.get(i).isNam())
radNam.setChecked(true);
else
radNu.setChecked(true);
viTri = i;
}
});

imgSua.setOnClickListener(new View.OnClickListener() {

32
@Override
public void onClick(View view) {
NhanVien nv = new NhanVien();
nv.setMa(edtMa.getText().toString());
nv.setTen(edtTen.getText().toString());
nv.setNam(radNam.isChecked());

// Cập nhật lại nv tại viTri được chọn trong listNhanVien


listNhanVien.set(viTri,nv);
// adapter.notifyDataSetChanged();
nhanVienAdapter.notifyDataSetChanged();

}
});

imgXoa.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listNhanVien.remove(viTri);
//adapter.notifyDataSetChanged();
nhanVienAdapter.notifyDataSetChanged();
}
});
}
}

Bài 2. Thiết kế giao diện Đăng nhập hệ thống

Hình 2-3: Giao diện Đăng nhập hệ thống

Mục tiêu: giới thiệu Shared Preferences và thay đổi ngôn ngữ ứng dụng.
Hướng dẫn:
Bước 1: Tạo dự án mới và đặt tên DangNhapHeThong.
Bước 2: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
layout_height "match_parent"
layout_width "match_parent"
1 LinearLayout
orientation "vertical"
layout_margin "10dp"

33
layout_width "wrap_content"
layout_height "wrap_content"
text "@string/textViewDangNhap"
textColor "#143cec"
TextView textSize "25dp"
(Đăng nhập hệ
2 textStyle "bold"
thống)
fontFamily "monospace" Font chữ
layout_gravity "center" Vị trí của view so
với view cha
Khoảng cách cạnh
layout_marginTop "20dp" trên của view so
với view cha
layout_width "match_parent"
layout_height "wrap_content"
TextInputLayout passwordToggleEnab Hiển thị nút bấm để
3 (Tài khoản, "true" (Mật khẩu) hiện nội dung
led
Mật khẩu) password
"@style/ThemeOverlay.
style Material3.AutoCompleteText
View.OutlinedBox"
"@+id/textEditUser"
id
"@+id/textEditPass"
layout_width "match_parent"
TextInputEditText
layout_height "wrap_content"
4 (Tài khoản,
"@string/inputEditTaiKhoan"
Mật khẩu) hint
"@string/inputEditMatKhau"
"text" Nhập dữ liệu chuỗi
inputType
"textPassword" Nhập dữ liệu pass
id "@+id/checkboxSave"
layout_width "wrap_content"
CheckBox
5 layout_height "wrap_content"
(Lưu thông tin)
layout_gravity "center"
text "@string/checkBoxLuu"
id "@+id/buttonLogin"
layout_width "wrap_content"
layout_height "wrap_content"
Button
6 text "@string/buttonDangNhap"
(Đăng nhập)
layout_gravity "center"
background "#2196F3"
textColor "#FFFFFF"

Bước 3: Trong res/values/string.xml, định nghĩa ngôn ngữ Tiếng việt.


<resources>
<string name="app_name">Đăng Nhập</string>
34
<string name="textViewDangNhap">ĐĂNG NHẬP HỆ THỐNG</string>
<string name="inputEditTaiKhoan">Tài khoản</string>
<string name="inputEditMatKhau">Mật khẩu</string>
<string name="checkBoxLuu">Lưu thông tin</string>
<string name="buttonDangNhap">Đăng nhập</string>
</resources>

Bước 4: Thay đổi ngôn ngữ ứng dụng, định nghĩa ngôn ngữ English (en).
Right click strings.xml(1)/Open Translations Editor/Add Locale(2)/Chọn Quốc gia
(English (en))/Nhập thông tin(3).

Bước 5: Viết code thiết kế giao diện trong file activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="10dp">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/textViewDangNhap"
android:textColor="#143cec"
android:textSize="25dp"
android:textStyle="bold"
android:layout_marginTop="20dp"
android:fontFamily="monospace"/>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditUser"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/inputEditTaiKhoan"/>
</com.google.android.material.textfield.TextInputLayout>

35
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleEnabled="true"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditPass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/inputEditMatKhau"
android:inputType="textPassword"/>
</com.google.android.material.textfield.TextInputLayout>

<CheckBox
android:id="@+id/checkboxSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/checkBoxLuu"
android:layout_gravity="center"/>

<Button
android:id="@+id/buttonLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#2196F3"
android:textColor="#FFFFFF"
android:text="@string/buttonDangNhap"/>
</LinearLayout>

Bước 6: Viết code sự kiện cho nút Login


Tập tin MainActivity.java:
- Viết hàm addViews() để truy xuất các view trong activity_main.xml và tạo tập tin
để lưu trạng thái đăng nhập.
public class MainActivity extends AppCompatActivity {
TextInputEditText edtUser, edtPass;
CheckBox chkSave;
Button btnLogin;

// Khai báo và khởi tạo Tên tập tin lưu trạng thái
String preferName = "DangNhapData";

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

private void addViews() {


edtUser = findViewById(R.id.textEditUser);
edtPass = findViewById(R.id.textEditPass);
chkSave = findViewById(R.id.checkboxSave);
btnLogin = findViewById(R.id.buttonLogin);
}
}

- Viết hàm onPause() và SavePreferences() để lưu thông tin và trạng thái đăng nhập.

36
@Override
protected void onPause() {
super.onPause();
SavePreferences();
}

private void SavePreferences() {


// Tạo đối tượng getSharedPreferences
SharedPreferences preferences = getSharedPreferences(preferName,
MODE_PRIVATE);

// Tạo đối tượng Editor để lưu thay đổi


SharedPreferences.Editor editor = preferences.edit();

if (chkSave.isChecked()) {
// Lưu vào editor
editor.putString("putUser",edtUser.getText().toString());
editor.putString("putPass",edtPass.getText().toString());
editor.putBoolean("putSave", chkSave.isChecked());
}
else
editor.clear(); // Xóa thông tin lưu trước đó

// Lưu xuống file


editor.commit();
}

- Viết hàm onResume() và RestorPreferences() để đọc thông tin đã lưu.


@Override
protected void onResume() {
super.onResume();
RestorPreference();
}

private void RestorPreference() {


SharedPreferences preferences = getSharedPreferences(preferName,
MODE_PRIVATE);

// Lấy giá trị putSave, nếu không tìm thấy


// thì cho giá trị mặc định là false(không check vào CheckBox).
boolean luuThongTin = preferences.getBoolean("putSave", false);
if (luuThongTin) //Nếu lưu thông tin là true
{
String taiKhoan = preferences.getString("putUser", "");
String matKhau = preferences.getString("putPass", "");
edtUser.setText(taiKhoan);
edtPass.setText(matKhau);
}
chkSave.setChecked(luuThongTin);
}

- Viết hàm addEvents() chứa sự kiện click nút Login.


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

private void addEvents() {


btnLogin.setOnClickListener(new View.OnClickListener() {

37
@Override
public void onClick(View v) {
String taiKhoan = edtUser.getText().toString().trim();
String matKhau = edtPass.getText().toString().trim();

if(taiKhoan.equals("admin") && matKhau.equals("123")) {


Toast.makeText(MainActivity.this, "Đăng nhập thành
công", Toast.LENGTH_LONG).show();
finish(); // đóng màn hình hiện tại

// Hiển thị Activity hệ thống


Intent intent = new Intent(MainActivity.this,
HeThongActivity.class);
startActivity(intent);
}
else
Toast.makeText(MainActivity.this,"Tài khoản &
mật khẩu chưa đúng",Toast.LENGTH_LONG).show();
}
});
}

Bước 7: Kết quả thực hiện chương trình

Hình 2-4: Giao diện kết quả Đăng nhập

Bài 3. Viết chương trình Quản lý Sản Phẩm

Hình 2-5: Giao diện Quản lý Sản phẩm

38
Mô tả:
- Đối tượng Sản phẩm gồm thuộc tính mã, tên và giá bán Sản phẩm.
- Hiển thị danh sách tên Sản phẩm lên ListView.
- Khi click item trên ListView gọi Activity Thông tin Sản phẩm và hiển thị thông tin
Sản phẩm đã chọn lên các view tương ứng.
- Nút “Trở về”: đóng Activity Thông tin Sản phẩm trở về Activity danh sách Sản
phẩm.
Nút “Xóa”: đóng Activity Thông tin Sản phẩm trở về Activity danh sách Sản phẩm
và xóa Sản phẩm đã chọn trên ListView.
Mục tiêu: giới thiệu Inten trong Android.
Hướng dẫn:
Bước 1: Tạo dự án mới và đặt tên QLySanPham.
Bước 2: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
layout_height "match_parent"
layout_width "match_parent"
1 LinearLayout
orientation "vertical"
layout_margin "10dp"
layout_width "match_parent"
layout_height "wrap_content"
text "Danh sách Sản phẩm"
TextView
(Danh sách sản textColor "#ffffff"
2 phẩm) textSize "25dp"
textStyle "bold"
gravity "center"
background "#2444F8"
id "@+id/listViewSanPham"
layout_width "match_parent"
9 ListView
layout_height "wrap_content"
listSelector "#D2E9FB"
Bước 3: Viết code thiết kế giao diện trong file activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
39
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Danh sách sản phẩm"
android:textSize="25dp"
android:textStyle="bold"
android:textColor="#ffffff"
android:background="#2444F8"
android:gravity="center"/>
<ListView
android:id="@+id/listViewSanPham"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="#D2E9FB"/>
</LinearLayout>

Bước 4: Thiết kế giao diện Thông tin chi tiết sản phẩm
Trong res/layout, tạo file Activity:
- Chọn new/Activity/Empty Activity, đặt tên activity_thong_tin_san_pham.xml
- Thiết kế giao diện như hình:

Hình 2-6: Giao diện Thông tin Sản phẩm

- Code giao diện trong activity_thong_tin_san_pham.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputEditMa"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mã sản phẩm"/>
</com.google.android.material.textfield.TextInputLayout>
40
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputEditTen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tên sản phẩm"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputEditGia"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Đơn giá bán"/>
</com.google.android.material.textfield.TextInputLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/buttonXoa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Xóa"/>
<Button
android:id="@+id/buttonTroVe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Trở về"
android:layout_marginLeft="10dp"/>
</LinearLayout>
</LinearLayout>

Bước 5: Tạo class SanPham.java


public class SanPham implements Serializable {
private String ma;
private String ten;
private int gia;

public SanPham() {
}

public SanPham(String ma, String ten, int gia) {


this.ma = ma;
this.ten = ten;
this.gia = gia;
}

public String getMa() {


return ma;
}

public void setMa(String ma) {

41
this.ma = ma;
}

public String getTen() {


return ten;
}

public void setTen(String ten) {


this.ten = ten;
}

public int getGia() {


return gia;
}

public void setGia(int gia) {


this.gia = gia;
}

@Override
public String toString() {
return this.ten;
}
}

Bước 6: Trong MainActivity.java:


- Viết hàm addViews() để truy xuất các view trong activity_main.xml.
- Tạo đối tượng ArrayAdapter để liên kết giữa ListView và danh sách dữ liệu.
- Khởi tạo 1 số sản phẩm và hiển thị tên Sản phẩm lên ListView.
public class MainActivity extends AppCompatActivity {
ListView lvSanPham;
ArrayAdapter<SanPham> sanPhamAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide(); //Ẩn tiêu đề của Activity
setContentView(R.layout.activity_main);
addViews();
}

private void addViews() {


lvSanPham = findViewById(R.id.listViewSanPham);
sanPhamAdapter = new ArrayAdapter<SanPham>(MainActivity.this,
android.R.layout.simple_list_item_1);
lvSanPham.setAdapter(sanPhamAdapter);

// Khởi tạo Sản phẩm


sanPhamAdapter.add(new SanPham("sp01", "Pepsi", 15000));
sanPhamAdapter.add(new SanPham("sp02", "7Up", 12000));
sanPhamAdapter.add(new SanPham("sp03", "Sting", 10000));
sanPhamAdapter.add(new SanPham("sp04", "Coca", 13000));
sanPhamAdapter.add(new SanPham("sp05", "Fanta", 11000));
}
}

- Viết hàm addEvents() chứa sự kiện click item trên ListView


public class MainActivity extends AppCompatActivity {
ListView lvSanPham;
ArrayAdapter<SanPham> sanPhamAdapter;
42
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addViews();
addEvents();
}

private void addEvents() {


// Sự kiện click item trên ListView
lvSanPham.setOnItemClickListener(new AdapterView.
OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView,
View view, int i, long l) {
// Lấy Sản phẩm tại vị trí thứ i
SanPham sp = sanPhamAdapter.getItem(i);

//Gọi và gửi sp qua activity_thong_tin_san_pham.xml


Intent intent= new Intent(MainActivity.this,
ThongTinSanPhamActivity.class);
intent.putExtra("SANPHAM",sp);
startActivityForResult(intent,100);
}
});
}
// Hàm nhập kết quả trả về
@Override
protected void onActivityResult(int requestCode, int resultCode,
@Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}

Bước 7: Trong ThongTinSanPhamActivity.java


- Viết hàm addViews() để truy xuất các view trong activity_thong_tin_san_pham.xml.
- Lấy Sản phẩm được gửi qua từ MainActivity.java và hiển thị thông tin sản phẩm lên
các view tương ứng.
public class ThongTinSanPhamActivity extends AppCompatActivity {
TextInputEditText inputEditMaSP, inputEditTenSP, inputEditGiaSP;
Button btnXoa, btnTroVe;
Intent intent;
SanPham sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Thông tin Sản phẩm");
setContentView(R.layout.activity_thong_tin_san_pham);
addViews();
}

private void addViews() {


inputEditMaSP = findViewById(R.id.inputEditMa);
inputEditTenSP = findViewById(R.id.inputEditTen);
inputEditGiaSP = findViewById(R.id.inputEditGia);
btnXoa = findViewById(R.id.buttonXoa);
btnTroVe = findViewById(R.id.buttonTroVe);

// Lấy sp được gửi qua từ MainActivity.java


intent = getIntent();
43
sp = (SanPham) intent.getSerializableExtra("SANPHAM");

// Gán thông tin sp lên các view tương ứng


inputEditMaSP.setText(sp.getMa());
inputEditTenSP.setText(sp.getTen());
inputEditGiaSP.setText(sp.getGia() + "");
}
}

- Viết hàm addEvents() chứa các sự kiện:


+ Sự kiện click nút Xóa
+ Sự kiện click nút Trở về
private void addEvents() {
btnTroVe.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});

btnXoa.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
intent.putExtra("SANPHAMXOA", sp);
setResult(200,intent);
finish();
}
});
}

Bước 8: Trong MainActivity.java cập nhật lại hàm onActivityResult(), nhận kết quả trả về
và thực hiện xóa sản phẩm.
@Override
protected void onActivityResult(int requestCode, int resultCode,
@Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 100 && resultCode == 200)
{
SanPham spXoa = (SanPham) data.getSerializableExtra("SANPHAMXOA");
for(int i=0; i<sanPhamAdapter.getCount(); i++)
{
SanPham sp = sanPhamAdapter.getItem(i);
if(sp.getMa().equals(spXoa.getMa()))
{
sanPhamAdapter.remove(sp);
break;
}
}
}
}

44
Bài 4. Cài đặt ứng dụng Ghi chú Công việc

Hình 2-7: Giao diện ứng dụng Ghi chú Công việc
Mô tả:
- Đối tượng Công việc gồm thuộc tính mã công việc, tên công việc.
- Hiển thị danh sách tên Công việc lên ListView.
- Thực hiện thêm, sửa, xóa Công việc và lưu vào CSDL SQLite.
Mục tiêu: giới thiệu CSDL SQLite trong Android.
Hướng dẫn:
Bước 1: Đặt tên, thay đổi thuộc tính các view của giao diện như bảng sau:

Thuộc tính
STT Tên view
Tên thuộc tính Giá trị Mô tả
layout_height "match_parent"
1 CoordinatorLayout
layout_width "match_parent"
id "@+id/listViewCongViec"
2 ListView layout_width "match_parent"
layout_height "match_parent"
id "@+id/actionButtonThem"
layout_width "match_parent"
3 FloatingActionButton
layout_height "wrap_content"
layout_gravity "right|bottom"

45
src "@drawable/ic_them" Thêm biểu tượng
vào view
backgroundTint "#E91E63" Màu nền
tint "#ffffff" Màu biểu tượng
fabSize "normal" FAB ở cỡ chuẩn
layout_marginEnd "12dp"
layout_marginBottom "12dp"

Code giao diện (activity_main.xml)


<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<ListView
android:id="@+id/listViewCongViec"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/actionButtonThem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="@drawable/ic_them"
android:backgroundTint="#E91E63"
android:tint="#ffffff"
app:fabSize="normal"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Bước 2: Định nghĩa lớp đối tượng DBHelper kế thừa từ lớp SQLiteOpenHelper và thêm nội
dung cho các phương thức sau:
public class DBHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "QLCongViec.sqlite";
public static final int DB_VERSION = 1;

public DBHelper(@Nullable Context context) {


super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// Tạo bảng CongViec
String sql = "CREATE TABLE IF NOT EXISTS CongViec(" +
"Id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"TenCV VARCHAR(200))";
sqLiteDatabase.execSQL(sql); // Thực thi chuỗi lệnh sql
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
// Sử dụng trong trường hợp thay đổi cấu trúc bảng, nâng cấp CSDL
// Xóa bảng nếu tồn tại bảng Công việc

46
String sql = "DROP TABLE IF EXISTS CongViec";
sqLiteDatabase.execSQL(sql); // Thực thi xóa bảng
onCreate(sqLiteDatabase); // Tạo lại bảng mới
}
}

Bước 3: Tạo lớp đối tượng tương ứng với bảng trong CSDL (CongViec.java)
public class CongViec {
private int IdCV;
private String TenCV;

public CongViec() {
}

public CongViec(int idCV, String tenCV) {


IdCV = idCV;
TenCV = tenCV;
}

public int getIdCV() {


return IdCV;
}

public void setIdCV(int idCV) {


IdCV = idCV;
}

public String getTenCV() {


return TenCV;
}

public void setTenCV(String tenCV) {


TenCV = tenCV;
}
}

Bước 4: Tạo lớp CongViecDAO.java thêm vào các phương thức thao tác với CSDL như:
thêm, sửa, xóa, truy vấn, ...
- Thêm dữ liệu vào bảng CongViec
- Lấy dữ liệu trong bảng CongViec
public class CongViecDAO {
private SQLiteDatabase db;
public CongViecDAO(Context context) {
DBHelper dbHelper = new DBHelper(context);
// Mở CSDL ở chế độ ghi để thực hiện các thao tác thêm, xóa, sửa các bảng
db = dbHelper.getWritableDatabase();
}
public void DuLieuMau()
{
String sql = "INSERT INTO CongViec VALUES(null,'Làm bài tập C#')";
db.execSQL(sql);
}
public List<CongViec> getCongViec() {
List<CongViec> list = new ArrayList<>();
Cursor cursor = db.rawQuery("SELECT * FROM CongViec", null);

while (cursor.moveToNext()) {
CongViec cv = new CongViec();
cv.setIdCV(cursor.getInt(0));

47
cv.setTenCV(cursor.getString(1));
//cv.setTenCV(cursor.getString(cursor.getColumnIndex("TenCV")));
list.add(cv);
}
return list;
}
}

Bước 5: Thiết kế giao diện để hiển thị từng dòng công việc trong ListView.
Trong res/layout, tạo file xml:
- Chọn new/XML/Layout XML File, đặt tên layout_item_cong_viec.xml
- Thiết kế giao diện như hình:

Hình 2-8: Giao diện item Công việc

<?xml version="1.0" encoding="utf-8"?>


<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="12dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:gravity="center">
<TextView
android:id="@+id/textviewTenCV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tên công việc"
android:textColor="#2240E9"
android:textSize="20dp"
android:layout_weight="2" />
<ImageView
android:id="@+id/imageviewSua"
android:src="@drawable/ic_sua"
android:layout_width="23dp"
android:layout_height="23dp"/>
<ImageView
android:id="@+id/imageviewXoa"
android:src="@drawable/ic_xoa"
android:layout_width="25dp"
android:layout_height="25dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>

48
Bước 6: Tạo lớp CongViecAdapter.java
public class CongViecAdapter extends ArrayAdapter<CongViec> {
private Activity context;
private int resource;
private List<CongViec> objects;
public CongViecAdapter(@NonNull Activity context, int resource,
@NonNull List<CongViec> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.objects = objects;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
View viewItem;
if(convertView == null) {
// Tạo view
LayoutInflater in = this.context.getLayoutInflater();
viewItem = in.inflate(this.resource,null);
}
else
viewItem = convertView;

// Lấy công việc tại vị trí postion


CongViec cv = getItem(position);

// Truy xuất các view và thay đổi nội dung hiển thị
TextView txthoten = viewItem.findViewById(R.id.textviewTenCV);
txthoten.setText(cv.getTenCV());
ImageView imgXoa = viewItem.findViewById(R.id.imageviewXoa);
ImageView imgSua = viewItem.findViewById(R.id.imageviewSua);

return viewItem;
}
}

Bước 7: Trong MainActivity.java, viết hàm addViews() để truy xuất các view trong
activity_main.xml và lấy dữ liệu trong bảng CongViec hiển thị lên ListView.
public class MainActivity extends AppCompatActivity {
private ListView lvCongViec;
private FloatingActionButton fabThem;

private List<CongViec> listCongViec;


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

private void addViews() {


lvCongViec = findViewById(R.id.listViewCongViec);
fabThem = findViewById(R.id.actionButtonThem);

CongViecDAO congViecDAO = new CongViecDAO(this);


congViecDAO.DuLieuMau();

49
// Lấy dữ liệu hiển thị lên ListView
listCongViec = congViecDAO.getCongViec();
congViecAdapter = new CongViecAdapter(MainActivity.this,
R.layout.activity_item_cong_viec,listCongViec);
lvCongViec.setAdapter(congViecAdapter);
}
}

Bước 8: Thiết kế giao diện Thêm Công việc


Trong res/layout, tạo file Activity:
- Chọn new/Activity/Empty Activity, đặt tên activity_them_cong_viec.xml
- Thiết kế giao diện như hình:

Hình 2-9: Giao diện thêm Công việc

Bước 8.1: Code giao diện activity_them_cong_viec.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="THÊM CÔNG VIỆC"
android:textColor="#ffffff"
android:textSize="20dp"
android:textStyle="bold"
android:gravity="center"
android:background="#445FF8"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditThemCVTen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tên công việc"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>

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

50
<Button
android:id="@+id/buttonThemCVThem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Thêm"/>

<Button
android:id="@+id/buttonThemCVHuy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hủy"/>
</LinearLayout>
</LinearLayout>

Bước 8.2: Trong CongViecDAO.java, thêm hàm insertCV()


public void insertCV(CongViec cv)
{
String sql = "INSERT INTO CongViec VALUES(null, '" +
cv.getTenCV() + "')";
db.execSQL(sql);
}
// hoặc:
public void insertCV(CongViec cv)
{
ContentValues values = new ContentValues();
values.put("TenCV", cv.getTenCV());
db.insert("CongViec",null,values);
}

Bước 8.3: Trong MainActivity.java, thêm hàm addEvents() chứa sự kiện click nút thêm
(fabThem). Khi click vào fabThem gọi activity_them_cong_viec.xml.
public class MainActivity extends AppCompatActivity {
private ListView lvCongViec;
private FloatingActionButton fabThem;

private List<CongViec> listCongViec;


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

addViews();
addEvents();
}

private void addEvents() {


fabThem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,
ThemCongViecActivity.class);
startActivity(intent,100);
}
});
}
}

Bước 8.4: Trong ThemCongViecActivity.java, thực hiện thêm công việc vào CSDL.

51
public class ThemCongViecActivity extends AppCompatActivity {
private TextInputEditText edtTen;
private Button btnThem, btnHuy;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide(); // Ẩn tiêu đề Activity
setContentView(R.layout.activity_them_cong_viec);

edtTen = findViewById(R.id.textEditThemCVTen);
btnThem = findViewById(R.id.buttonThemCVThem);
btnHuy = findViewById(R.id.buttonThemCVHuy);

// Sự kiện Click của nút Thêm


btnThem.setOnClickListener(new View.OnClickListener() {
MainActivity main = new MainActivity();
@Override
public void onClick(View v) {
if(edtTen.getText().toString().equals(""))
Toast.makeText(ThemCongViecActivity .this, "Vui lòng
nhập tên công việc",Toast.LENGTH_LONG).show();
else {
CongViec cv = new CongViec(edtTen.getText().toString());
CongViecDAO congViecDAO = new
CongViecDAO(ThemCongViecActivity.this);
congViecDAO.insertCV(cv);
Toast.makeText(ThemCongViecActivity.this,"Đã thêm",
Toast.LENGTH_LONG).show();
}
}
});

// Sự kiện nút hủy


btnHuy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}

Bước 8.5: Trong MainActivity.java, thêm hàm onResume() cập nhật dữ liệu trên ListView.
public class MainActivity extends AppCompatActivity {
private ListView lvCongViec;
private FloatingActionButton fabThem;

private List<CongViec> listCongViec;


private CongViecAdapter congViecAdapter;

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

addViews();
addEvents();
}

// Cập nhật dữ liệu trên ListView


@Override

52
public void onResume() {
super.onResume();
CongViecDAO congViecDAO = new CongViecDAO(MainActivity.this);
List<CongViec> updateList = congViecDAO.getCongViec();
listCongViec.clear();
for( CongViec item : updateList)
listCongViec.add(item);
congViecAdapter.notifyDataSetChanged();
}
}

Bước 9: Thiết kế giao diện Sửa Công việc


Trong res/layout, tạo file Activity:
- Chọn new/Activity/Empty Activity, đặt tên activity_sua_cong_viec.xml
- Thiết kế giao diện như hình:

Hình 2-10: Giao diện Cập nhật Công việc

Bước 9.1: Code thiết kế giao diện activity_sua_cong_viec.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="CẬP NHẬT CÔNG VIỆC"
android:textColor="#ffffff"
android:textSize="20dp"
android:textStyle="bold"
android:gravity="center"
android:background="#445FF8"/>

<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/textEditSuaCVTen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tên công việc"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>

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

<Button
android:id="@+id/buttonSuaCVSua"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sửa"/>

<Button
android:id="@+id/buttonSuaCVHuy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hủy"/>
</LinearLayout>
</LinearLayout>

Bước 9.2: Trong CongViecDAO.java, thêm hàm updateCV()


public void updateCV(CongViec cv)
{
String sql = "UPDATE CongViec SET TenCV = '" + cv.getTenCV() +
"' WHERE Id = '" + cv.getIdCV() + "'";
db.execSQL(sql);
}
// hoặc:
public long updateCV(CongViec cv)
{
ContentValues values = new ContentValues();
values.put("TenCV", cv.getTenCV());
return db.update("CongViec",values,"id=?",
new String[]{String.valueOf(cv.getIdCV())});
}

Bước 9.3: Trong CongViecAdapter.java


- Click vào imgSua hiển thị activity_sua_cong_viec.java dạng Dialog.
- Thực hiện sửa công việc được chọn và cập nhật vào CSDL.
public class CongViecAdapter extends ArrayAdapter<CongViec> {
private Activity context;
private int resource;
private List<CongViec> objects;
public CongViecAdapter(@NonNull Activity context, int resource,
@NonNull List<CongViec> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.objects = objects;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
View viewItem;
if(convertView == null) {
// Tạo view thông qua inflate
LayoutInflater in = this.context.getLayoutInflater();
viewItem = in.inflate(this.resource,null);

54
}
else
viewItem = convertView;

// Lấy công việc tại vị trí postion


CongViec cv = getItem(position);

// Truy xuất các view và thay đổi nội dung hiển thị
TextView txthoten = viewItem.findViewById(R.id.textviewTenCV);
txthoten.setText(cv.getTenCV());
ImageView imgXoa = viewItem.findViewById(R.id.imageviewXoa);
ImageView imgSua = viewItem.findViewById(R.id.imageviewSua);

//Sự kiện click hình sửa


imgSua.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.activity_sua_cong_viec);
dialog.setCancelable(false);

// Truy xuất các view của activity_sua_cong_viec.xml


TextInputEditText edtSuaCVTen = dialog.
findViewById(R.id.textEditSuaCVTen);
Button btnSuaCVSua = dialog.
findViewById(R.id.buttonSuaCVSua);
Button btnSuaCVHuy = dialog.
findViewById(R.id.buttonSuaCVHuy);

// Hiển thị tên công việc cần cửa lên edtSuaCVTen


edtSuaCVTen.setText(cv.getTenCV());

// Sự kiện click nút Sửa


btnSuaCVSua.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CongViec cvSua = new CongViec(cv.getIdCV(),
edtSuaCVTen.getText().toString());
CongViecDAO congViecDAO = new CongViecDAO(context);
congViecDAO.updateCV(cvSua);
Toast.makeText(context,"Cập nhật thành công",
Toast.LENGTH_LONG).show();
dialog.cancel();

// Gọi hàm onResume() trong MainActivity.java


MainActivity mainActivity = (MainActivity) getContext();
mainActivity.onResume();

}
});
// Sự kiện click của nút Hủy
btnSuaCVHuy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.cancel();
}
});
dialog.show();
}
});
return viewItem;
}
}

55
Bước 10: Xóa Công việc, trong CongViecDAO.java thêm hàm deleteCV()
public void deleteCV(CongViec cv)
{
String sql = "DELETE FROM CongViec WHERE Id = '" + cv.getIdCV() + "' ";
db.execSQL(sql);
}
// hoặc:
public int deleteCV(CongViec cv){
return db.delete("CongViec","id=?", new
String[]{String.valueOf(cv.getIdCV())});
}

Bước 10.1: Trong CongViecAdapter.java


- Click vào imgXoa hiển thị thông báo hỏi có muốn xóa công việc được chọn không.
- Thực hiện xóa công việc và cập nhật vào CSDL.
public class CongViecAdapter extends ArrayAdapter<CongViec> {
private Activity context;
private int resource;
private List<CongViec> objects;
public CongViecAdapter(@NonNull Activity context, int resource,
@NonNull List<CongViec> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.objects = objects;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
View viewItem;
if(convertView == null) {
// Tạo view thông qua inflate
LayoutInflater in = this.context.getLayoutInflater();
viewItem = in.inflate(this.resource,null);
}
else
viewItem = convertView;

// Lấy công việc tại vị trí postion


CongViec cv = getItem(position);

// Truy xuất các view và thay đổi nội dung hiển thị
TextView txthoten = viewItem.findViewById(R.id.textviewTenCV);
txthoten.setText(cv.getTenCV());
ImageView imgXoa = viewItem.findViewById(R.id.imageviewXoa);
ImageView imgSua = viewItem.findViewById(R.id.imageviewSua);

// Sự kiện click hình xóa


imgXoa.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Khởi tạo một AlertDialog.Builder
AlertDialog.Builder dialogXoa = new AlertDialog.
Builder(context);
dialogXoa.setTitle("Thông báo");
dialogXoa.setMessage("Bạn có muốn xóa công việc '" +
cv.getTenCV() + "' ?");
dialogXoa.setCancelable(false);

56
// Tạo button "Có"
dialogXoa.setPositiveButton("Có", new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Thực hiên xóa công việc
CongViecDAO congViecDAO = new CongViecDAO(context);
congViecDAO.deleteCV(cv);
dialog.cancel();

// Gọi hàm onResume() trong MainActivity.java


MainActivity mainActivity = (MainActivity) getContext();
mainActivity.onResume();
}
});

// Tạo button “Không”


dialogXoa.setNegativeButton("Không", new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialogXoa.show();
}
});
return viewItem;
}
}

57

You might also like