Android 原生导航 I-ActionBar

概述:

App bar, 也被称为action bar, 是Activity中最重要的设计元素之一, 因为它提供了一个用户熟悉的可视化结构和交互功能. 使用app bar可以让我们的app跟其它的Android app风格保持一致, 让用户可以快速的理解如何操作app并拥有一个良好的用户体验. App bar的关键功能如下:

l  它是一个专用的区域用于向用户展示其在app中的位置.

l  以一个可预测的方式访问重要的操作, 比如搜索.(风格一致的一种优势).

l  支持导航和view切换(通过tab或者下拉列表).


本文描述了如何使用v7 appcompat支持库中的Toolbar控件作为一个app bar. 还有其它的方法可以实现一个app bar, 比如有些主题默认情况下就会设置一个ActionBar作为一个app bar. 但是使用appcompat中的Toolbar使得设置app bar在各种设备上的使用都变得更加简单, 并且留给我们更多的可以自定义app bar的空间.

下文将会包括这几个小节:

l  设置App bar: 介绍如何向activity添加一个Toolbar小组件, 并设置它为activity的app bar.

l  添加和处理Action: 介绍如何添加action到app bar, 以及它的溢出(overflow)菜单和相应用户操作.

l  添加一个向上(Up)操作: 介绍如何添加一个Up按键到app bar, 这样用户就可以导航回到app的home页面了.

l  Action View和Action Provider: 介绍如何使用这些组件来提供app bar的高级功能.

设置App bar:

app bar的最简单的风格是在其一边显示activity的主题, 另一边则显示一个溢出菜单.即便是如此简单的格式, 它依然提供了有用的信息给用户, 并提供了一个一致的Android风格和体验. 下图展示了带有主题和溢出菜单的app bar:


从Android 3.0(API level 11)开始, 所有的使用默认主题的activity都将拥有一个ActionBar作为app bar. 然而app bar的更多功能逐渐随着新的Android版本的发布被添加到原生ActionBar中. 这导致在不同版本的Android设备中它们的原生ActionBar拥有不同的行为. 相比之下, 最近被添加到支持库中的功能是Toolbar, 并且它们在任何可以使用支持库的设备上都可以使用. 正因为如此, 我们应该使用支持库的Toolbar类来实现我们的activity app bar. 使用支持库的Toolbar可以让我们确保我们的app在不同版本的设备上拥有一致的体验. 比如Toolbar组件可以在Android 2.1(API level 7)及更高的版本上提供统一的materialdesign的体验, 但是原生的action bar不能支持material design, 除非它的版本在Android 5.0以上.

添加一个Toolbar到Activity:

1.      在工程中添加v7 appcompat支持库.

2.      确保Activity是继承自AppCompatActivity的:

public class MyActivity extends AppCompatActivity {
  // ...
}

提醒: 任何一个使用Toolbar的Activity都应该确认这个.

3.      在app的manifest中, 设置<application>标签使用appcompat的NoActionBar主题. 使用这些主题中的一个来阻止app使用原生的ActionBar类. 栗子:

<application
    android:theme="@style/Theme.AppCompat.Light.NoActionBar"
    />

4.      添加一个Toolbar到activity的layout. 栗如, 下面的layout代码添加了一个Toolbar并指定它悬浮在activity上方.

<android.support.v7.widget.Toolbar
   android:id="@+id/my_toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   android:background="?attr/colorPrimary"
   android:elevation="4dp"
   android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
   app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

Material design 规范推荐app bar指定elevation为4dp. 如果使用Toolbar作为app bar, 那么应该将它至于activitylayout的顶部.

5.      在activity的onCreate()方法中, 调用activity的setSupportActionBar()方法, 并将activity的Toolbar作为参数传给它. 该方法会设置Toolbar作为activity的app bar. 栗如:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);
    Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
    setSupportActionBar(myToolbar);
    }

现在我们的app就拥有了一个带有基础功能的action bar. 默认情况下, action bar仅包含app的名字和一个溢出菜单. Options menu也只包含一个Settings项. 我们可以添加更多的action到action bar和溢出菜单.

使用app bar的实用方法:

一旦设置了Toolbar作为activity的app bar, 我们就可以访问多种v7 appcompat支持库中ActionBar类提供的实用方法. 它让我们可以做很多有用的事, 比如隐藏和显示app bar. 要使用ActionBar的适用方法, 调用activity的getSupportActionBar()方法. 它会返回一个ActionBar对象的reference. 一旦我们有了这个reference, 就可以调用任何ActionBar中的方法来调整app bar, 比如如果想要隐藏app bar, 那么就调用ActionBar.hide().

添加和处理Action:

