Android 用户界面---操作栏(Action Bar 四)

创建一个定制的操作提供器

当你想要创建一个有动态行为和在溢出菜单中有默认图标的操作视窗时,,继承ActionProvider类来定义这些行为是一个比好的的方案。创建自己的操作提供器,提供一个有组织的可重用的组件,而不是在Fragment或Activity的代码中处理各种操作项的变换和行为。

要创建自己的操作提供器,只需简单的继承ActionProvider类,并且实现合适的回调方法。你应该实现以下重要的回调方法:

ActionProvider()

   这个构造器把应用程序的Context对象传递个操作提供器,你应该把它保存在一个成员变量中,以便其他的回调方法使用。

OnCreateActionView()

   这是你给菜单项定义操作视窗的地方。使用从构造器中接收的Context对象,获取一个LayoutInflater对象的实例,并且用XML资源来填充操作视窗,然后注册事件监听器。如:

public View onCreateActionView() {
    // Inflate the action view to be shown on the action bar.
    LayoutInflater layoutInflater = LayoutInflater.from(mContext);
    View view = layoutInflater.inflate(R.layout.action_provider, null);
    ImageButton button = (ImageButton) view.findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Do something...
        }
    });
    return view;

}

onPerformDefaultAction()
   在选中溢出菜单中的菜单时,系统会调用这个方法,并且操作提供器应该这对这个选中的菜单项执行默认的操作。

但是,如果你的操作提供器提供了一个子菜单,即使是溢出菜单中一个菜单项的子菜单,那么也要通过onPrepareSubMenu()回调方法来显示子菜单。这样onPerformDefaultAction()在子菜单显示时就不会被调用。

注意:实现了onOptionsItemSelected()回调方法的Activity或Frament对象能够通过处理item-selected事件(并且返回true)来覆盖操作提供器的默认行为,这种情况下,系统不会调用onPerformDefaultAction()回调方法。

添加导航选项标签

当你想要在一个Activity中提供导航选择标签时,使用操作栏的选项标签是一个非常好的选择(而不是使用TabWidget类),因为系统会调整操作栏选项标签来适应不同尺寸的屏幕的需要---在屏幕足够宽的时候,导航选项标签会被放到主操作栏中;当屏幕太窄的时候,选项标签会被放到一个分离的横条中,如图9和图10所示。

pic

图9. Honeycomb Gallery应用程序中的操作栏选项标签的截图

http://developer.android.com/resources/samples/HoneycombGallery/index.html

 pic

图10. 在窄屏设备上被堆放在操作栏中的选项标签的截屏

要使用选项标签在Fragmengt之间切换,你必须在每次选择一个选项标签时执行一个Fragment事务。如果你不熟悉如何使用FragmentTransaction对象来改变Fragment,请阅读Fragment开发指南。

