Tự động tạo các thành phần cho Class bằng Lombok trong Android Studio

bài trước, Tui có hướng dẫn cách sử dụng Lombok trong Eclipse, bài này Tui tiếp tục sử dụng Lombok trong Android Studio để hướng dẫn các bạn cách tự động tạo các thành phần cho Class.

Ta có 3 bước chính để sử dụng được Lombok trong Android Studio.

Bước 1: Cài đặt Plugin Lombok

Bước 2: Chỉnh dependencies

Bước 3: Viết annotation cho Class.

Bây giờ ta đi vào chi tiết từng bước.

Để cài đặt Plug-in Lombok ta có vài chỗ để cài. Một là từ màn hình Welcome/chọn Configure/ chọn Plugins. Hai là từ Project đang mở sẵn ta vào File > Settings > Plugins

từ màn hình Plugins này ta tìm Lombok để cài.

Hình trên là từ màn hình Welcome ta chọn Configure

Sau đó chọn Plugins, màn hình Plugins hiển thị ra như bên dưới:

Mục tìm kiếm ta gõ “lombok”, sau đó nhìn bên góc phải có nút “Install”, ta nhấn Install để cài đặt:

Sau khi cài đặt xong ta thấy nút ‘”Installed” bị mờ đi như dưới đây:

Nhấn OK để hoàn tất quá trình cài Lombok Plugins

Bây giờ ta tạo một Project tên: TestLombokAndroid (xem các bài về Android Studio 2020 tại đây):

Từ Android Studio/ chọn Create New Project:

Mục Templates chọn Phone and Tablet.

Mục chi tiết bên phải chọn Empty Activity

Nhấn Next để tiếp tục:

Đặt tên dự án: TestLombokAndroid

Các package cho phù hợp

ngôn ngữ Java

Minimum SDK 26

Sau đó nhấn Finish để tạo Project.

Sau đó vào build.gradle (Module):

Bổ sung thư viện Lombok vào dependencies:

dependencies {
compileOnly ‘org.projectlombok:lombok:1.18.16’
annotationProcessor ‘org.projectlombok:lombok:1.18.16’
}

chi tiết:

Tùy vào thời điểm chọn version mà bạn nhập cho đúng, sau đó nhấn “Sync Now

Tiếp theo ta tạo model: tranduythanh.com.model, và tạo một lớp SanPham có cấu trúc như dưới đây:

package tranduythanh.com.model;

public class SanPham {
private int ma;
private String ten;
private int soLuong;
private double donGia;
}

Ở trên, ta chỉ cần khai báo các thuộc tính mà thôi. Tiếp theo ta dùng các cú pháp của Lombok để setup cho lớp SanPham:

Mã lệnh:

package tranduythanh.com.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class SanPham {
private int ma;
private String ten;
private int soLuong;
private double donGia;
}

Ở trên ta thấy:

@AllArgsConstructor tự động tạo ra constructor đầy đủ đổi số.

@NoArgsConstructor tự động tạo ra constructor mặc định

@Data tự động tạo mọi getter/setter cho class

Bây giờ trong giao diện của Android, ta tiết kế 4 EditText, 1 Button để thử nghiệm class SanPham:

Code XML của activity_main.xml như sau:

Ta gán sự kiện cho Button “Thực hiện”:

chi tiết lệnh cho thucHienLombok:

package tranduythanh.com.testlombokandroid;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import tranduythanh.com.model.SanPham;

public class MainActivity extends AppCompatActivity {

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

public void thucHienLombok(View view) {
EditText edtMa=findViewById(R.id.edtMa);
EditText edtTen=findViewById(R.id.edtTen);
EditText edtSoLuong=findViewById(R.id.edtSoLuong);
EditText edtDonGia=findViewById(R.id.edtDonGia);

SanPham sp1=new SanPham(
Integer.parseInt(edtMa.getText().toString()),
edtTen.getText().toString(),
Integer.parseInt(edtSoLuong.getText().toString()),
Double.parseDouble(edtDonGia.getText().toString()));

Toast.makeText(this,sp1.toString(),Toast.LENGTH_LONG).show();
}
}

Chạy phần mềm lên ta có:

Ví dụ code ở trên dùng constructor đầy đủ đối số. Ta cũng có thể sử dụng Constructor mặc định và gọi các getter/setter:

SanPham sp1=new SanPham();
sp1.setMa(Integer.parseInt(edtMa.getText().toString()));
sp1.setTen(edtTen.getText().toString());
sp1.setSoLuong(Integer.parseInt(edtSoLuong.getText().toString()));
sp1.setDonGia(Double.parseDouble(edtDonGia.getText().toString()));
String info=”Mã=”+sp1.getMa()+”\n”+
“Tên=”+sp1.getTen()+”\n”+
“Số lượng=”+sp1.getSoLuong()+”\n”+
“Đơn giá=”+sp1.getDonGia();
Toast.makeText(this,info,Toast.LENGTH_LONG).show();

