控件 -- ActionBar

一、概念

在Android 3.0中,ActionBar是一个非常重要的交互元素,ActionBar取代了传统的标题栏,在程序运行中一直置于顶部,对于Android平板设备来说,屏幕更大,标题栏使用ActionBar来设计可以展示更多丰富的内容,方便操控。

二、使用

1.添加ActionBar

在Android 3.0及更高的版本中,Activity中都默认包含有ActionBar。

2.取消ActionBar

manifest设置:


代码设置:

ActionBar actionBar = getActionBar();  
actionBar.hide();  //隐藏

actionBar.show();  //显示

如果使用一个主题(theme)来移除Activity上的ActionBar,那么窗口将不再会有ActionBar,因此在运行时也就没有办法来添加ActionBar,调用getActionBar()方法会返回null值。

3.添加Action按钮

ActionBar可以根据应用程序当前的功能来提供与其相关的Action按钮,这些按钮都会以图标或文字的形式直接显示在ActionBar上。当然,如果按钮过多,ActionBar上显示不完,多出的一些按钮可以隐藏在overflow里面(最右边的三个点就是overflow按钮),点击一下overflow按钮就可以看到全部的Action按钮了。
(1)定义menu资源

//menu_main.xml



    
    
    


这里我们通过标签定义了三个Action按钮。
标签中又有一些属性,其中:
id:是该Action按钮的唯一标识符;
icon:用于指定该按钮的图标;
title:用于指定该按钮可能显示的文字(在图标能显示的情况下,通常不会显示文字);
actionViewClass:用于指定一个构建视窗所使用的布局资源;
showAsAction:用于指定按钮显示的位置。

showAsAction主要有以下几种值可选:
ifRoom:会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中,当然个数并不仅仅局限于4个,依据屏幕的宽窄而定。
never:永远不会显示,只会在溢出列表中显示,而且只显示标题,所以在定义item的时候,最好把标题都带上。
always:无论是否溢出,总会显示。
withText:示意ActionBar要显示文本标题,ActionBar会尽可能显示这个标题,但是如果图标有效并且受到ActionBar空间的限制,文本标题有可能显示不全。
collapseActionView:声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开,否则这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间,一般要配合ifRoom一起使用才会有效果。

title中的内容通常情况下只会在overflow中显示出来,ActionBar中由于屏幕空间有限,默认是不会显示title内容的。但是出于以下几种因素考虑,即使title中的内容无法显示出来,我们也应该给每个item中都指定一个title属性:
●当ActionBar中的剩余空间不足的时候,如果Action按钮指定的showAsAction属性是ifRoom的话,该Action按钮就会出现在overflow当中,此时就只有title能够显示了。
●如果Action按钮在ActionBar中显示,用户可能通过长按该Action按钮的方式来查看到title的内容。

(2)重写Activity的onCreateOptionsMenu()方法
当Activity启动的时候,系统会调用Activity的onCreateOptionsMenu()方法来取出所有的Action按钮,我们只需要在这个方法中去加载一个menu资源,并把所有的Action按钮都定义在资源文件里面就可以了。

@Override 
public boolean onCreateOptionsMenu(Menu menu) {  
    MenuInflater inflater = getMenuInflater();  
    inflater.inflate(R.menu.menu_main, menu);  
    return super.onCreateOptionsMenu(menu);  
}  

(3)重写Activity的onOptionsItemSelected()方法

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {  
        case R.id.user_p:  
            Toast.makeText(this, "你点击了“用户”按键!", Toast.LENGTH_SHORT).show();  
            return true;  
        case R.id.write_p:  
            Toast.makeText(this, "你点击了“发布”按键!", Toast.LENGTH_SHORT).show();  
            return true;  
        case R.id.favo_p:  
            Toast.makeText(this, "你点击了“收藏”按键!", Toast.LENGTH_SHORT).show();  
            return true;  
        default:  
            return super.onOptionsItemSelected(item);  
    }  
}

4.通过ActionBar图标进行导航

ActionBar actionBar = getActionBar();  
actionBar.setDisplayHomeAsUpEnabled(true); 

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) { 
        case android.R.id.home:  
            finish();
            return true; 
        ...
    }
}

5.添加ActionView

