ActionBar

来源:互联网 发布:农村淘宝合伙人招募网 编辑:程序博客网 时间:2024/06/06 00:49
一、介绍
(一) 
ActionBar和sherlockActionBar - supershll - 记忆里

ActionBar有4个区域,包括
[1]app icon:可以替换为别的logo
[2]View Control:drop-down菜单或tab controls。也可以用来显示非交互的内容,例如app title或更长的品牌信息。
[3]action buttons:盛不下的会自动移动到action overflow中。长按可显示action的名称。action Buttons的总宽度不会超过整个ActionBar宽度的50%。一般小于360dp的屏幕宽度只能放置2个icons,360-499dp的可以放置3个icons,500-599dp可以放4个icons,600dp以上可以放5个icons。
[4]action overflow:

(二)ActionBar自Android 3.0(API Level 11)引入,但Android 2.1以后就可以使用了(需要引入appcompat v7 Support Library)。本文主要介绍如何在低于3.0的设备上使用ActionBar。要使用ActionBar首先需要引入
import android.support.v7.app.ActionBar
【API 11中 import android.app.ActionBar】

(三)使用ActionBar
1、Activity继承ActionBarActivity。
2、在Manifest文件中为Activity设置主题为Theme.AppCompat或其子主题,例如:
<activity android:theme:"@style/Theme.AppCompat.Light" ...>
【API 11中默认主题是Theme.Holo,自带ActionBar,如果不想使用ActionBar,可以使用Theme.Holo.NoActionBar主题】

3、在运行时隐藏ActionBar
ActionBar actionBar = getSupportActionBar();
actionBar.hide();//隐藏ActionBar
//actionBar.show();//显示

【注意:默认情况下,ActionBar和ActivityLayout分享屏幕空间,当ActionBar显示或隐藏时,系统会调整layout来充满屏幕的空间。如果你的app需要经常显示或隐藏ActionBar,你应该启用overlay模式,这样ActionBar会绘制在activity的layout的上方,要开启overlay模式,你需要创建一个主题Theme,并设置<item name="windowActionBarOverlay">true</item>属性为true,详情看后面】

4、替换logo
默认情况下,ActionBar的app Icon使用你在Manifest文件中为<application>或<activity>元素指定的icon属性的图片。
你可以指定actionbar的logo属性来替换此图片。
logo应该比icon更宽一些,但不应该包括不必要的文本。

5、添加action items
当你的Activity启动时,系统会调用Acitivity的onCreateOptionsMenu()方法来渲染ActionBar。
如果要请求菜单项直接显示为一个Action Button (推理,默认是显示在overflow中?),看例子:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
          android:icon="@drawable/ic_action_search"
          android:title="@string/action_search"
          yourapp:showAsAction="ifRoom"  />
    ...
</menu>

默认情况下,Action Button只显示icon,要想显示title,则
<item yourapp:showAsAction="ifRoom|withText" ... />
系统只是尽量显示title
【你还可以使用showAsAction="always",让菜单项强制显示成一个Aciton Button,但这在窄屏设备上会出现layout problems。一般使用action view时使用这个选项。建议不要使用这个属性值。】

6、处理action items的点击事件,还是使用onOptionsItemSelected()方法。

7、使用Split ActionBar。可选操作:
ActionBar和sherlockActionBar - supershll - 记忆里
 
(1)为<application>或<activity>元素添加uiOptions="splitActionBarWhenNarrow"。但这个属性只在API 14以上才被理解,旧版本会忽视它。
(2)要支持旧版本,为每个<activity>元素添加<meta-data>子元素,如下:
     <manifest ...>
        <activity uiOptions="splitActionBarWhenNarrow" ... >
            <meta-data android:name="android.support.UI_OPTIONS"  android:value="splitActionBarWhenNarrow" />
        </activity>
    </manifest>