Chạy lên ta cũng có kết quả như mong muốn.

Đây là source code của bài này: https://www.mediafire.com/file/v8oqdvoqa0fmx70/TestLombokAndroid.rar/file

Chúc các bạn thành công!

Bài 14. TextView, EditText, Button trong Android phần 2

Như vậy ở bài 13 Tui đã hướng dẫn các bạn lý thuyết về bộ 3 nguy hiểm TextView, EditText, Button. Bài này Tui sẽ ứng dụng nó để làm 1 tiện ích nho nhỏ đó là “Đọc số tiền bằng chữ”. Ví dụ khi người dùng nhập vào số tiền “8767543” -> “Tám triệu bảy trăm sáu mươi bảy nghìn năm trăm bốn mươi ba”

Tạo một dự án tên “DocTienBangChu”, thiết kế giao diện như hình dưới đây:

XML Layout code như sau:

[code language=”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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:background="#fff120"
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Nhập số tiền bằng Số:" />

<EditText
android:id="@+id/editNumberOfMoney"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />

<Button
android:id="@+id/btnDocTien"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Đọc Tiền" />

<TextView
android:id="@+id/txtTextOfMoney"
android:layout_width="match_parent"
android:layout_height="151dp"
android:background="#fff120"
android:text="" />
</LinearLayout>
[/code]

Tiến hành cấu hình ViewBinding cho dự án, bạn nào chưa học bài ViewBinding thì xem lại bài 12.

Tiếp theo bấm chuột phải vào java/chọn new/ chọn package:

Màn hình Choose Destination Directory xuất hiện như dưới đây:

Chọn app\src\main\java

Rồi bấm OK:

Nhập package name là: tranduythanh.com.utils rồi nhấn Enter.

Ta thấy package utils xuất hiện ra như trên. Bây giờ tạo thư viện để đọc Tiền bằng số ra chữ (trên mạng có nhiều, thích tham khảo ở đâu cũng được, miễn là nó chạy đúng, ví dụ có thể tham khảo tại đây, mã nguồn bên dưới Tui cũng tham chiếu từ link đó cho các bạn dễ đọc):

Sau đó tạo một lớp tên là MoneyConverter:

Đặt tên xong thì double click vào Class, ta thấy kết quả như dưới đây:

Bây giờ tiến hành coding để đọc 1 số tiền bằng số ra chữ. Dĩ nhiên ta không phải học kỹ thuật đọc chữ thế nào, mà ta chỉ ứng dụng nó để làm việc với TextView , EditText, Button nên Tui sẽ bỏ qua bước giải thích thuật toán này (chi tiết bạn xem tại link ).

Dưới đây là coding MoneyConverter mà Tui có cấu trúc lại chút đỉnh:

[code language=”java”]
package tranduythanh.com.utils;
import java.util.ArrayList;
import java.util.Arrays;
public class MoneyConverter {
private static final String KHONG = "không";
private static final String MOT = "một";
private static final String HAI = "hai";
private static final String BA = "ba";
private static final String BON = "bốn";
private static final String NAM = "năm";
private static final String SAU = "sáu";
private static final String BAY = "bảy";
private static final String TAM = "tám";
private static final String CHIN = "chín";
private static final String LAM = "lăm";
private static final String LE = "lẻ";
private static final String MUOI = "mươi";
private static final String MUOIF = "mười";
private static final String MOTS = "mốt";
private static final String TRAM = "trăm";
private static final String NGHIN = "nghìn";
private static final String TRIEU = "triệu";
private static final String TY = "tỷ";
private static final String [] number = {KHONG, MOT, HAI, BA,
BON, NAM, SAU, BAY, TAM, CHIN};
public static String TextOfMoney(String numberOfMoney)
{
ArrayList<String> kq = new ArrayList<String>();
//Cắt chuổi string chử số ra thành các chuổi nhỏ 3 chử số
ArrayList<String> List_Num = Split(numberOfMoney, 3);
while (List_Num.size() != 0)
{
//Xét 3 số đầu tiên của chuổi (số đầu tiên của List_Num)
switch (List_Num.size() % 3)
{
//3 số đó thuộc hàng trăm
case 1:
kq.addAll(read_3num(List_Num.get(0)));
break;
// 3 số đó thuộc hàng nghìn
case 2:
ArrayList<String> nghin = read_3num(List_Num.get(0));
if(!nghin.isEmpty()){
kq.addAll(nghin);
kq.add(NGHIN);
}
break;
//3 số đó thuộc hàng triệu
case 0:
ArrayList<String> trieu = read_3num(List_Num.get(0));
if(!trieu.isEmpty()) {
kq.addAll(trieu);
kq.add(TRIEU);
}
break;
}
//Xét nếu 3 số đó thuộc hàng tỷ
if (List_Num.size() == (List_Num.size() / 3) * 3 + 1 && List_Num.size() != 1) kq.add(TY);
//Xóa 3 số đầu tiên để tiếp tục 3 số kế
List_Num.remove(0);
}
String textResult=String.join(" ",kq);
return textResult;
}
//Đọc 3 số
private static ArrayList<String> read_3num(String a)
{
ArrayList<String> kq = new ArrayList<String>();
int num = -1;
try{ num = Integer.parseInt(a); } catch(Exception ex){}
if (num == 0) return kq;

int hang_tram = -1;
try{ hang_tram = Integer.parseInt(a.substring(0, 1)); } catch(Exception ex){}
int hang_chuc = -1;
try{ hang_chuc = Integer.parseInt(a.substring(1, 2)); } catch(Exception ex){}
int hang_dv = -1;
try{ hang_dv = Integer.parseInt(a.substring(2, 3)); } catch(Exception ex){}
//xét hàng trăm
if (hang_tram != -1){
kq.add(number[hang_tram]);
kq.add(TRAM);
}
//xét hàng chục
switch (hang_chuc)
{
case -1:
break;
case 1:
kq.add(MUOIF);
break;
case 0:
if (hang_dv != 0) kq.add(LE);
break;
default:
kq.add(number[hang_chuc]);
kq.add(MUOI);
break;
}
//xét hàng đơn vị
switch (hang_dv)
{
case -1:
break;
case 1:
if ((hang_chuc != 0) && (hang_chuc != 1) && (hang_chuc != -1))
kq.add(MOTS);
else kq.add(number[hang_dv]);
break;
case 5:
if ((hang_chuc != 0) && (hang_chuc != -1))
kq.add(LAM);
else kq.add(number[hang_dv]);
break;
case 0:
if (kq.isEmpty()) kq.add(number[hang_dv]);
break;
default:
kq.add(number[hang_dv]);
break;
}
return kq;
}
private static ArrayList<String> Split(String str, int chunkSize) {
int du = str.length() % chunkSize;
//Nếu độ dài chuổi không phải bội số của chunkSize thì thêm # vào trước cho đủ.
if (du != 0)
for (int i = 0; i < (chunkSize – du); i++) str = "#" + str;
return splitStringEvery(str, chunkSize);
}
//Hàm cắt chuổi ra thành chuổi nhỏ
private static ArrayList<String> splitStringEvery(String s, int interval) {
ArrayList<String> arrList = new ArrayList<String>();
int arrayLength = (int) Math.ceil(((s.length() / (double) interval)));
String[] result = new String[arrayLength];
int j = 0;
int lastIndex = result.length – 1;
for (int i = 0; i < lastIndex; i++) {
result[i] = s.substring(j, j + interval);
j += interval;
}
result[lastIndex] = s.substring(j);
arrList.addAll(Arrays.asList(result));
return arrList;
}
}
[/code]

Bây giờ ta vào MainActivity để xử lý:

[code language=”java”]
package tranduythanh.com.doctienbangchu;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;

import tranduythanh.com.doctienbangchu.databinding.ActivityMainBinding;
import tranduythanh.com.utils.MoneyConverter;

public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding=ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
adEvents();
}
private void adEvents() {
binding.btnDocTien.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String docTien= MoneyConverter.TextOfMoney(binding.editNumberOfMoney.getText().toString());
binding.txtTextOfMoney.setText(docTien);
}
});
}
}
[/code]

