Action Bar

本文详细介绍了Android中ActionBar的设计目标、实现方式及使用场景。包括如何在不同主题下启用ActionBar,如何定制搜索框、菜单项显示方式,以及如何通过ActionBar进行导航等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A key goal of the action bar design is to make the frequently used actions easily
available to the user without searching through option menus or context menus.

An action bar is owned by an activity and follows its lifecycle.
An action bar can take one of three forms: tabbed action bar, list
action bar, or standard action bar. You see how these various action
bars look and behave in each of the modes.

ou see how to place a custom search widget in the action bar

 provides user actions and navigation modes

Beginning with Android 3.0 (API level 11), the action bar is included in all activities that use the Theme.Holo theme (or one of its descendants), which is the default theme when either thetargetSdkVersion or minSdkVersion attribute is set to "11" or greater.


If you don't want the action bar for a particular activity, set the activity theme to Theme.Holo.NoActionBar. For example:

<activity android:theme="@android:style/Theme.Holo.NoActionBar">

You can also hide the action bar at runtime by calling hide(). For example:

ActionBar actionBar = getActionBar();
actionBar.hide();

When the action bar hides, the system adjusts your activity layout to fill all the screen space now available. You can bring the action bar back with show().

 your activity regularly hides and shows the action bar (such as in the Android Gallery app), you might want to use overlay mode. Overlay mode draws the action bar on top of your activity layout rather than in its own area of the screen

To enable overlay mode, create a theme for your activity and setandroid:windowActionBarOverlay to true.

In the XML file, you can request a menu item to appear as an action item by declaringandroid:showAsAction="ifRoom" for the <item> element. This way, the menu item appears in the action bar for quick access only if there is room available. If there's not enough room, the item appears in the overflow menu.

menu item supplies both a title and an icon if you want to display the text title, add "withText" to theandroid:showAsAction attribute.


However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected() on the activity before calling the same callback for the fragment.

Using the App Icon for Navigation


When the user touches the icon, the system calls your activity'sonOptionsItemSelected() method with the android.R.id.homeID. In response, you should either start the home activity or take the user one step up in your application's structural hierarchy.

If you respond to the application icon by returning to the home activity, you should include the FLAG_ACTIVITY_CLEAR_TOP flag in the Intent. With this flag,

In case the user can enter the current activity from another application, you might also want to add theFLAG_ACTIVITY_NEW_TASK flag. This flag ensures that, when the user navigates either "home" or "up", the new activity is not added to the current task, but instead started in a task that belongs to your application


So if your activity accepts intents from other applications (it declares any generic intent filters), you should usually add theFLAG_ACTIVITY_NEW_TASK flag to the intent:

To declare an action view for an item in your menu resource, use either the android:actionLayout orandroid:actionViewClass attribute to specify either a layout resource or widget class to use, respectively. For example:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_search"
          android:title="@string/menu_search"
          android:icon="@drawable/ic_menu_search"
          android:showAsAction="ifRoom|collapseActionView"
          android:actionViewClass="android.widget.SearchView" />
</menu>
Notice that the  android:showAsAction  attribute also includes  "collapseActionView" . This is optional and declares that the action view should be collapsed into a button. When the user selects the button, the action view expands.


If you need to update your activity based on the visibility of your action view, you can receive callbacks when it's expanded and collapsed by defining an OnActionExpandListener and registering it withsetOnActionExpandListener(). For example:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    MenuItem menuItem = menu.findItem(R.id.actionItem);
    ...

    menuItem.setOnActionExpandListener(new OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // Do something when collapsed
            return true;  // Return true to collapse action view
        }

        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // Do something when expanded
            return true;  // Return true to expand action view
        }
    });
}

Adding an Action Provider


the ShareActionProvider is an extension ofActionProvider that facilitates a “share" action by showing a list of available share targets from the action bar.

To declare an action provider for an action item, define theandroid:actionProviderClass attribute for the appropriate the <item>element in your menu resource, using the fully-qualified class name of the action provider. For example:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_share"
          android:title="@string/share"
          android:showAsAction="ifRoom"
          android:actionProviderClass="android.widget.ShareActionProvider" />
    ...
</menu>

Creating a custom action provider

To create your own, simply extend the ActionProvider class and implement its callback methods as appropriate. Most importantly, you should implement the following:

ActionProvider()
This constructor passes you the application   Context, which you should save in a member field to use in the other callback methods.
onCreateActionView()
This is where you define the action view for the item. Use the   Context  acquired from the constructor to instantiate a   LayoutInflater  and inflate your action view layout from an XML resource, then hook up event listeners. For example:
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()
The system calls this when the menu item is selected from the overflow menu and the action provider should perform a default action for the menu item.

However, if your action provider provides a submenu, through the onPrepareSubMenu() callback, then the submenu appears even when the menu item is in the overflow menu. Thus,onPerformDefaultAction() is never called when there is a submenu.

Note: An activity or a fragment that implements onOptionsItemSelected() can override the action provider's default behavior by handling the item-selected event (and returning true), in which case, the system does not call onPerformDefaultAction().

Adding Navigation Tabs

When you want to provide navigation tabs in an activity, using the action bar's tabs is a great option (instead of usingTabWidget), because the system adapts the action bar tabs for different screen sizes—placing them in the main action bar when the screen is sufficiently wide, or in a separate bar (known as the "stacked action bar") when the screen is too narrow, as shown in figures 9 and 10.
@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);
}
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.
    }
}

The basic procedure to enable drop-down navigation is:

  1. Create a SpinnerAdapter that provides the list of selectable items for the drop-down and the layout to use when drawing each item in the list.
  2. Implement ActionBar.OnNavigationListener to define the behavior that occurs when the user selects an item from the list.
  3. Enable navigation mode for the action bar with setNavigationMode(). For example:
    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

    Note: You should perform this during your activity's onCreate() method.

  4. Set the callback for the drop-down list with setListNavigationCallbacks(). For example:
    actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback);



SpinnerAdapter
 is an adapter that provides data for a spinner widget, such as the drop-down list in the action bar. SpinnerAdapter is an interface that you can implement, but Android includes some useful implementations that you can extend, such as ArrayAdapter and SimpleCursorAdapter. For example, here's an easy way to create a SpinnerAdapter by using ArrayAdapter implementation, which uses a string array as the data source:

SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
          android.R.layout.simple_spinner_dropdown_item);

The createFromResource() method takes three parameters: the application Context, the resource ID for the string array, and the layout to use for each list item.

string array defined in a resource looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="action_list">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
    </string-array>
</pre>

The ArrayAdapter returned by createFromResource() is complete and ready for you to pass it tosetListNavigationCallbacks() (in step 4 from above). Before you do, though, you need to create theOnNavigationListener.

Your implementation of ActionBar.OnNavigationListener is where you handle fragment changes or other modifications to your activity when the user selects an item from the drop-down list. There's only one callback method to implement in the listener: onNavigationItemSelected().

The onNavigationItemSelected() method receives the position of the item in the list and a unique item ID provided by the SpinnerAdapter.

Here's an example that instantiates an anonymous implementation of OnNavigationListener, which inserts a Fragment into the layout container identified by R.id.fragment_container:

mOnNavigationListener = new OnNavigationListener() {
  // Get the same strings provided for the drop-down's ArrayAdapter
  String[] strings = getResources().getStringArray(R.array.action_list);

  @Override
  public boolean onNavigationItemSelected(int position, long itemId) {
    // Create new fragment from our own Fragment class
    ListContentFragment newFragment = new ListContentFragment();
    FragmentTransaction ft = openFragmentTransaction();
    // Replace whatever is in the fragment container with this fragment
    //  and give the fragment a tag name equal to the string at the position selected
    ft.replace(R.id.fragment_container, newFragment, strings[position]);
    // Apply changes
    ft.commit();
    return true;
  }
};

This instance of OnNavigationListener is complete and you can now callsetListNavigationCallbacks() (in step 4), passing the ArrayAdapter and this OnNavigationListener.

In this example, when the user selects an item from the drop-down list, a fragment is added to the layout (replacing the current fragment in the R.id.fragment_container view). The fragment added is given a tag that uniquely identifies it, which is the same string used to identify the fragment in the drop-down list.

Here's a look at the ListContentFragment class that defines each fragment in this example:

public class ListContentFragment extends Fragment {
    private String mText;

    @Override
    public void onAttach(Activity activity) {
      // This is the first callback received; here we can set the text for
      // the fragment as defined by the tag specified during the fragment transaction
      super.onAttach(activity);
      mText = getTag();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // This is called to define the layout for the fragment;
        // we just create a TextView and set its text to be the fragment tag
        TextView text = new TextView(getActivity());
        text.setText(mText);
        return text;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值