ActionView是一种可以在ActionBar中替换Action按钮的控件,它可以允许用户在不切换界面的情况下通过ActionBar完成一些较为丰富的操作。比如说,你需要完成一个搜索功能,就可以将SeachView这个控件添加到ActionBar中。
(1)定义menu资源
为了声明一个ActionView,我们可以在menu资源中通过actionViewClass属性来指定一个控件:


(2)重写Activity的onCreateOptionsMenu()方法

@Override 
public boolean onCreateOptionsMenu(Menu menu) {  
    MenuInflater inflater = getMenuInflater();  
    inflater.inflate(R.menu.main, menu);  
    MenuItem searchItem = menu.findItem(R.id.action_search);  
    SearchView searchView = (SearchView) searchItem.getActionView();  
    // 配置SearchView的属性  
    ...
    return super.onCreateOptionsMenu(menu);  
}  

有些程序可能还希望在ActionView展开和合并的时候显示不同的界面,其实我们只需要去注册一个ActionView的监听器就能实现这样的功能:

@Override 
public boolean onCreateOptionsMenu(Menu menu) {  
    MenuInflater inflater = getMenuInflater();  
    inflater.inflate(R.menu.main, menu);  
    MenuItem searchItem = menu.findItem(R.id.action_search);  
    searchItem.setOnActionExpandListener(new OnActionExpandListener() {  
        @Override 
        public boolean onMenuItemActionExpand(MenuItem item) {  
            Log.d("TAG", "on expand");  
            return true;  
        }  
          
        @Override 
        public boolean onMenuItemActionCollapse(MenuItem item) {  
            Log.d("TAG", "on collapse");  
            return true;  
        }  
    });  
    return super.onCreateOptionsMenu(menu);  
}  

6.添加ActionProvider

和ActionView有点类似,ActionProvider也可以将一个Action按钮替换成一个自定义的布局。但不同的是,ActionProvider能够完全控制事件的所有行为,并且还可以在点击的时候显示子菜单。
(1)定义menu资源
为了添加一个ActionProvider,我们需要在标签中指定一个actionViewClass属性,在里面填入ActionProvider的完整类名。我们可以通过继承ActionProvider类的方式来创建一个自己的ActionProvider,同时Android也提供好了几个内置的ActionProvider,比如说ShareActionProvider。




     
    ...

(2)重写Activity的onCreateOptionsMenu()方法

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_main, menu);
    MenuItem shareItem = menu.findItem(R.id.action_share);
    ShareActionProvider provider = (ShareActionProvider) shareItem
        .getActionProvider();
    provider.setShareIntent(getDefaultIntent());
    return super.onCreateOptionsMenu(menu);
}

private Intent getDefaultIntent() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("image/*");
    return intent;
}

这里我们通过getDefaultIntent()方法来构建了一个Intent,该Intent会将所有可以共享图片的程序都列出来。

这个ShareActionProvider点击之后是可以展开的,有点类似于overflow的效果,这就是ActionProvider的子菜单。

7.添加导航Tabs

Tabs的应用可以算是非常广泛了,它可以使得用户非常轻松地在应用程序中切换不同的视图。而Android官方更加推荐使用ActionBar中提供的Tabs功能,因为它更加的智能,可以自动适配各种屏幕的大小。比如说,在平板上屏幕的空间非常充足,Tabs会和Action按钮在同一行显示,而如果是在手机上,屏幕的空间不够大的话,Tabs和Action按钮则会分为两行显示。

添加步骤:
(1)实现ActionBar.TabListener接口,这个接口提供了Tab事件的各种回调,比如当用户点击了一个Tab时,可以进行切换Tab的操作;
(2)为每一个想添加的Tab创建一个ActionBar.Tab的实例,并且调用setTabListener()方法来设置ActionBar.TabListener。除此之外,还需要调用setText()方法来给当前Tab设置标题;
(3)最后调用ActionBar的addTab()方法将创建好的Tab添加到ActionBar中。

//TabListener
import android.app.ActionBar;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;

public class TabListener implements ActionBar.TabListener {
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class 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 clz) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
    }

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

    public void onTabSelected(ActionBar.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(ActionBar.Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            // Detach the fragment, because another one is being attached
            ft.detach(mFragment);
        }
    }

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