Chạy lên ta có kết quả:

 

Như vậy Tui đã hướng dẫn xong bài ứng dụng TextView, EditText, Button để làm tiện ích đọc tiền bằng số ra chữ.

Ở bài này Ta ôn tập lại cách thức sử dụng 3 control cơ bản ở trên, sử dụng lại ViewBinding để truy suất tới các biến control trên giao diện cũng như gán sự kiện cho nó

Bạn có thể tải code mẫu ở đây: https://gitlab.com/duythanhcse/DocTienBangChu/

Bài học sau Tui sẽ hướng dẫn các bạn các kỹ thuật xử lý trên CheckBox, RadioButton

Các bạn chú ý theo dõi nhé

Chúc các bạn thành công.

Bài 13. TextView, EditText, Button trong Android phần 1

Android cung cấp rất nhiều View/Control để ta có thể tùy chọn thiết kế giao diện tương tác người dùng. TextView dùng để hiển thị dữ liệu, EditText để hiển thị và cho phép thay đổi thông tin, Button để ra lệnh, CheckBox để chọn nhiều lựa chọn, RadioButton để chọn một lựa chọn, ImagView để hiển thị hình ảnh…

Trong bài này Tui sẽ trình bày về 3 View cơ bản nhất, mà bất kỳ một phần mềm cùi bắp nào cũng có đó là: TextView, EditText và Button.