App bar让我们可以添加按钮来为用户提供操作. 这个功能让我们可以将最重要的操作添加到当前的app顶部. 比如, 一个照片浏览app可能会在用户查看相片列表的时候在屏幕顶部显示”共享”和”创建相册”按钮; 当用户查看单个的照片时, 可以显示”裁剪”按钮.

App bar上面的空间是很有限的. 如果一个app添加的action超过了app bar可以容纳的数量, appbar会将超出的action放到一个溢出菜单中. App也可以指定某个action总是显示在溢出菜单中, 而不是显示在app bar上. 下图是一个拥有单个action按钮和一个溢出菜单的app bar:

添加Action按钮:

所有的action按钮和其它在溢出菜单中的action都被定义在一个XML菜单资源中. 要添加一个action到action bar, 需要在res/menu/目录下创建一个新的XML文件. 添加为每个想要添加的action添加一个<item>元素, 栗如:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- "Mark Favorite", should appear as action button if possible -->
    <item
        android:id="@+id/action_favorite"
        android:icon="@drawable/ic_favorite_black_48dp"
        android:title="@string/action_favorite"
        app:showAsAction="ifRoom"/>

    <!-- Settings, should always be in the overflow -->
    <item android:id="@+id/action_settings"
          android:title="@string/action_settings"
          app:showAsAction="never"/>

</menu>

App:showAsAction属性指定了action是否应该作为一个按钮显示在appbar上面. 如果设置该值为”ifRoom”, 那么action会在空间足够的情况下显示在app bar上面; 如果没有足够的空间, 超出的action会被放在溢出菜单中. 如果设置为了”never”, 那么action总是会被放在溢出菜单中, 而不会显示在app bar上.

如果action被显示在app bar上面, 那么系统会使用action的图标作为action按钮. 我们可以在Material Icons页面中找到很多有用的图标.

响应Action:

当用户选择了app bar中的某个项的时候, 系统会调用activity的onOptionsItemSelected()回调方法, 并传给它一个MenuItem对象来说明哪个项被点击了.在我们实现的onOptionsItemSelected()方法中, 使用MenuItem.getItemId()来查看被选择的项. 返回的ID可以跟<item>中的android:id属性对比, 相同的就是. 栗如, 下面这段代码检查了用户点击哪个按钮. 如果没有识别到用户选择的action, 那么它将直接调用父类的方法:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_settings:
            // User chose the "Settings" item, show the app settings UI...
            return true;

        case R.id.action_favorite:
            // User chose the "Favorite" action, mark the current item
            // as a favorite...
            return true;

        default:
            // If we got here, the user's action was not recognized.
            // Invoke the superclass to handle it.
            return super.onOptionsItemSelected(item);

    }
}

添加一个Up操作:

我们的APP应该为用户提供简单的返回到主界面的方法. 一种很便利的方式就是在除主界面之外的所有activity的app bar上提供一个Up按钮. 当用户点击Up按钮, app就导航到当前activity的parent.

声明一个Parent Activity:

要在一个activity中实现up操作, 我们首先要声明一个activity的parent. 我们可以在app 的manifest中通过设置android:parentActivityName属性来实现该功能. 该属性在Android4.1(API level 16)中引入. 要想在更老版本的设备中支持它, 可以定义一个<meta-data>键值对, 名字是”android.support.PARENT_ACTIVYT”并指定值为parent activity的名字. 栗如, 假设我们的app有个主界面叫MainActivity和一个子activity.下面这段代码声明了这两个activity, 并指定了它们的亲子关系:

<application ...>
    ...

    <!-- Themain/home activity (it has no parent activity) -->

    <activity
        android:name="com.example.myfirstapp.MainActivity" ...>
        ...
    </activity>

    <!-- A childof the main activity -->
    <activity
        android:name="com.example.myfirstapp.MyChildActivity"
        android:label="@string/title_activity_child"
        android:parentActivityName="com.example.myfirstapp.MainActivity">

        <!-- Parent activity meta-data to support 4.0 and lower -->
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity"/>

    </activity>
</application>

启用Up按钮: 

要为一个已经拥有了parent 的activity启动Up按钮, 需要调用app bar的setDisplayHomeAsUpEnabled()方法. 通常我们在activity创建的时候调用该方法. 栗如下面的onCreate()方法设置了一个Toolbar作为MyChildActivity的app bar., 然后启用了app bar的Up按钮:

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my_child);

    //my_child_toolbar is defined in the layout file
    Toolbar myChildToolbar =
        (Toolbar) findViewById(R.id.my_child_toolbar);
    setSupportActionBar(myChildToolbar);

    // Get a supportActionBar corresponding to this toolbar
    ActionBar ab = getSupportActionBar();

    // Enable the Upbutton
    ab.setDisplayHomeAsUpEnabled(true);
}

