Android ActionBar使用

来源:互联网 发布:淘宝上传凭证图片尺寸 编辑:程序博客网 时间:2024/06/01 10:13

转载请标明出处:
http://blog.csdn.net/zq2114522/article/details/50576158;
本文出自:【梁大盛的博客】

Android ActionBar使用

很久之前看Google官方一个Note笔记本代码.那时候觉得很神奇程序上面那一栏东西会随着Activity的跳转进行切换按钮,并且当长按那些按钮的时候会有提示按钮的功能.那时候还没意识到那就是ActionBar.当然那时候只是一个菜鸟那时候也没怎么了解过ActionBar,就是觉得很神奇.很诧异到底是什么实现的.最后时间长了很没深究.这几天有空档把ActionBar英文文档彻头彻尾的看了一遍.突然想起以前不理解的东西原来就是ActionBar.在后面的版本因为ActionBar自身的原因引入ToolBar那也是后话了,但是必须知道ToolBar也是基于ActionBar很多功能来实现的.

ActionBar在Android 3.0(Api 11)引入的一个概念.那就意味着Android 3.0以前的FrameWork没有ActionBar存在的.Android 3.0推出的时候,也推出support library借此支持旧版本的机器(Android 2.1-Api 7及其以上的版本)能用上ActionBar等新东西.

添加ActionBar

Android 3.0为分界线.如果只运行在Android 3.0以后的机器可以直接使用ActionBar无需导入其他support library.但是为了更好的兼容性,一般都推荐使用support library借此能支持Android 2.1以上的机器.

  • 如果你的程序只允许在Android 3.0及其以上的机器(minSdkVersion 11)

    使用的包:
    import android.app.ActionBar

    Activity只需继承android.app.Activity

    “application”或者”activity”的android:theme属性必须是Theme.Holo(或者是Theme.Holo的子类)

  • 如果你的程序支持在Android 2.1及其以上的机器(minSdkVersion 7)
    使用的包:
    import android.support.v7.app.ActionBar

    Activity必须继承android.support.v7.app.AppCompatActivity或者android.support.v7.app.ActionBarActivity(AppCompatActivity和ActionBarActivity的区别.早期通过继承ActionBarActivity实现低版本支持ActionBar.在Support Library更新到v22.1的时候引入AppCompatActivity代替ActionBarActivity.在以后版本我们使用ActionBarActivity即可.)

    “application”或者”activity”的android:theme属性必须是Theme.AppCompat(或者是Theme.AppCompat的子类)

添加ActionBar需要关注的地方就是这三点.

简单代码(使用support library,以便支持到更低的版本)
MainActivity.java

package com.example.dsliang.actionbardemo;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;public class MainActivity extends ActionBarActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.dsliang.actionbardemo">    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:gravity="center"    android:layout_height="match_parent">    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="ActionBar!" /></LinearLayout>

build.gradle

apply plugin: 'com.android.application'android {    compileSdkVersion 23    buildToolsVersion "23.0.2"    defaultConfig {        applicationId "com.example.dsliang.actionbardemo"        minSdkVersion 7        targetSdkVersion 23        versionCode 1        versionName "1.0"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    testCompile 'junit:junit:4.12'    compile 'com.android.support:appcompat-v7:23.1.1'}

运行在Android 4.1.1是成长着样子的
运行在Android 4.1.1是成长着样子的

运行在Android 2.3.7是成长着样子的
运行在Android 2.3.7是成长着样子的

隐藏、显示ActionBar

获取ActionBar实例

如果使用FrameWork的Actionbar在onCreate函数通过getActionBar函数获取ActionBar的实例.(如果使用support library库需要使用getSupportActionBar函数获取ActionBar的实例)

注意:如果当你使用support library库的时候使用getActionBar函数获取ActionBar的实例.返回的值是null.反之也是同理.(getActionBar函数 - minSdkVersion 11)
  • 隐藏Actionbar
    ActionBar.hide()函数
  • 显示ActionBar
    ActionBar.show()函数

    注意:默认每次显示/隐藏ActionBar都会导致布局重新加载.视觉效果上会导致隐藏的时候整个布局给拉伸一次,显示又会导致压缩一次.针对需要频繁隐藏/显示ActionBar的情况可以将ActionBar设置成Overlay模式(覆盖在layout层上,像FrameLayout的效果.即使隐藏/显示也不会导致布局重新加载).

隐藏/显示效果:
这里写图片描述
隐藏/显示明显看到布局有重新加载.

ActionBar OverLyaout模式

(只是修改了AndroidManifest.xml和styles.xml)
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.dsliang.actionbardemo">    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

styles.xml

<resources>    <!-- Base application theme. -->    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">        <!-- Customize your theme here. -->        <item name="windowActionBarOverlay">true</item>        <item name="colorPrimary">@color/colorPrimary</item>        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>        <item name="colorAccent">@color/colorAccent</item>    </style></resources>

效果:
这里写图片描述

Action Button

在Android 3.0以后一个很值得注意到地方,他取消了菜单键并且将菜单功能集成到ActionBar里面了.由此Action Button诞生.Action Button是将本来的六宫格菜单都搬到ActionBar的右侧.在能显示的前提下都将菜单已标题或者图标加标题的形式显示在ActionBar的右侧.但是众所周知,ActionBar控件也不是很大.ActionBar会将无法容纳的Action Button放置在Overflow按钮里面(三个小点的图标).

很久之前的菜单键是这样的(六宫格)
很久之前的菜单键是这样的(Android 2.3.7)

这里写图片描述
现在是这样的(Android 4.1.1)

定义菜单键(Action Button)

  • 定义菜单键的xml文件(一般放置在res/menu/目录下)

    根节点”menu”并且包含子节点”item”,在子节点”item”定义菜单键的属性.包括:title-标题,icon-图标,id-id号,showAsAction-按钮的表现形式,等等.

    注意:在Android 3.0以前的版本,FrameWork里面并没有showAsAction这个属性.使用这属性的使用要定义命名空间.
  • 调用onCreateOptionMenu函数加载Action Button

menu.xml

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto">    <item        android:id="@+id/menu_search"        app:showAsAction="always"        android:icon="@android:drawable/ic_menu_search"        android:title="search" />    <item        android:id="@+id/menu_camera"        android:icon="@android:drawable/ic_menu_camera"        app:showAsAction="ifRoom|withText"        android:title="camera" />    <item        android:id="@+id/menu_add"        android:icon="@android:drawable/ic_menu_add"        app:showAsAction="ifRoom"        android:title="add" />    <item        android:id="@+id/menu_delete"        android:icon="@android:drawable/ic_menu_delete"        app:showAsAction="never"        android:title="delete" /></menu>

Activity类实现onCreateOptionsMenu方法即可

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

showAsAction属性解析
always:显示在ActionBar,但是只有有空间才会显示,没空间的情况下会放置在OverFlow里面
ifRoom:如果有足够空间则显示在ActionBar,没空间的情况下会放置在OverFlow里面
never:安置在OverFlow里面
withText:如果有足够空间把标题也显示在图标右侧并且用”|”号分割将图标和标题分割开.(Action Button Icon属性是可选的.如果显示在ActionBar,那么只会显示图标.添加withText以后如果显示在ActionBar的时候有足够空间会把标题和图标以前显示.当显示在ActionBar并且没显示标题的时候,长按图标会弹出标题.当Action Button显示在OverFlow的时候只会显示标题不会显示图标.)

效果图:
这里写图片描述

响应Action Button点击事件

继承Activity的onOptionsItemSelected函数,当点击Action Button的时候会调用onOptionsItemSelected函数通过MenuItem.getId可以获取到哪一个Action Button给点击.

注意:onOptionsItemSelected函数的返回值.如果返回真那就意味着已经把这一个事件消耗了.如果返回假这事件会继续传递下去(传递到Fragment).注意:不仅仅可以通过继承Activity的onOptionsItemSelected函数添加Action Button.还可以通过继承Fragment的onOptionsItemSelected函数实现添加Action Button.区别在于通过Fragment添加的Action Button项会排列在通过Activity添加的Action Button后面.当用户点击Action Button的时候会调用activity的onOptionsItemSelected函数.如果activity的onOptionsItemSelected返回true表明此事件已经处理了不在传递.如果activity的onOptionsItemSelected返回false那么会继续调用Fragment的onOptionsItemSelected函数继续处理这次点击事件.
public class MainActivity extends AppCompatActivity { ... public boolean onOptionsItemSelected(MenuItem item) {        switch (item.getItemId()) {            case R.id.menu_add:                //Do something                return true;            case R.id.menu_camera:                //Do something                return true;            case R.id.menu_delete:                //Do something                return true;            case R.id.menu_search:                //Do something                return true;        }        return super.onOptionsItemSelected(item);    } }

4.1.1 Overflow效果
4.1.1 Overflow效果

2.37 Overflow效果
2.37 Overflow效果

注意:Overflow运行效果区别原因.如果有menu按钮那么不会再显示Overflow按钮

导航栏

ActionBar除了集成了Action Button之外还暗藏一个导航栏.
在使用ActionBar的Tab功能之前,你的布局需要预留一个地方给Tab所需显示的控件.一般做法是使用FrameLayout显示Tab需要显示的内容.切换Tab的时候将Tab对于的Fragment放置到该容器当中.
使用方法:

  • 调用getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS),此函数的功能是把Tab栏显示出来.

  • 实现ActionBar.TabListener接口

    onTabSelected - Tab给选择的时候调用
    onTabUnselected - Tab反选择的时候调用
    onTabReselected - Tab选中状态再给选择的时候调用(一般不做处理)

  • 实现ActionBar.Tab,ActionBar.Tab代表一个Tab选项

  • 调用ActionBar.addTab函数把Tab添加到ActionBar

代码:

MainActivity.java

package com.example.dsliang.actionbardemo;import android.app.Activity;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentTransaction;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {    ActionBar mActionBarSupport;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ActionBar.Tab tab;        mActionBarSupport = getSupportActionBar();        mActionBarSupport.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        tab = mActionBarSupport.newTab()                .setText(R.string.tab_sports)                .setTabListener(new TabListener<TabSportFragment>(this, "体育新闻", TabSportFragment.class));        mActionBarSupport.addTab(tab);        tab = mActionBarSupport.newTab()                .setText(R.string.tab_international)                .setTabListener(new TabListener<TabInternationalFragment>(this, "国际新闻", TabInternationalFragment.class));        mActionBarSupport.addTab(tab);        tab = mActionBarSupport.newTab()                .setText(R.string.tab_focus)                .setTabListener(new TabListener<TabFocusFragment>(this, "今日焦点", TabFocusFragment.class));        mActionBarSupport.addTab(tab);    }    class TabListener<T extends Fragment> implements ActionBar.TabListener {        private Fragment mFragment;        private final Activity mActivity;        private final String mTag;        private final Class<T> mClass;        public TabListener(Activity activity, String tag, Class<T> clz) {            mActivity = activity;            mTag = tag;            mClass = clz;        }        @Override        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {            if (mFragment == null) {                mFragment = Fragment.instantiate(mActivity, mClass.getName());                ft.add(R.id.fragment_content, mFragment, mTag);            } else {                ft.attach(mFragment);            }        }        @Override        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {            if (mFragment != null) {                ft.detach(mFragment);            }        }        @Override        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {        }    }}

TabFocusFragment.java

package com.example.dsliang.actionbardemo;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by dsliang on 2016/1/25. */public class TabFocusFragment extends Fragment {    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view;        TextView textView;        view = inflater.inflate(R.layout.tab_fragment_layout, container, false);        textView = (TextView) view.findViewById(R.id.txtTextView);        textView.setText(R.string.tab_focus);        return view;    }}

TabInternationalFragment.java

package com.example.dsliang.actionbardemo;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by dsliang on 2016/1/25. */public class TabInternationalFragment extends Fragment {    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view;        TextView textView;        view = inflater.inflate(R.layout.tab_fragment_layout, container, false);        textView = (TextView) view.findViewById(R.id.txtTextView);        textView.setText(R.string.tab_international);        return view;    }}