使用Split ActionBar时,如果你禁用了actionbar icon和title【使用setDisplayShowHomeEnabled(false)和setDisplayShowTitleEnabled(false)】,navigation tabs就进到了main bar中。


8、使用app Icon作为Up按钮
    actionbar.setDisplayHomeAsUpEnabled();
现在icon左边会出现Up符号(caret)。但是现在点击home图标不会做任何事情。你有2个选择:
(1)在Manifest文件中指定parent Activity:
      (a)在android4.1(API 16)以后,你可以为每个<activity>元素声明parentActivityName属性
      (b)在旧版本中还是使用<meta-data>子元素:
                <application ... >
                    ...
                   <!-- The main/home activity (has no parent activity) -->
                   <activity
                        android:name="com.example.myfirstapp.MainActivity" ...>
                        ...
                    </activity>
                    <!-- A child of the main activity -->
                   <activity
                        android:name="com.example.myfirstapp.DisplayMessageActivity"
                        android:label="@string/title_activity_display_message"
                        android:parentActivityName="com.example.myfirstapp.MainActivity" >
                        <!-- Parent activity meta-data to support API level 7+ -->
                        <meta-data
                            android:name="android.support.PARENT_ACTIVITY"
                            android:value="com.example.myfirstapp.MainActivity" />
                   </activity>
                </application>

(2)在你的Activity中重载getSupportParentActivityIntent()和onCreateSupportNavigateUpTaskStack()。
       (a)getSupportParentActivityIntent()是用户按Up按钮时,如果你的Activity在你的app的自己的task中时调用的回调函数。
       (b)onCreateSupportNavigateUpTaskStack()是用户按Up按钮时,如果你的Activity没有在你的app的自己的task中时调用的回调函数。

即使你重载了getSupportParentActivityIntent()来指定了Up导航,你也可以通过在Manifest文件中声明parent Activity,从而不需要实现onCreateSupportNavigateUpTaskStack()。然后,onCreateSupportNavigateUpTaskStack()的默认实现会基于在Manifest文件中声明的parent Activite综合出一个back stack。
【注意:如果你的应用使用的是fragments而不是很多Activities,那么上面的那些方法都不会工作。此时,你需要重载onSupportNavigateUp()来手动执行fragment Transaction】

9、添加Action View:在xml中使用actionLayout或actionViewClass属性,例如:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_search"
          android:title="@string/action_search"
          android:icon="@drawable/ic_action_search"
          yourapp:showAsAction="ifRoom|collapseActionView"
          yourapp:actionViewClass="android.support.v7.widget.SearchView
" />
</menu>

【注意到showAsAction属性还包括了一个"collapseActionView"值。这个值是可选的,它声明了Action View应该作为一个Action Button,表示该view可以放进overflow,但用户选择了它之后,它就会仍然显示于action bar中,因此你不用在onOptionsItemSelected()回调中响应该事件。如果在此回调函数中你返回了true,那么Action View就不会被展开了。
当用户按了Up按钮或Back按钮时,系统也会收缩你的Action View。
如果你需要根据Action View的是否可见来更新你的Activity,你可以通过实现OnActionExpandListener来做到。例如:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    MenuItem menuItem = menu.findItem(R.id.actionItem);
    ...
    // 当使用Support Library时,setOnActionExpandListener()方法是一个静态方法
    MenuItemCompat.setOnActionExpandListener(menuItem, 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
        }
    });
}


你可以在onCreateOptionsMenu()回调函数中配置Action View(例如添加事件监听)。例子:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_activity_actions, menu);
    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
   //在API Level11以上使用下面的方法   
    //SearchView searchView=menu.findItem(R.id.action_search).getActionView();
   
 // Configure the search info and add any event listeners
    ...
    return super.onCreateOptionsMenu(menu);
}