首先,你的布局必须包含一个用于放置跟每个Fragment对象关联的选项标签的ViewGroup对象。并且要确保这个ViewGroup对象有一个资源ID,以便你能够在选项标签的切换代码中能够引用它。另外,如果选项标签的内容填充在Activity的布局中(不包括操作栏),那么Activity不需要任何布局(你甚至不需要调用setContentView()方法)。相反,你能够把每个Fragment对象放到默认的根ViewGroup对象中,你能够用android.R.id.content ID来引用这个ViewGroup对象(在Fragment执行事务期间,你能够在下面的示例代码中看到如何使用这个ID的。

决定了Fragment对象在布局中的显示位置后,添加选项标签的基本过程如下:

1.  实现ActionBar.TabListener接口。这个接口中回调方法会响应选项标签上的用户事件,以便你能够切换Fragment对象;

2.  对于每个要添加的选项标签,都要实例化一个ActionBar.Tab对象,并且调用setTabListener()方法设置ActionBar.Tab对象的事件监听器。还可以用setText()或setIcon()方法来设置选项标签的标题或图标。

3.  通过调用addTab()方法,把每个选项标签添加到操作栏。

在查看ActionBar.TabListener接口时,注意到回调方法只提供了被选择的ActionBar.Tab对象和执行Fragment对象事务的FragmentTransaction对象---没有说明任何有关Fragment切换的事。因此。你必须定义自己的每个ActionBar.Tab之间的关联,以及ActionBar.Tab所代表的适合的Fragment对象(为了执行合适的Fragment事务)。依赖你的设计,会有几种不同的方法来定义这种关联。在下面的例子中,ActionBar.TabListener接口的实现提供了一个构造器,这样每个新的选项标签都会使用它自己的监听器实例。每个监听器实例都定义了几个在对应Fragment对象上执行事务时必须的几个成员变量。

例如,以下示例是ActionBar.TabListener接口的一种实现,在这个实现中,每个选项标签都使用了它自己的监听器实例:

public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;

    /** Constructor used each time a new tab is created.
      * @param activity  The host Activity, used to instantiate the fragment
      * @param tag  The identifier tag for the fragment
      * @param clz  The fragment's Class, used to instantiate the fragment
      */
    public TabListener(Activity activity, String tag, Class<T> clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

    /* The following are each of the ActionBar.TabListener callbacks */

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // Check if the fragment is already initialized
        if (mFragment == null) {
            // If not, instantiate and add it to the activity
            mFragment = Fragment.instantiate(mActivity, mClass.getName());
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            // If it exists, simply attach it in order to show it
            ft.attach(mFragment);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

警告:针对每个回调中的Fragment事务,你都不必调用commit()方法---系统会调用这个方法,并且如果你自己调用了这个方法,有可能会抛出一个异常。你也不能把这些Fragment事务添加到回退堆栈中。

在这个例子中,当对应的选项标签被选择时,监听器只是简单的把一个Fragment对象附加(attach()方法)到Activity布局上---或者,如果没有实例化,就会创建这个Fragment对象,并且把它添加(add()方法)到布局中(android.R.id.content ViewGroup的一个子类),当这个选项标签解除选择时,对应的Fragment对象也会被解除与布局的依附关系。

ActionBar.TabListener的实现做了大量的工作,剩下的事情就是创建每个ActionBar.Tab对象并把它添加到ActionBar对象中,另外,你必须调用setNavigationMode(NAVIGATION_MODE_TABS)方法来让选项标签可见。如果选项标签的标题实际指示了当前的View对象,你也可以通过调用setDisplayShowTitleEnabled(false)方法来禁用Activity的标题。

例如,下面的代码使用上面定义的监听器在操作栏中添加了两个选项标签。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Notice that setContentView() is not used, because we use the root
    // android.R.id.content as the container for each fragment

    // setup action bar for tabs
    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    actionBar.setDisplayShowTitleEnabled(false);

    Tab tab = actionBar.newTab()
            .setText(R.string.artist)
            .setTabListener(new TabListener<ArtistFragment>(
                    this, "artist", ArtistFragment.class));
    actionBar.addTab(tab);

    tab = actionBar.newTab()
        .setText(R.string.album)
        .setTabListener(new TabListener<AlbumFragment>(
                this, "album", AlbumFragment.class));
    actionBar.addTab(tab);
}

注意:以上有关ActionBar.TabListener的实现,只是几种可能的技术之一。在API Demos应用中你能够看到更多的这种样式。

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html

如果Activity终止了,那么你应该保存当前选择的选项标签的状态,以便当用户再次返回时,你能够打开合适的选项标签。在保存状态的时刻,你能够用getSelectedNavigationIndex()方法查询当前的被选择的选项标签。这个方法返回被选择的选项标签的索引位置。

警告:保存每个Fragment所必须的状态是至关重要的,因为当用户用选项标签在Fragment对象间切换时,它会查看Fragment在离开时样子。

注意:在某些情况下,Android系统会把操作栏选项标签作为一个下拉列表来显示,以便确保操作栏的最优化显示。

添加下拉式导航

作为Activity内部的另一种导航(或过滤)模式,操作栏提供了内置的下拉列表。下拉列表能够提供Activity中内容的不同排序模式。

启用下拉式导航的基本过程如下:

1.  创建一个给下拉提供可选项目的列表,以及描画列表项目时所使用的布局;

2.  实现ActionBar.OnNavigationListener回调,在这个回调中定义当用户选择列表中一个项目时所发生的行为;

3.  用setNavigationMode()方法该操作栏启用导航模式,如:

ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

4.  用setListNavigationCallbacks()方法给下拉列表设置回调方法,如:

actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);

这个方法需要SpinnerAdapter和ActionBar.OnNavigationListener对象。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值