TabSportFragment.java

package com.example.dsliang.actionbardemo;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by dsliang on 2016/1/25. */public class TabSportFragment extends Fragment {    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view;        TextView textView;        view = inflater.inflate(R.layout.tab_fragment_layout, container, false);        textView = (TextView) view.findViewById(R.id.txtTextView);        textView.setText(R.string.tab_sports);        return view;    }}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center"    android:orientation="vertical">    <FrameLayout        android:id="@+id/fragment_content"        android:layout_width="match_parent"        android:layout_height="match_parent"></FrameLayout></LinearLayout>

tab_fragment_layout.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center"    android:orientation="vertical">    <TextView        android:id="@+id/txtTextView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="25sp" /></LinearLayout>

strings.xml

<resources>    <string name="app_name">ActionBarDemo</string>    <string name="tab_sports">体育新闻</string>    <string name="tab_international">国际新闻</string>    <string name="tab_focus">今日焦点</string></resources>

TabFocusFragment、TabInternationalFragment、TabSportFragment三个Fragment代码是基本一样的。实质应该用不同的Fragment代替,仅作示范。
具体代码里面已经很清楚了,就不再细说了。(除了导航栏意外还有另一种下拉导航栏,基本都是大同小异的。)

效果:
这里写图片描述

Action View

