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 có khả năng tương thích ngược.

Thêm logic chuyển đổi

Lớp trừu tượng TabHelper đóng vai trò là 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 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ủa bạn có thể hỗ trợ việc triển khai hai 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ó FrameLayout để chứa nội dung thẻ, vì các 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 nào cần tăng cường tuỳ thuộc vào phiên bản nền tảng. Đây là logic tương tự như trong phần trước để xác định cách triển khai TabHelper nào sẽ sử dụng.

Sử dụng TabHelper trong hoạt động

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 bản sao của đố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 mẫu của 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 mẫu của các thẻ 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).