10、添加Action Provider
(1)和Action View类似,Action Provider也使用自定义的layout,但Action Provider可以显示一个子菜单。
要声明一个Action Provider,需要在menu xml中使用actionViewClass属性。
你可以继承ActionProvider类,但是Android提供了一些预定义的Action Provider,例如ShareActionProvider。
因为ActionProvider定义了它自己的行为,所以你不用在onOptionsItemSelected()方法中监听他们的动作。虽然系统仍然会调用此函数,但记住要return false才能让ActionProvider收到onPerformDefaultAction()回调从而正常工作。
例子:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
    <item android:id="@+id/action_share"
          android:title="@string/share"
          yourapp:showAsAction="ifRoom"
          yourapp:actionProviderClass="android.support.v7.widget.ShareActionProvider"
     />
    ...
</menu>

(2)现在你还需要定义分享时你要使用的Intent。在onCreateOptionsMenu()方法中调用MenuItemCompat.getActionProvider()并向其传递包含actionProvider的menuItem。然后调用setShareIntent(),如果用户上下文发生更改,你必须再次调用setShareIntent()来更新Intent内容。
例子:
private ShareActionProvider mShareActionProvider;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_activity_actions, menu);
    // Set up ShareActionProvider's default share intent
    MenuItem shareItem = menu.findItem(R.id.action_share);
    mShareActionProvider = (ShareActionProvider)MenuItemCompat.getActionProvider(shareItem);
    mShareActionProvider.setShareIntent(getDefaultIntent());

    return super.onCreateOptionsMenu(menu);
}

//一旦需要时,你就要尽快再次调用mShareActionProvider.setShareIntent()
private Intent getDefaultIntent() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    return intent;
}

(3)默认情况下,ShareActionProvider使用DEFAULT_SHARE_HISTORY_FILE_NAME文件来保持一份历史记录,使用次数多的放在前面,使用次数少的放在后面。如果你使用ShareActionProvider或其子类,只有一个动作时,那就使用这个文件也无所谓。如果你有多个动作时,你应该调用setShareHistoryFileName()来指定你自己的HistoryFile,并且提供一个XML文件。

(4)创建一个自定义的action Provider
      (a)继承ActionProvider,最重要的你要继承的方法:
           (i)ActionProvider():构造方法
           (ii)onCreateActionView(MenuItem):例子:
                   public View onCreateActionView(MenuItem forItem) {
                      // 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;
                   }
          (iii)onPerformDefaultAction():当用户点击该menuitem时的动作,如果你的Action Provider准备提供一个子菜单,则实现onPrepareSubMenu()方法。如果实现了该方法,那么onPerformDefaultAction()就不会被调用
  
11、添加Navigation Tabs,步骤:
  (1)实现ActionBar.TabListener接口。
  (2)实例化ActionBar.Tab并设置setTabListener、setText()、setIcon()。
  (3)使用addTab()方法添加到ActionBar。
   例子:
   (1)创建实现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.
        }
    }
    【注意!你不能调用fragmentTransaction的commit()方法。】

    (2)接下来就是创建ActionBar.Tab,并将其添加到ActionBar。另外,你还必须调用setNavigationMode(NAVIGATION_MODE_TABS),这让Action Tabs变得可见。
      例子:
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          // 注意 setContentView()没有被调用,但是我们使用android.R.id.content作为每个fragment的容器
         // setup action bar for tabs
          ActionBar actionBar = getSupportActionBar();
         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);
    }

12、添加Drop-down Navigation
ActionBar提供了一个内建的drop-down list("Spinner")。当切换内容是重要的,但不是常用操作时,可以使用该控件。
步骤:
  (1)创建一个SpinnerAdater
  (2)实现ActionBar.OnNavigationListener来定义用户选择了list中的item时的操作。
  (3)在Activity的onCreate()方法中设置ActionBar:setNavigationMode(NAVIGATION_MODE_LIST)
  (4)设置回调: actionBar.setListNavigationCallbacks(mSpinnerAdater,mNavigationCallback);