//Fragment1,Fragment2、Fragment3类似
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment1 extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment1, container, false);
    }
}

//fragment1.xml,fragment2.xml、fragment3.xml类似


    


//MainActivity
private void initView() {
    // 提示getActionBar方法一定在setContentView后面
    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // 添加Tab选项
    ActionBar.Tab tab = actionBar
            .newTab()
            .setText("澳门风云2")
            .setTabListener(
                    new TabListener(this, "film1",
                            Fragment1.class));
    actionBar.addTab(tab);

    tab = actionBar
            .newTab()
            .setText("五十度灰")
            .setTabListener(
                    new TabListener(this, "film2",
                            Fragment2.class));
    actionBar.addTab(tab);

    tab = actionBar
            .newTab()
            .setText("爸爸去哪儿2")
            .setTabListener(
                    new TabListener(this, "film3",
                            Fragment3.class));
    actionBar.addTab(tab);
}

8.添加下拉列表导航

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

添加步骤:
(1)创建一个给下拉提供可选项目的列表,以及描画列表项目时所使用的布局;
(2)实现ActionBar.OnNavigationListener回调,在这个回调中定义当用户选择列表中一个项目时所发生的行为;
(3)用setNavigationMode()方法该操作栏启用导航模式;
(4)用setListNavigationCallbacks()方法给下拉列表设置回调方法。

//strings.xml

    Fragment1
    Fragment2
    Fragment3


//MainActivity
private ActionBar.OnNavigationListener mOnNavigationListener;
private String[] arry_list;
private void initView() {
    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    // //导航模式必须设为NAVIGATION_MODE_LIST
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

    // 定义一个下拉列表数据适配器
    SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
            R.array.action_list,
            android.R.layout.simple_spinner_dropdown_item);
    arry_list = getResources().getStringArray(R.array.action_list);
    mOnNavigationListener = new ActionBar.OnNavigationListener() {

        @Override
        public boolean onNavigationItemSelected(int position, long itemId) {
            Fragment newFragment = null;
            switch (position) {
                case 0:
                    newFragment = new Fragment1();
                    break;
                case 1:
                    newFragment = new Fragment2();
                    break;
                case 2:
                    newFragment = new Fragment3();
                    break;
                default:
                    break;
            }
            getFragmentManager()
                    .beginTransaction()
                    .replace(R.id.container, newFragment,
                            arry_list[position]).commit();
            return true;
        }
    };
    actionBar.setListNavigationCallbacks(mSpinnerAdapter,
            mOnNavigationListener);
}

9.自定义ActionBar样式

(1)使用主题
可以将主题应用到整个应用程序,也可以只应用于某个Activity。通过在AndroidManifest.xml文件中给标签指定android:theme属性就可以实现了。如果只想让ActionBar使用深色系的主题,而Activity的内容部分仍然使用浅色系的主题,可以通过声明以下主题来实现:

android:theme="@android:style/Theme.Holo.Light.DarkActionBar"

(2)自定义背景
如果想要修改ActionBar的背景,我们可以通过创建一个自定义主题并重写actionBarStyle属性来实现。这个属性可以指向另外一个样式,然后我们在这个样式中重写background这个属性就可以指定一个drawable资源或颜色,从而实现自定义背景的功能。




(3)自定义文字颜色









(4)自定义Tab Indicator
为了可以明确分辨出我们当前选中的是哪一个Tab项,通常情况下都会在选中Tab的下面加上一条横线作为标识,这被称作Tab Indicator。如果要自定义Tab Indicator,首先我们需要重写actionBarTabStyle这个属性,将它指向一个新建的Tab样式,然后重写background这个属性即可。需要注意的是,background必须要指定一个state-list drawable文件,这样在各种不同状态下才能显示出不同的效果。

步骤1:准备四张图片,分别用于表示Tab的四种状态:选中未按下、选中且按下、未选中未按下、未选中且按下,并创建state-list drawable文件。

//actionbar_tab_indicator.xml
 
 
 
     
     
     
     
 
 

步骤2:修改style.xml文件。

 
 
     
      
     
 
 

你可能感兴趣的:(控件 -- ActionBar)