Dùng thành phần nhận biết phiên bản

Giờ đây, bạn đã có hai cách triển khai TabHelperCompatTab — một cho Android 3.0 trở lên và một cho các phiên bản cũ hơn của nền tảng này — đã đến lúc thực hiện các bước triển khai này. Bài học này thảo luận về việc tạo logic để chuyển đổi giữa các phương thức triển khai này, tạo bố cục nhận biết phiên bản và cuối cùng là sử dụng thành phần giao diện người dùng tương thích ngược.

Thêm logic chuyển đổi

Lớp trừu tượng TabHelper đóng vai trò là một nhà máy để tạo các thực thể TabHelperCompatTab phù hợp với phiên bản, dựa trên phiên bản nền tảng của thiết bị hiện tại:

Kotlin

sealed class TabHelper(protected val mActivity: FragmentActivity, protected val tag: String) {

    abstract fun setUp()

    abstract fun addTab(tab: CompatTab)

    // Usage is tabHelper.newTab("tag")
    fun newTab(tag: String): CompatTab =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                CompatTabHoneycomb(mActivity, tag)
            } else {
                CompatTabEclair(mActivity, tag)
            }

    companion object {
        // Usage is TabHelper.createInstance(activity)
        fun createInstance(activity: FragmentActivity): TabHelper =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    TabHelperHoneycomb(activity)
                } else {
                    TabHelperEclair(activity)
                }
    }
}

Java

public abstract class TabHelper {
    ...
    // Usage is TabHelper.createInstance(activity)
    public static TabHelper createInstance(FragmentActivity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            return new TabHelperHoneycomb(activity);
        } else {
            return new TabHelperEclair(activity);
        }
    }

    // Usage is tabHelper.newTab("tag")
    public CompatTab newTab(String tag) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            return new CompatTabHoneycomb(mActivity, tag);
        } else {
            return new CompatTabEclair(mActivity, tag);
        }
    }
    ...
}

Tạo bố cục hoạt động có nhận biết phiên bản

Bước tiếp theo là cung cấp bố cục cho hoạt động có thể hỗ trợ triển khai 2 thẻ. Đối với cách triển khai cũ (TabHelperEclair), bạn cần đảm bảo bố cục hoạt động chứa TabWidgetTabHost, cùng với vùng chứa nội dung thẻ:

res/layout/main.xml:

<!-- This layout is for API level 5-10 only. -->
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />

    </LinearLayout>
</TabHost>

Để triển khai TabHelperHoneycomb, bạn chỉ cần có một FrameLayout để chứa nội dung thẻ, vì chỉ báo thẻ do ActionBar cung cấp:

res/layout-v11/main.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabcontent"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Trong thời gian chạy, Android sẽ quyết định phiên bản bố cục main.xml sẽ tăng cường tuỳ thuộc vào phiên bản nền tảng. Đây cũng là logic được trình bày trong phần trước để xác định phương thức triển khai TabHelper cần sử dụng.

Sử dụng TabHelper trong hoạt động của bạn

Trong phương thức onCreate() của hoạt động, bạn có thể lấy đối tượng TabHelper và thêm các thẻ bằng đoạn mã sau:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    setContentView(R.layout.main)

    TabHelper.createInstance(this).apply {
        setUp()

        newTab("photos")
                .setText(R.string.tab_photos)
                .also { photosTab ->
                    addTab(photosTab)
                }

        newTab("videos")
                .setText(R.string.tab_videos)
                .also { videosTab ->
                    addTab(videosTab)
                }
    }
}

Java

@Override
public void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.main);

    TabHelper tabHelper = TabHelper.createInstance(this);
    tabHelper.setUp();

    CompatTab photosTab = tabHelper
            .newTab("photos")
            .setText(R.string.tab_photos);
    tabHelper.addTab(photosTab);

    CompatTab videosTab = tabHelper
            .newTab("videos")
            .setText(R.string.tab_videos);
    tabHelper.addTab(videosTab);
}

Khi chạy ứng dụng, mã này sẽ tăng cường bố cục hoạt động chính xác và tạo thực thể cho đối tượng TabHelperHoneycomb hoặc TabHelperEclair. Lớp cụ thể được sử dụng thực sự được làm mờ đối với hoạt động vì chúng dùng chung giao diện TabHelper phổ biến.

Dưới đây là hai ảnh chụp màn hình của quá trình triển khai này khi chạy trên thiết bị Android 2.3 và Android 4.0.

Ảnh chụp màn hình mẫu của các thẻ chạy trên thiết bị Android 2.3 (sử dụng TabHelperEclair). Ảnh chụp màn hình ví dụ về các thẻ chạy trên thiết bị Android 4.0 (sử dụng TabHelperHoneycomb).

Hình 1. Ảnh chụp màn hình ví dụ về các thẻ có khả năng tương thích ngược chạy trên thiết bị Android 2.3 (sử dụng TabHelperEclair) và thiết bị Android 4.0 (sử dụng TabHelperHoneycomb).