13.1 TextView

TextView là view dùng để chỉ hiển thị dữ liệu không cho phép người sử dụng thay đổi dữ liệu. TextView thuộc nhóm Common và Text trong công cụ Palette:

Ta có thể kéo thả các View vào giao diện thiết kế một cách dễ dàng.

Bảng 13.1. Các thuộc tính/sự kiện quan trọng của TextView

Các thuộc tính/sự kiện Mô tả
android:id Id của TextView
android:layout_width Độ rộng
android:layout_height Độ cao
android:text Chữ hiển thị lên giao diện
android:textColor Màu chữ
android:textSize Cỡ chữ
android:background Màu nền
android:hint Chữ gợi ý khi android:text rỗng

Để truy suất TextView ta cần đặt Id cho nó trong thanh công cụ Properties hoặc trong XML. Hàm findViewById đã được giới thiệu trước đó dùng để truy suất View (Hoặc dùng ViewBinding được trình bày trong bài 12):

TextView txtMessage=findViewById(R.id.txtMessage);

Để thiết lập nội dung hiển thị ta có hai cách:

  • Trong Java code (Activity):

txtMessage.setText(“ Thầy Trần Duy Thanh ”);

  • Trong XML:

android:text=“ Thầy Trần Duy Thanh ”

[code language=”xml”]
<TextView
android:id="@+id/txtMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_light"
android:textColor="@android:color/holo_blue_light"
android:text="Khoa Hệ Thống Thông Tin"
android:textSize="30sp"
/>
[/code]

Ngoài id, text thì TextView còn có các thuộc tính quan trọng khác như: layout_width(thiết lập độ rộng), layout_height(thiết lập chiều cao), background(màu nền), textColor(màu chữ), textSize(cỡ chữ). Các thuộc tính cho TextView rất nhiều và được cung cấp sẵn trong công cụ Properties ta có thể vào đây để thao tác.

13.2 EditText

EditText là lớp kế thừa từ TextView, được dùng thay đổi nội dung text, chứa tất cả thuộc tính của TextView nên TextView hoạt động như thế nào thì EditText hoạt động như vậy, nằm trong nhóm Text của Palette. Đặt Id nên bắt đầu là là edt hoặc txt

Android đã tự động phân EditText thành nhiều loại khác nhau: Nhập chuỗi, số, điện thoại, email, mật khẩu … dựa vào thuộc tính inputType. Nhờ thuộc tính inputType mà trải nghiệm người dùng được tốt hơn, điện thoại sẽ hiển thị bàn phím tương ứng với inputType mà ta cấu hình giúp người dùng thao tác một cách dễ dàng và nhanh chóng:

EditText có nhiều thuộc tính quan trọng ta cần quan tâm:

Bảng 13.2. Các thuộc tính/sự kiện quan trọng của EditText

Các thuộc tính/sự kiện Mô tả
android:id Id của EditText
android:layout_width Độ rộng
android:layout_height Độ cao
android:text Chữ hiển thị lên giao diện
android:textColor Màu chữ
android:textSize Cỡ chữ
android:background Màu nền
android:hint Chữ gợi ý khi android:text rỗng
android:inputType Thiết lập loại dữ liệu nhập để có bàn phím phù hợp

Ta thấy trong nhóm Text rất nhiều View (EditText), tùy vào nhu cầu sử dụng mà ta kéo thả các EditText phù hợp ra.

Cấu trúc XML của Edittext:

[code language=”xml”]
<EditText
android:id="@+id/edtPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="1"
android:textColor="@android:color/holo_blue_light"
android:inputType="textPassword"
android:text="hoilamgi"

/>

[/code]

Thuộc tính inPutType= “textPassword” giúp ta khi nhập dữ liệu vào thì phần mềm tự động mã hóa thành các ký tự * để bảo mật. Edittext ngoài ra còn sử dụng Hint để nhắc nhớ người dùng, ta có thể bổ sung android:hint = “nhập mật khẩu ở đây”, người dùng sẽ biết ô này dùng để làm gì.

Để truy suất ta cũng dùng hàm findViewById (Hoặc dùng ViewBinding được trình bày trong bài 12):

EditText edtPassword=findViewById(R.id.edtPassword);

Để thay đổi nội dung hiển thị ta dùng: edtPassword.setText(“obama”)

Để lấy nội dung người dùng nhập liệu: edtPassword.getText().toString()

13.3. Button

Đối tượng Button được xây dựng từ TextView, cho phép thể hiện các nội dung văn bản, hình ảnh – nhận và phản hồi tương tác nhấn từ người dùng. Nên đặt Id cho Button bắt đầu bằng btn

Button thuộc nhóm Buttons hoặc Common trong công cụ Palette:

Các thuộc tính trong Button tương tự như trong TextView và EditText