我们并不需要在activity的onOptionsItemSelected()方法中捕捉up操作. 该方法将会调用父类中的方法,就像前面响应Action中的一样. 父类中的方法将会处理Up操作, 并导航到manifest中指定的parent activity.

ActionView和Action Provider:

V7 appcompat支持库中的Toolbar提供了很多不同的方法让用户可以跟我们的app进行交互. 前文描述了如何定义一个actoin, 可以是一个按钮或者菜单项. 这里讲再介绍两个多功能的组件:

l  Action View: 它是一个可以通过app bar提供丰富功能的action. 比如, 一个搜索action view可以让用户在app bar中输入搜索文本, 而不用改变activity或者fragment.

l  Action Provider: 它是一个可以自定义layout的action. Action开始的时候显示为一个按钮或者菜单项, 但是当用户点击action, action Provider可以控制action的行为, 而我们可以自定义这个行为.比如, action Provider可以在用户点击某个action的时候显示一个菜单.

Android支持库中提供了一些特定的actionview和action Provider组件. 比如, SearchView组件让我们可以实现搜索功能; ShareActionProvider组件则可以创建一个action Provider来跟其它app共享信息. 我们还可以定义自己的action view和action provider.

添加一个action view:

要添加一个action view, 需要在Toolbar的菜单资源中创建一个<item>标签. 添加下面其中一个属性到<item>中:

l  actionViewClass: 实现该action的类.

l  actionLayout: 描述action组件的layout.

设置showAsAction属性为”ifRoom|collapseActionView”或者”never|collapseActionView”.其中clooapseActionView标志表示当用户不跟action交互的时候它是如何显示的: 如果组件在app bar上面, 那么它应该显示为一个图标. 如果组件在溢出菜单中, 那么它应该显示为一个菜单项. 当用户跟action view交互的时候, 它将会扩展并填满app bar. 下面的代码展示了如何添加一个SearchView组件到app bar中:

<itemandroid:id="@+id/action_search"
     android:title="@string/action_search"
     android:icon="@drawable/ic_search"
     app:showAsAction="ifRoom|collapseActionView"
     app:actionViewClass="android.support.v7.widget.SearchView"/>

当用户不与它交互的时候, app会将其显示为一个图标(也就是通过android:icon指定的图标). 如果空间不够则会将其显示在溢出菜单中. 当用户点击图标或者溢出菜单的时候, 它就会扩展来填满Toolbar, 让用户可以输入要搜索的字符串.


如果想要配置action, 那么可以在activity的onCreateOptionMenu()方法中这样做. 我们可以通过静态方法getActionView()来得到action view的对象说明. 栗如, 下面的代码用于获取SearchView的对象说明:

@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);


    // Configure thesearch info and add any event listeners...

    return super.onCreateOptionsMenu(menu);
}

响应action view的扩展:

如果action的<item>标签拥有一个collapseActionView标记, 那么app会在action view没有跟用户交互的时候将其显示为一个图标. 用户点击了图标, onOptionsItemSelected()的内置handler就会展开actionview. 如果activity的子类重写了onOptionsItemSelected()方法, 那么重写的方法必须调用super.onOptionsItemSelected()方法, 这样子类才能扩展开actionview.

如果我们想要在action view扩展开或者折叠起来的时候做一些事情, 那么可以定义一个类来实现MenuItem.OnActionExpandListener, 并将其传给setOnActionExpandListener().栗如, 我们可能想要在action view扩展或者折叠的时候更新它, 那么可以这样做:

@Override
public boolean onCreateOptionsMenu(Menu menu){
    getMenuInflater().inflate(R.menu.options, menu);
    // ...

    // Define thelistener
    OnActionExpandListener expandListener = new OnActionExpandListener(){
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item){
            // Do something when action item collapses
            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
        }
    };

    // Get theMenuItem for the action item
    MenuItem actionMenuItem = menu.findItem(R.id.myActionItem);

    // Assign thelistener to that action item
    MenuItemCompat.setOnActionExpandListener(actionMenuItem, expandListener);

    // Any otherthings you have to do when creating the options menu…

    return true;
}

添加一个Action Provider:

要声明一个action provider, 需要在Toolbar的菜单资源中创建一个<item>标签. 添加一个actionProviderClass属性, 并设置它为action provider的类的全名. 栗如, 这段代码声明了一个ShareActionProvider, 它是一个支持库中定义的组件, 可以让app分享数据给别的app:

<itemandroid:id="@+id/action_share"
    android:title="@string/share"
    app:showAsAction="ifRoom"
    app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>

在这个栗子中, 没有必要为组件声明一个图标, 因为ShareActionProvider提供了自己的图标. 如果需要为其定义一个自定义的图标, 那么可以声明一个icon. 更多关于ActionProvider和ShareActionProvider的信息, 可以参考它们的reference.

 

参考: https://developer.android.com/training/appbar/index.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值