除了Action Button和Tab之外还有Action View。
什么是Action View?
我们可以在ActionBar中嵌入我们自定义的Layout或者View控件,称之Action View。
有什么用途?
在不改变ActionBar、Fragment和Activity的前提下快速完成某些操作,如:搜索等(当然在ActionBar内嵌一个SearchView是最常见的)。
使用方法:

  • 和定义Action Buton基本一样,就是多了一个actionViewClass属性(collapseActionView表明将ActionView折叠成一个ActionButton)

    例如:app:showAsAction=”ifRoom|collapseActionView”

     注意:actionViewClass属性也是在低版本没定义的。需要在xml文件新建命名空间
  • 查找Actoin View对应的View

    代码

getMenuInflater().inflate(R.menu.main_activity_actions, menu);    MenuItem searchItem = menu.findItem(R.id.action_search);    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
注意:MenuItemCompat.getActionView(searchItem)是Api 7提供的函数。Api 11以后可以使用menu.findItem(R.id.action_search).getActionView()

- 定义Action View回调事件
通过MenuItemCompat.setOnActionExpandListener设置折叠/打开监听函数
(具体可以看后面提供的代码)

代码

MainActivity.java

package com.example.dsliang.actionbardemo;import android.os.Bundle;import android.support.v4.view.MenuItemCompat;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.SearchView;import android.view.Menu;import android.view.MenuItem;import android.widget.Toast;public class MainActivity extends AppCompatActivity {    ActionBar mActionBarSupport;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ActionBar.Tab tab;        mActionBarSupport = getSupportActionBar();    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        MenuItem menuItem;        SearchView searchView;        getMenuInflater().inflate(R.menu.menu, menu);        menuItem = menu.findItem(R.id.menu_search);        searchView = (SearchView) MenuItemCompat.getActionView(menuItem);        //可以针对searchView设置相应的监听函数        //....searchView        //设置折叠监听函数        MenuItemCompat.setOnActionExpandListener(menuItem, new MenuItemCompat.OnActionExpandListener() {            @Override            public boolean onMenuItemActionExpand(MenuItem item) {                Toast.makeText(MainActivity.this, "ActionView open", Toast.LENGTH_SHORT).show();                return true;            }            @Override            public boolean onMenuItemActionCollapse(MenuItem item) {                Toast.makeText(MainActivity.this, "ActionView collapse", Toast.LENGTH_SHORT).show();                return true;            }        });        return super.onCreateOptionsMenu(menu);    }}

menu.xml

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto">    <item        android:id="@+id/menu_search"        app:showAsAction="ifRoom|collapseActionView"        android:icon="@android:drawable/ic_menu_search"        android:title="search"        app:actionViewClass="android.support.v7.widget.SearchView"/>    <item        android:id="@+id/menu_camera"        android:icon="@android:drawable/ic_menu_camera"        app:showAsAction="ifRoom"        android:title="camera" />    <item        android:id="@+id/menu_add"        android:icon="@android:drawable/ic_menu_add"        app:showAsAction="ifRoom"        android:title="add" />    <item        android:id="@+id/menu_delete"        android:icon="@android:drawable/ic_menu_delete"        app:showAsAction="ifRoom"        android:title="delete" /></menu>

效果:
这里写图片描述
Action View 效果

总结:这一篇写的挺多的.遗憾AcionBar Home按钮没写.打算等有时间继续写下去.此外下一篇写Menu的使用.因为ActionBar使用必定就牵涉到Menu了!

参考


1:ActionBar http://android.xsoftlab.net/guide/topics/ui/actionbar.html
2:ActionBar http://android.xsoftlab.net/reference/android/support/v7/app/ActionBar.html
3:Menu http://android.xsoftlab.net/reference/android/view/Menu.html
4:如何在有菜单键的机器显示OverFlow按钮 http://www.jb51.net/article/52468.htm
5:Android ActionBar完全解析,使用官方推荐的最佳导航栏 http://itindex.net/detail/49902-android-actionbar-%E5%AE%8C%E5%85%A8
6:ActionBar侧拉栏 http://blog.csdn.net/jjwwmlp456/article/details/41206513

0 0