Bảng 13.3. Các thuộc tính/sự kiện quan trọng của Button

Các thuộc tính/sự kiện Mô tả
android:id Id của EditText
android:layout_width Độ rộng
android:layout_height Độ cao
android:text Chữ hiển thị lên giao diện
android:textColor Màu chữ
android:textSize Cỡ chữ
android:background Màu nền
android:onClick Gán sự kiện cho Button

Cấu trúc XML của Button:

[code language=”xml”]
<Button
android:id="@+id/btnDangNhap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Đăng Nhập"
/>

[/code]

Button thường dùng để cho phép người dùng ra lệnh thực thi một nghiệp vụ nào đó, sự ra lệnh này gọi là các sự kiện (event). Button ngoài hiển thị dữ liệu còn có nhiệm vụ lắng nghe các sự kiện người dùng, hai cách nhanh nhất để lắng nghe sự kiện:

  • Lắng nghe trong XML: android:onClick=“tenPhuongThuc”
  • Lắng nghe trong java code:

btnDangNhap.setOnCLickListener(new OnClickLisntener() {

@Override

public void onClick(View v) {

xuLyDangNhap();

}

});

Chi tiết các kỹ thuật xử lý sự kiện sẽ được trình bày ở các bài sau.

Như vậy Tui đã trình bày xong phần lý thuyết của TextView, EditText và Button. Bài sau Tui sẽ làm một ví dụ cụ thể về ứng dụng của 3 Control này, dĩ nhiên Tui sẽ dùng kỹ thuật mới là ViewBinding để tương tác với các control trên giao diện, còn bạn nào  muốn dùng findViewById thì có thể xem tại đây).

Các bạn chú ý theo dõi nhé

Chúc các bạn thành công.

Bài 12. ViewBinding trong Android

Như vậy ở bài 11 các bạn đã biết cách dùng findViewById để truy suất tới các control trên giao diện, tuy nhiên nó làm mất khá nhiều thanh xuân của lập trình viên, phải lặp đi lặp lại thao tác findViewById. Đặc biệt nó cũng khó tiếp cận cho những lập trình viên nhảy từ .Net qua.

Android Studio trong các phiên bản mới gần đây đã hỗ trợ ViewBinding để giúp chúng ta dễ dàng truy suất tới các control trên giao diện.

Bây giờ các bạn tạo một dự án tên “HocViewBinding“, sau đó vào file build.gradle (module:HocViewBinding.app):

Ở trên các bạn thấy nhóm android{}, xuống dưới cùng (thực ra chỗ nào cũng được) trong nhóm android{} ngày đằng sau compileOptions{}, bổ sung thêm lệnh:

[code language=”java”]
buildFeatures{
viewBinding=true
}
[/code]

Nếu bạn dùng Android version cũ hơn Tui đang sử dụng thì thay lệnh trên bằng:

[code language=”java”]
viewBinding {
enabled = true
}
[/code]

chi tiết bao gồm cả android {}:

[code language=”java”]
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "tranduythanh.com.hocviewbinding"
minSdkVersion 26
targetSdkVersion 29
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android-optimize.txt’), ‘proguard-rules.pro’
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
buildFeatures{
viewBinding=true
}
}
[/code]

Sau đó nhớ nhấn Sync Now:

Sau khi Sync Now thành công thì tất cả các Layout (layout xml) trong dự án Android Studio sẽ được phát sinh ra một lớp, tương với tên Layout XML + Binding

Ví dụ: Ta vào thư mục “layout“, trong thư mục này có “activity_main.xml” thì nó sẽ tự động phát sinh ra một lớp tên là “ActivityMainBinding“, tương tự như vậy nếu ta có 1 layout khác tên là “activity_login.xml” thì nó cũng sẽ tự phát sinh thêm một lớp tên là “ActivityLoginBinding“:

Từ lớp binding này ta có thể cấu hình để có thể truy suất trực tiếp vào control trên giao diện mà không cần thông qua hàm findViewById.

Android cũng hỗ trợ cho phép ta cấu hình từ chối binding cho các layout, ví dụ có một layout nào đó mà bạn không muốn dùng binding thì thêm thuộc tính sau cho nó:

[code language=”xml”]

<LinearLayout

tools:viewBindingIgnore="true" >

</LinearLayout>

[/code]

Bây giờ ta sẽ vào phần xử lý mã nguồn để khai báo các biến sử dụng ViewBinding:

Đây là màn hình coding gốc ban đầu của MainActivity:

[code language=”java”]
package tranduythanh.com.hocviewbinding;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
[/code]

Ta viết mã lệnh để truy suất trực tiếp các control trên giao diện thông qua binding:

[code language=”java”]
package tranduythanh.com.hocviewbinding;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import tranduythanh.com.hocviewbinding.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
//khai báo biến binding có kiểu tương ứng với lớp được tạo ra từ layout của màn hình
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//gọi hàm inflate
binding=ActivityMainBinding.inflate(getLayoutInflater());
//thay thế đối số truyền vào cho setContentView bằng binding.getRoot()
setContentView(binding.getRoot());
}
}
[/code]

Tới đây, để truy suất tới bất kỳ biến control nào trên giao diện ta sẽ thông qua đối tượng binding. Bất cứ khi nào ta kéo thả control/view vào giao diện, đặt id cho control/view thì chỉ cần lấy {binding}.{id của control}.

Ví dụ giờ ta chỉnh sửa layout ta kéo một Button và 1 TextView vào giao diện (activity_main.xml) như sau:

code XML:

[code language=”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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btnClickMe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click Me" />
<TextView
android:background="#FF0F1F"
android:id="@+id/txtMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
[/code]

Bạn thấy Button Tui đặt id là “btnClickMe“, TextView Tui đặt là “txtMessage“.

Bây giờ quay lại màn hình mã lệnh, thêm hàm addEvents() để xử lý như sau:

[code language=”java”]
package tranduythanh.com.hocviewbinding;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import tranduythanh.com.hocviewbinding.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
//khai báo biến binding có kiểu tương ứng với lớp được tạo ra từ layout của màn hình
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//gọi hàm inflate
binding=ActivityMainBinding.inflate(getLayoutInflater());
//thay thế đối số truyền vào cho setContentView bằng binding.getRoot()
setContentView(binding.getRoot());
addEvents();
}
private void addEvents() {

}
}
[/code]

bạn không tạo hàm addEvents() cũng được, ở đây Tui tạo ra để cho các bạn làm quen, sau này các Project ở các bài học tiếp theo sẽ làm giống vầy, lý do là khi ta làm Project sẽ có rất nhiều control trên giao diện cũng như nhiều xử lý khác, do đó tốt nhất ta nên tách hàm ra để dễ quản lý, và tìm lỗi.

trong hàm addEvents() này ta sẽ thử tiến hành dùng binding để truy suất tới các control như sau nhé:

[code language=”java”]
private void addEvents() {
//truy suất trực tiếp tới biến btnClickMe để gán sự kiện nhấn vào Button:
binding.btnClickMe.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//truy suất trực tiếp vào biến txtMessage để hiển thị chuỗi dữ liệu:
binding.txtMessage.setText("chào Thầy Trần Duy Thanh");
}
});
}
[/code]

Bạn thấy đấy, ở trên Tui không hề dùng findViewById nào cả, Tui dùng biến binding truy suất trực tiếp tới các biến control trên giao diện.

Chạy phần mềm lên ta có kết quả như bình thường:

Như vậy Tui đã hướng dẫn xong bài ViewBinding, tới đây bạn đã có được 2 kỹ thuật truy suất tới các biến control trên giao diện, bạn thích dùng kỹ thuật nào cũng được.

Coding bạn có thể tải ở đây:

https://drive.google.com/open?id=1o-ZDy0AQDG2_lr2bh8lbYOMa7q27sacZ

Các bài sau Tui sẽ trình bày về các control cơ bản như TextView, EditText, Button

Các bạn chú ý theo dõi nhé.

Chúc các bạn thành công.

Bài 11. findViewById trong Android

Trong Android, để truy suất tới các control bất kỳ ta có nhiều cách: Ta có thể dùng findViewById hoặc dùng ViewBinding.

Trong bài này Tui sẽ trình bày về kỹ thuật dùng findViewById, bài sau sẽ nói về ViewBinding.

Khi lập trình Android, để tương tác với các View/Control trong giao diện chúng ta thường thông qua thuộc tính Id của các view/control để truy suất thay đổi dữ liệu. Vì Android chia màn hình (Activity) thành hai phần: Phần thiết giao diện, phần xử lý nghiệp vụ. Do đó để truy suất được tới các View trong phần giao diện Android cung cấp hàm findViewById (Tạm thời nó sẽ không quen thuộc với những ai đi từ .Net dev qua, ở bài sau học ViewBinding các bạn sẽ thấy dễ chịu hơn):

Ta chú ý mỗi lần đặt Id cho bất kỳ một View nào đó thì Id này sẽ tự động được phát sinh ra trong lớp R của Android. Vì vậy khi truy suất tới View ta dùng R.id.idView.

Phiên bản cũ phải ép kiểu (ở trên thấy (Button)findViewById)

Phiên bản mới hơn 1 chút không cần ép kiểu

Phiên bản mới ta có thể dùng ViewBinding thay thế cho findViewById.

Ví dụ:

Tạo một dự án tên là “HocFindViewById” có giao diện như sau (cách tạo xem tại đây):

Cod XML layout như dưới đây:

