Trang chủ » Tái sử dụng layout với include và merge trong Android
Lập trình Android

Tái sử dụng layout với include và merge trong Android

Mặc dù Android có rất nhiều Widgets, cũng như các Components cho phép ta làm việc rất hiệu quả, tuy nhiên với những cụm components như 1 layout có ImageView và TextView hiển thị dưới dạng list chẳng hạn, thì ta phải sử dụng thẻ include và merge để tái sử dụng layout mà mình muốn.

Xin chào mọi người! Đã lâu lắm rồi mình mới có dịp viết lại blog (giờ có phân bua giải thích gì thì mọi người cũng nghĩ là mình lười thôi, mà sự thật là mình cũng lười :v). Nhân dịp mình viết lại blog, mình xin mở thêm 1 chuyên mục mới trong chuỗi các Ngôn ngữ lập trình, đó là Lập trình Android. Ở các bài viết về Android, mình sẽ sử dụng Xamarin và ngôn ngữ C# để viết thay vì dùng Java (đơn giản vì mình thích thế :v), các bạn cũng có thể viết lại bằng Java, thật ra không khác gì nhiều lắm. Và mình sẽ cố gắng tìm hiểu cũng như cập nhật các mẹo và thủ thuật hay trong Android để tăng chất lượng bài viết hơn.

include
Anh em ta là một gia đình, một gia đình là code hết mình! Ồ de!

Từ đó giờ, việc include quả không quá xa lạ với mọi lập trình viên chúng ta, nó cho phép bạn tái sử dụng một số đoạn code được lặp đi lặp lại trong 1 project nào đó. Và trong Android cũng vậy, với thẻ <include/> chúng ta có thể sử dụng 1 cụm các Widgets như là 1 TextView kèm theo 1 EditText chẳng hạn:

include example

Sử dụng thẻ include

Việc tạo ra 1 include layout thật ra cũng rất đơn giản, nó giống như việc ta đang copy-và-paste 1 đống code từ 1 file bên ngoài vào trong file cần include. Ở đây mình tạo ra 1 file tên layout/include_fieldname.axml (.axml là 1 phần mở rộng trong Xamarin, tương tự như .xml trong Android) như sau:

<xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Field:" />
    <EditText 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" />
</LinearLayout>

Và trong file layout/Main.axml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    <TextView 
        android:text="Include và Merge trong Android" 
        android:textAppearance="?android:attr/textAppearanceLarge" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:paddingBottom="40dp" 
        android:gravity="center" />
    <include 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        layout="@layout/include_fieldname" />
    <include 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        layout="@layout/include_fieldname" />
    <include 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        layout="@layout/include_fieldname" />
</LinearLayout>
ví dụ về include
Kết quả sau khi chạy thành công…

Sử dụng thẻ merge

Giả sử trong 1 project, ta muốn layout của mình sẽ hiển thị như thế này:

ví dụ về include

Tất nhiên với cách Include cũ, ta không thể tạo ra 1 layout như thế này được vì trong file layout/include_fieldname.axml có 1 ViewGroup root là LinearLayout dạng vertical. Về lý thuyết ta cũng không thể bỏ ViewGroup root này được vì có 2 Widgets con, nên ta cần phải bao chúng trong 1 element cha. Vậy thì làm cách nào để có thể hiển thị các include components trong các layouts khác nhau? Lúc này <merge/> thật sự là 1 vị cứu tinh. Ở trong file layout/include_fieldname.axml ta chỉnh lại như sau:

<?xml version="1.0" encoding="utf-8"?>
<merge 
    xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Field:" />
    <EditText 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" />
</merge>

Và trong file layout/Main.axml, ta chỉnh lại:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    <TextView 
        android:text="Include và Merge trong Android" 
        android:textAppearance="?android:attr/textAppearanceLarge" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:paddingBottom="40dp" 
        android:gravity="center" />
    <LinearLayout 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:orientation="horizontal">
        <include 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content" 
            layout="@layout/include_fieldname" />
    </LinearLayout>
    <LinearLayout 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:orientation="vertical">
        <include 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content" 
            layout="@layout/include_fieldname" />
    </LinearLayout>
</LinearLayout>

Để ý rằng trong file layout/Main.axml lúc này xuất hiện thêm 2 ViewGroup khác nhau, nhưng chúng cùng include 1 file là layout/include_fieldname.axml. Đây là thế mạnh của thẻ <merge/>, nó là 1 pseudo parent giúp ta có thể include các components vào các layouts khác nhau để phục vụ cho việc hiển thị trên đa cửa sổ. Ngoài ra nó còn giúp ta loại bỏ các layouts không cần thiết, tránh trường hợp lồng quá nhiều ViewGroup sẽ giảm hiệu suất hoạt động của ứng dụng.

File layout:

<LinearLayout>
    <TextView />
    <EditText />
</LinearLayout>

File Main:

<FrameLayout>
    <include layout="@layout/layout" />
    <include layout="@layout/layout" />
</FrameLayout>

Nó sẽ tương đương:

<FrameLayout>
    <LinearLayout>
        <TextView />
        <EditText />
    </LinearLayout>
    <LinearLayout>
        <TextView />
        <EditText />
    </LinearLayout>
</FrameLayout>

Việc lồng ghép các ViewGroup như trên rất phức tạp, và lại kém hiệu quả cho ứng dụng của mình. Ta có thể thay thế bằng thẻ merge để loại bỏ đi các LinearLayout phức tạp trên.

Trên đây là bài viết về tái sử dụng layout với 2 thẻ include và merge. Cảm ơn các bạn đã chú ý theo dõi. Xin chào và hẹn gặp lại ở những bài viết tiếp theo!

About the author

Võ Hoài Sơn

Tính tình bất định
Chọc vào là bịnh
Rất yêu lập trình
Luôn code hết mình
Mình hiện đang là sinh viên của trường ĐH Khoa học tự nhiên TPHCM. Bản thân rất thích code, kiêm luôn cả mần thơ nên thường hơi hâm hâm dở dở. Ngoài ra chém gió, chém chuối, chém trái cây các kiểu cũng là sở trường của mình. Rất mong được làm quen với các bạn :D

Add Comment