13、ActionBar样式:
【注意:所有的backgrounddrawable都应该使用9-patch图像,并且小于40dp高和30dp宽。】
    a、一般外观 样式:
  (a1)actionBarStyle:默认style是Widget.AppCompat.ActionBar,它应该作为父style。
     支持的style包括:
     (a)background
     (b)backgroundStacked:stacked action bar一般指tabs。
     (c)backgroundSplit:split action bar
     (d)actionButtonStyle:默认样式是Widget.AppCompat.ActionButton。
     (e)displayOptions:定义一个或多个Action Bar的显示属性,例如是否使用app logo,是否显示activity title,是否启用Up按钮。等等
     (f)divider:action items之间的divider。
     (g)titleTextStyle:默认是TextAppearance.AppCompat.Widget.ActionBar.Title。

  (a2)windowActionBarOverlay:默认是false,此时Actionbar和Activity Layout分享屏幕空间。设置成true时,你的activity将占据整个空间,系统在其上绘制ActionBar。Holo主题默认ActionBar是半透明的,DeviceDefault主题在不同的设备上有不同的表现。要解决ActionBar的遮挡问题,你可以在layout xml中设置view的marginTop:
  <SomeView ...android:layout_marginTop="?android:attr/actionBarSize" />
    你也可以在运行时使用actionBar.getHeight()获取其高度。

    b、Action Items样式:
  (1)actionButtonStyle:
  (2)actionBarItemBackground:应该使用state-list drawable
  (3)itemBackground:action overflow item的背景,应该使用state-list drawable
  (4)actionBarDivider:
  (5)actionMenuTextColor:
  (6)actionMenuTextAppearance:
  (7)actionBarWidgetTheme:action views的theme

   c、Navigation Tabs样式:
  (1)actionBarTabStyle:默认样式是Widget.AppCompat.ActionBar.TabView。
  (2)actionBarTabBarStyle:默认样式是Widget.AppCompat.ActionBar.TabBar。
  (3)actionBarTabTextStyle:默认样式是Widget.AppCompat.ActionBar.TabText。

   d、Drop-down Lists样式:
  (1)actionDropDownStyle:默认样式是Widget.AppCompat.Spinner.DropDown.ActionBar。

  e、theme例子:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"  parent="@style/Theme.AppCompat.Light">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:actionBarTabTextStyle">@style/TabTextStyle</item>
        <item name="android:actionMenuTextColor">@color/actionbar_text</item>

        <!-- Support library compatibility -->
        <item name="actionBarStyle">@style/MyActionBar</item>
        <item name="actionBarTabTextStyle">@style/TabTextStyle</item>
        <item name="actionMenuTextColor">@color/actionbar_text</item>
    </style>

    <!-- general styles for the action bar -->
    <style name="MyActionBar"  parent="@style/Widget.AppCompat.ActionBar">
        <item name="android:titleTextStyle">@style/TitleTextStyle</item>
        <item name="android:background">@drawable/actionbar_background</item>
        <item name="android:backgroundStacked">@drawable/actionbar_background</item>
        <item name="android:backgroundSplit">@drawable/actionbar_background</item>

        <!-- Support library compatibility -->
        <item name="titleTextStyle">@style/TitleTextStyle</item>
        <item name="background">@drawable/actionbar_background</item>
        <item name="backgroundStacked">@drawable/actionbar_background</item>
        <item name="backgroundSplit">@drawable/actionbar_background</item>
    </style>

    <!-- action bar title text -->
    <style name="TitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>

    <!-- action bar tab text -->
    <style name="TabTextStyle"  parent="@style/Widget.AppCompat.ActionBar.TabText">
        <item name="android:textColor">@color/actionbar_text</item>
    </style>
</resources>

    f、使用Theme:
        <application android:theme="@style/CustomActionBarTheme" ... />   或
       <activity android:theme="@style/CustomActionBarTheme" ... />
0 0
原创粉丝点击