[code language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="21dp"
android:background="#FFEB3B"
android:text="Mời bạn nhập số phone:"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<EditText
android:id="@+id/edtPhoneNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="phone"
android:text="0987773061"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:layout_editor_absoluteX="74dp" />

<Button
android:id="@+id/btnCall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gọi điện"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edtPhoneNumber" />
</androidx.constraintlayout.widget.ConstraintLayout>

[/code]

ở trên View/Control Edittext (để nhập liệu) ta đặt id là “edtPhoneNumber”, code bên dưới sẽ truy suất vào control Edittext dựa vào id này.

Bây giờ ta  bổ sung sự kiện cho nut Gọi điện, thêm thuộc tính android:conClick, đặt tên hàm bên trong:

Ví dụ ta đặt tên hàm là xuLyGoiDien, lúc này nó sẽ báo lỗi vì chưa được khai báo trong Java code, giờ ta làm cho nó tự động phát sinh mã lệnh như sau: Click chuột vào hàm, nó xổ ra cái bóng đèn, nhấn vào bóng đèn chọn -> Create ‘xuLyGoiDien(View)’ in ‘MainActivity’ (Hoặc bạn cũng có thể nhấn tổ hợp phím Alt+ Enter)

Lúc này MainActivity sẽ phát sinh ra một hàm xuLyGoiDien như dưới đây:

[code language=”java”]
package tranduythanh.com.hocfindviewbyid;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

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

public void xuLyGoiDien(View view) {

}

}
[/code]

Bây giờ ta bổ sung mã lệnh cho hàm xuLyGoiDien:

[code language=”java”]
public void xuLyGoiDien(View view) {
//lệnh findViewById để truy suất tới control có id tương ứng truyền vào:
EditText edtPhone=findViewById(R.id.edtPhoneNumber);
//Lấy số phone ra:
String phoneNumber=edtPhone.getText().toString();
//Khai báo Intent để quay số gọi điện thoại
Intent intent=new Intent(Intent.ACTION_DIAL);
//Cú pháp gọi điện thoại
Uri uri=Uri.parse("tel:"+phoneNumber);
//gán uri cho intent:
intent.setData(uri);
//Gọi chức năng gọi điện thoại
startActivity(intent);
}
[/code]

Ở trên là hàm findViewById để truy suất vào control theo đúng id tương ứng truyền vào trong hàm. Với Android, mỗi lần 1 control được kéo thả vào màn hình, nó sẽ có 1 id, ta có thể sửa lại id hoặc đặt id mới. Thì Id này sẽ tự động được lưu trong file R (R là file tự động).

Android version mới không cần phải ép kiểu, nó tự tìm ra đúng kiểu control.

Chạy phần mềm lên ta được:

Như vậy Tui đã trình bày xong kỹ thuật dùng findViewById để truy suất tới các biến control trên giao diện, nó áp dụng cho mọi control nhé (Android họ thường gọi control là View).

coding tải ở đây: https://drive.google.com/open?id=1ADI-5lsDMgdnFjiNupIrPcoFbJszSjtO

Ở bài sau Tui sẽ hướng dẫn các bạn kỹ thuật dùng ViewBinding để truy suất trực tiếp vào các control mà không cần thông qua findViewById, giúp tiết kiệm thời gian hơn cho lập trình viên, cũng như làm quen thuộc hơn cho những ai đi từ .Net dev qua.

Các bạn chú ý làm lại bài này trước nhé, phải hiểu cơ chế hoạt động của nó, biết nhiều kỹ thuật để trong mọi trường hợp ta có thể áp dụng được các kỹ thuật khác nhau.

Các bạn chú ý theo dõi nhé

Chúc các bạn thành công

Bài 10. Các Layout trong Android

Layout là nơi để tổ chức sắp xếp control/View trên giao diện và thường được sử dụng đầu tiên khi ta thiết kế giao diện. Các Layout này được Android Studio bố trí trong Palette/Layouts:

Trong bài này Tui sẽ trình bày về các layout:
10.1. ConstraintLayout
10.2. Frame Layout 
10.3. Linear Layout
10.4. Table Layout
10.5. Relative layout 

Dưới đây là các kiến thức chi tiết:

10.1. ConstraintLayout

Constraint layout dùng để định vị trí tương đối của Một control/View trên màn hình với các phần tử khác trong layout:

Ta có thể xác định một constraint cho một hay nhiều mặt của một view bằng chế độ kết nối bất kỳ sau đây :

  • Điểm neo nằm trên một View khác.
  • Một cạnh của layout.
  • Một guideline.

Android cung cấp các loại Constraint sau: Relative positioning, Margins,Centering positioning,Visibility behavior,Dimension constraints,Chains. Layout này được áp dụng để thiết kế các màn hình Responsive không lệ thuộc vào độ phân giải.

Cấu trúc XML của ConstraintLayout được mô tả như sau:

