Android 11 开发者预览版现已推出;快来测试并分享您的反馈吧

创建使用旧 API 的实现

本节课讨论如何创建镜像新 API 但仍支持旧设备的实现。

确定替代解决方案

要以向后兼容的方式使用新界面功能,最具挑战性的任务就是为旧平台版本决定并实现旧版(回退)解决方案。在许多情况下,使用旧界面框架功能可以实现这些新界面组件的用途。例如:

一般而言,将新界面组件向后移植到旧设备,没有一个通用的解决方案。注意用户体验:在旧设备上,用户可能不熟悉新的设计模式和界面组件。适当考虑如何使用熟悉的元素提供相同的功能。在许多情况下,如果应用生态系统中的新界面组件比较显眼(如操作栏),或互动模型非常简单直观(例如使用 ViewPager 滑动视图),则问题不大。

使用旧 API 实现标签页

要创建操作栏标签页的旧实现,可以使用 TabWidgetTabHost(虽然也可以选择使用水平布局的 Button 微件)。在名为 TabHelperEclairCompatTabEclair 的类中实现此步骤,因为该实现使用不高于 Android 2.0 (Eclair) 的版本中引入的 API。

Eclair 标签页实现的类图。

图 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。下一课将讨论如何在您的应用中使用这些实现。

您还应阅读以下内容: