使用旧版 API 创建实现

本课程讨论如何创建一个镜像更新的 API 但支持旧版设备的实现。

决定替代解决方案

以向后兼容的方式使用更新的 UI 功能最具挑战性的任务是决定并实施针对旧版平台版本的旧版(回退)解决方案。在许多情况下,可以使用旧版 UI 框架功能来实现这些更新的 UI 组件的目的。例如

通常没有适用于将更新的 UI 组件移植到旧版设备的通用解决方案。请注意用户体验:在旧版设备上,用户可能不熟悉更新的设计模式和 UI 组件。请考虑如何使用熟悉的元素来提供相同的功能。在许多情况下,这并不那么令人担忧 - 如果更新的 UI 组件在应用程序生态系统中很突出(例如操作栏),或者交互模型非常简单直观(例如使用 ViewPager 的滑动视图)。

使用旧版 API 实现选项卡

要创建操作栏选项卡的旧版实现,可以使用 TabWidgetTabHost(尽管可以使用水平排列的 Button 小部件)。在名为 TabHelperEclairCompatTabEclair 的类中实现此功能,因为此实现使用的是在 Android 2.0(Eclair)或更高版本中引入的 API。

Class diagram for the Eclair implementation of tabs.

图 1. 选项卡 Eclair 实现的类图。

CompatTabEclair 实现将选项卡属性(例如选项卡文本和图标)存储在实例变量中,因为没有 ActionBar.Tab 对象可用于处理此存储。

Kotlin

class CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :
        CompatTab(tag) {

    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private var text: CharSequence? = null
    ...

    override fun setText(resId: Int): CompatTab {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.resources.getText(resId)
        return this
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

Java

public class CompatTabEclair extends CompatTab {
    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private CharSequence text;
    ...

    public CompatTab setText(int resId) {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.getResources().getText(resId);
        return this;
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

TabHelperEclair 实现使用 TabHost 小部件上的方法来创建 TabHost.TabSpec 对象和选项卡指示器。

Kotlin

class TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {

    private var tabHost: TabHost? = null
    ...

    override fun setUp() {
        // Our activity layout for pre-Honeycomb devices
        // must contain a TabHost.
        tabHost = tabHost ?: mActivity.findViewById<TabHost>(android.R.id.tabhost).apply {
            setup()
        }
    }

    override fun addTab(tab: CompatTab) {
        ...
        tabHost?.newTabSpec(tab.tag)?.run {
            setIndicator(tab.getText()) // And optional icon
            ...
            tabHost?.addTab(this)
        }
    }
    // The other important method, newTab() is part of
    // the base implementation.
}

Java

public class TabHelperEclair extends TabHelper {
    private TabHost tabHost;
    ...

    protected void setUp() {
        if (tabHost == null) {
            // Our activity layout for pre-Honeycomb devices
            // must contain a TabHost.
            tabHost = (TabHost) mActivity.findViewById(
                    android.R.id.tabhost);
            tabHost.setup();
        }
    }

    public void addTab(CompatTab tab) {
        ...
        TabSpec spec = tabHost
                .newTabSpec(tag)
                .setIndicator(tab.getText()); // And optional icon
        ...
        tabHost.addTab(spec);
    }

    // The other important method, newTab() is part of
    // the base implementation.
}

现在,您有两个 CompatTabTabHelper 实现:一个适用于运行 Android 3.0 或更高版本的设备并使用新的 API,另一个适用于运行 Android 2.0 或更高版本的设备并使用旧版 API。下一课将讨论如何在您的应用程序中使用这些实现。