[code language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
[/code]

Android Studio còn cung cấp chức năng chuyển đổi từ ConstraintLayout qua các layout khác(và ngược lại), bằng cách bấm chuột phải vào Layout bất kỳ/chọn Convert View ==>Chọn layout đích mà ta muốn chuyển đổi:

Với Sinh Viên mới học thì nên chọn LinearLayout, sau khi chọn LinearLayout:

LineLayout lại vừa có Horizontal và Vertical, ta có thể bấm chuột phải vào nó để đổi tiếp:

10.2. Frame Layout 

Sử dụng trong các trường hợp xây dựng bố cục tổ chức hiển thị một đối tượng duy nhất. Đối tượng mặc định vị trí top-left trên FrameLayout, View khai báo sau sẽ chồng nên View khai báo trước, có thể sử dụng thuộc tính Gravity để thiết lập lại vị trí.

[code language=”xml”]
<FrameLayout android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/h0"
android:id="@+id/imageView3"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/h1"
android:id="@+id/imageView4" />
</FrameLayout>
[/code]

Ta thấy hình h1 khai báo sau nên h1 sẽ chồng nên h0, cả hai hình này đều được neo ở góc top-left của màn hình: FrameLayout được sử dụng rất nhiều trong Tabhost

10.3. Linear Layout

Sử dụng trong các trường hợp xây dựng bố cục tổ chức hiển thị các đối tượng theo một chiều duy nhất (chiều dọc-vertical hoặc ngang-horizontal).
Đối tượng mặc định vị trí top left trên LinearLayout , có thể sử dụng thuộc tính Gravity để thiết lập lại vị trí.

[code language=”xml”]

<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout1"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

[/code]

Ta thay đổi chiều dọc (android:orientation= “vertical”), chiều ngang (android:orientation= “horizontal”) các View sẽ tự động sắp xếp:

LinearLayout hỗ trợ thuộc tính text android:gravity để căn chỉnh chữ trong View, android:layout_gravity để căn chỉnh vị trí tương đối của View trong layout.

Ngoài ra LinearLayout còn hỗ trợ nhiều thuộc tính khác như android:padding để tăng độ dày của View, android:layout_margin để tăng/giảm khoảng cách giữa các View.

10.4. Table Layout

TableLayout kế thừa từ LinearLayout, cho phép hiển thị các đối tượng theo nhiều dòng (TableRow). Mỗi dòng có thể chứa nhiều View, mỗi View được xem là một cột. Đặc biệt TableLayout lấy dòng có số lượng View nhiều nhất làm số cột, tức là nếu TableLayout có 3 dòng: dòng đầu tiên có 2 View, dòng thứ hai có 5 View và dòng cuối cùng có 4 View thì cột được xác định cho TableLayout này là 5.

TableLayout cho phép ta Meger(trộn) các ô trong TableRow bằng cách thiết lập thuộc tính layout_span cho View trong TableRow:

Hay layout_column để di chuyển vị trí của View tới một cột nào đó trong TableRow:

Dùng stretchColumns để dãn đều các control, các cell (ta thường dùng dấu “*” để cấu hình cho toàn bộ các cột, hoặc nhập số để cấu hình cho cột được chỉ định):

[code language=”xml”]

<TableLayout
android:stretchColumns="*"
android:layout_width="match_parent"
android:layout_height="match_parent">

[/code]

10.5. Relative layout 

RelativeLayout cho phép sắp xếp các View theo vị trí tương đối giữa các View khác trên giao diện (kể cả View chứa nó). Thường nó dựa vào Id của các View khác để sắp xếp theo vị trí tương đối. Do đó khi làm RelativeLayout ta phải chú ý là đặt Id của View cho chuẩn xác, nếu sau khi Layout xong mà ta lại đổi Id của các View thì giao diện sẽ bị xáo trộn (do đó nếu đổi ID thì phải đổi luôn các tham chiếu khác sao cho khớp với Id mà ta mới đổi).

Trên giao diện lúc kéo thả các View trên RelativeLayout ta tự căn chỉnh, lúc này các View sẽ tự động sắp xếp theo cách ta kéo thả trên màn hình.

Như vậy là Tui đã trình bày xong một số layout thường dùng trong Android. Việc nắm rõ cách thức hoạt động của layout rất quan trọng, trước khi thiết kế một giao diện, điều đầu tiên là phải nghĩ tới layout trước. Nó giống như khi chúng ta xây dựng một căn nhà, thì phải có bản vẽ kỹ thuật trước vậy.

Các bạn nhớ đọc kỹ lại nhé để hiểu rõ các layout

Bài học sau Tui sẽ trình bày về findViewById và ViewBinding. Một trong những kỹ thuật để truy suất tới các control trên giao diện. Nó rất quan trọng, các bạn chú ý theo dõi nhé

Chúc các bạn thành công!