1.引入
1.0 很有用的参考链接
下面内容参考自 Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)_guolin的博客-优快云博客_actionbar导航
1.1 应用结构--好的应用应有清晰的结构
在第六章了解到,创建应用时会有3种不同类型的屏幕:
除此之外,他们还有很棒的快捷路径:使用导航。
1.2 不同导航类型
披萨应用的顶级屏幕显示了一个选项列表,提供了运行用户访问的一些选项。
前3个选项链接到类别活动;第一个选项会为用户提供一个披萨列表,第二个选项提供一个意大利面列表,第三个会显示一个分店列表。可以认为类别活动都是被动的(passive)。它们只是显示信息,帮助你在应用中完成导航。
第4个选项链接到一个详细信息/编辑活动,允许用户创建一个订单。这个选项是主动的(active)。它允许用户完成一些创建工作。
通常会用不同的方式处理主动和被动导航选项。这一章中我们会介绍如何处理主动导航选项。
1.3 使用动作条ActionBar实现导航
1.3.1 什么是动作条 ActionBar
Action Bar是一种新増的导航栏功能,在Android 3.0之后加入到系统的API当中,它标识了用户当前操作界面的位置,并提供了额外的用户动作、界面导航等功能。使用ActionBar的好处是,它可以给提供一种全局统一的UI界面,使得用户在使用任何一款软件时都懂得该如何操作,并且ActionBar还可以自动适应各种不同大小的屏幕。下面是一张使用ActionBar的界面截图
其中,[1]是ActionBar的图标,[2]是两个action按钮,[3]是overflow按钮
在这个披萨应用中,我们可以在各个活动的顶部增加一个动作条,这样一来,不论用户当前在什么位置,都能很容易地下订单。这个动作条要包含一个Create Order(创建订单)按钮,不论用户在什么位置都能轻松访问。
1.3.2 添加动作条ActionBar
先看动作条的用法:
- 显示应用或活动名,使用户知道他们在应用中的哪个位置。例如,email应用可以使用动作条告诉用户目前在查看收件箱还是垃圾邮件文件夹。
- 用一种可预测的方式突出显示关键的动作,例如,共享内容或完成搜索。
- 导航到其他活动来完成一个动作。
要增加动作条,需要使用一个包含动作条的主题。主题就是应运用到整个活动或应用的一个样式,使应用有一种一致的观感。它会控制很多方面,如活动背景和动作条的颜色,以及文本的样式等等。Android提供许多可以使用的内置主题。
怎么添加动作条:
ActionBar的添加非常简单,只需要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类就可以了
如何移除动作条?
见1.0 的链接 即可。
2.支持库
2.1 工程分析
自行看书N404
关于AndroidManifest.xml文件的分析:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hfad.bitsandpizzas">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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>
android:icon属性来为应用指定一个图标。这个图标用作为应用的启动程序图标,如果使用的主体会在动作条上显示图标,他就会使用这个图标。
这个图标可以是一个drawable或mipmap资源。mipmap是可以作为应用图标的图像,这些图像资源放在app/src/main/res的mipmap*文件夹中。与drawables一样,可以把不同的图像增加到适当命名的mipmap文件夹中,针对不同的屏幕密度增加不同的图像。例如,有高密度屏幕的设备使用mipmap-hdpi文件夹中的图标。布局中使用@mipmap指示mipmap资源。
android:label属性为应用或活动指定一个用户友好的标签,具体作为应用还是活动标签,这取决于它用在<application>还是<activity>属性中。动作条会显示当前活动的标签。如果当前活动没有标签,他就会使用应用的标签。
android:theme属性用于指定主题。在<application>元素中使用这个属性将把主体应用到整个应用。如果在<activity>元素中使用这个属性,则会把它应用到一个活动。
我们的android:theme属性值为"@style/AppTheme".@style前缀表示这个主体在一个样式资源文件中定义。那么什么是样式资源文件呢?
在样式资源文件中定义样式:
样式资源文件包含你想要使用的所有主题的详细信息。
在Android Studio中创建一个工程时,IDE会为你创建一个默认的样式资源文件,名为styles.xml,位于app/src/main/res/values文件夹。这个文件如下所示:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
样式资源文件包含一个或多个样式。每个样式使用<style>元素定义。
每个样式必须有一个名,这就是你用n a me属性定义的名字。样式必须有一个名字,这样AndroidManifest.xml中的android:theme属性才可以引用这个主题。在这里,样式名为"AppTheme",所以AndroidManifest.xml可以使用"@style/AppTheme"来引用这个主题。
parent属性指定这个样式从哪里继承属性。在上面的代码中,它要继承"Theme.AppCompat.Light.DarkActionBar"。
还可以修改一个现有主题的属性,使用样式资源文件定制应用的外观。为此,要为<style>增加一个<item>元素,描述你想做的修改。例如,下面的代码将主题修改为让所有活动都有一个红色背景:
要改变应用使用的主题,则需要:
在style.xml中设置默认主题。
需要注意的是,主题版本要和MainActivity主活动类所继承的类版本要匹配。
根据书上的操作,运行应用时,会发生什么?
2.2 为动作条增加动作项--Action按钮
2.2.1 为动作条增加动作项的步骤
ActionBar还可以根据应用程序当前的功能来提供与其相关的Action按钮,这些按钮都会以图标或文字的形式直接显示在ActionBar上。当然,如果按钮过多,ActionBar上显示不完,多出的一些按钮可以隐藏在overflow里面(最右边的三个点就是overflow按钮),点击一下overflow按钮就可以看到全部的Action按钮了.
动作项--Action按钮就是动作条中的按钮或文本,可以单击这些动作项来完成某些工作。
例如,我们要为动作条增加一个“Create Order”(创建订单)按钮。
要为动作条增加动作项,需要做3件事:
1.在一个菜单资源文件menu_main.xml中定义动作项。
2.让活动充气( inflate)菜单资源。
可以通过实现onCreateoptionsMenu()方法来做到。
3.增加代码。指定单击各个动作项时要做什么。
可以实现onoptionsItemselected()方法来做到。
2.2.2 菜单资源文件
在项目的res文件夹下,创建menu文件夹,所有菜单资源文件全放在这个文件中。
下面的菜单资源文件,描述了动作条溢出区中显示的一个Setting动作项:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never"/>
</menu>
每个菜单资源文件都有一个根元素<menu>。菜单资源文件会定义一个菜单,或者要增加到动作条的一组菜单项。应用可以包含多个资源文件,如果希望动作条上有不同的动作项,这就很有用。
要使用<item>元素为菜单增加菜单项。每个动作项使用一个单独的<item>来描述。<item>元素有很多属性,下面列出其中最常用的一些属性:
关于菜单showAsAction属性:
showAsAction属性用于指示是否希望这一项出现在动作条中。
app:showAsAction
它有三个可选项
1.always:总是显示在界面上
2.never:不显示在界面上,只让出现在右边的三个点中(三个点就是图中的 overflow)
3.ifRoom:如果有位置才显示,不然就出现在右边的三个点中(三个点就是图中的 overflow)
android:showAsAction
这个属性可接受的值有:
1.alaways:这个值会使菜单项一直显示在ActionBar上。
2.ifRoom:如果有足够的空间,这个值会使菜单显示在ActionBar上。
3.never:这个值菜单永远不会出现在ActionBar上。
4.withText:这个值使菜单和它的图标,菜单文本一起显示。
需要注意的是,android和app这两个域不同,其设置也不同,千万不能错!!!!
2.2.3 增加一个新动作项
我们要为动作条增加一个新的动作项来创建订单。这个动作项的标题为“Create Order”,另外有一个图标。
在动作条中使用图标时,可以创建自己的图标,也可以使用Android动作条图标集(icon pack)中高端图标(这个需要下载)。
增加了这些图标之后,在strings.xml中增加一个新的action_create_order字符串:
<string name="action_create_order">Create Order</string>
为menu_main.xml增加菜单项:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item android:id="@+id/action_create_order"
android:title="@string/action_create_order"
android:icon="@drawable/ic_action_new_event"
android:orderInCategory="1"
android:showAsAction="ifRoom" />
<item android:id="@+id/action_share"
android:title="@string/action_share"
android:orderInCategory="2"
android:showAsAction="ifRoom"
android:actionProviderClass="android.widget.ShareActionProvider" />
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>
如果没有足够的空间,新菜单项将在动作条上显示为一个图标。
2.2.4 用onCreateOptionMenu()方法在活动中充气菜单
package com.hfad.bitsandpizzas;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;//onCreateOptionsMenu()方法要使用Menu类
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//实现这个方法会把菜单资源文件中的菜单项增加到动作条
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
// 参数1:菜单资源文件 参数2:是一个Menu对象,表示动作条
return super.onCreateOptionsMenu(menu);
}
}
这个方法将menu_main.xml菜单资源文件中的菜单项增加到动作条Menu对象。
2.2.5 用onOptionsltemSelected()方法响应动作项Action单击
要在单击动作条中的动作项时让活动作出响应,需要实现onOptionsItemSelected()方法。只要单击了动作条中的动作项就会运行这个方法。
onOptionsItemselected ()方法有一个参数,这是一个MenuItem对象,表示动作条上单击的动作项。可以使用MenuItem的getItemId()方法得到动作条上所单击的动作项的ID,来完成一个适当的动作,如启动一个新的活动。
下面是代码:
//MenuItem对象是动作条上单击的动作项
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.action_create_order:
//让创建订单动作项完成一些工作
return true;
case R.id.action_settings:
//AS会为我们创建一个setting项,在这里增加一些代码让它做些工作
return true;
default:
return super.onOptionsItemSelected(item);
}
}
我们要在单击创建订单动作项时,让它启动一个名为OrderActivity的新活动。
2.2.6 创建OrderActivity
我们再创建一个名为OrderActivity的新活动,使创建订单动作项可以启动这个活动。
创建一个新的空活动“CreateActivity”,布局名为“activity_oreder”,标题名“Create Order”,菜单资源名为"menu_order"。
要让该活动的标题名为“Create Order”,需要在AndroidManifest.xml中,对CreateActivity的相关标签做出修改:
<activity android:name=".OrderActivity"
android:label="Create Activity"></activity>
下面给出代码,需要明确的是 OrderActivity扩展Activity类而不是其他类。
public class OrderActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
}
}
OrderActivity代码中没有包含onCreateOptionsMenu()和onOptionsItemselected()方法,因为我们不需要orderActivity在动作条中显示菜单资源文件中的菜单项。如果确实希望显示菜单项,就要增加这些方法。
既然已经创建了orderActivity,下面让MainActivity中的创建订单动作项启动这个活动。
2.2.7 用创建订单动作项启动OrderActivity
单击MainActivity动作条中的创建订单动作时,我们希望它启动orderActivity。为此,需要更新MainActivity中的onOptionsItemSelected()方法。我们将用一个意图启动OrderActivity。
代码:
package com.hfad.bitsandpizzas;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;//onCreateOptionsMenu()方法要使用Menu类
import android.view.MenuItem;
import androidx.annotation.NonNull;
public class MainActivity extends Activity {
//...
//MenuItem对象是动作条上单击的动作项
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.action_create_order:
//让创建订单动作项完成一些工作
Intent intent = new Intent(this, OrderActivity.class);//单击创建订单动作时要用这个意图启动OrderActivity
startActivity(intent);
return true;
case R.id.action_settings:
//AS会为我们创建一个setting项,在这里增加一些代码让它做些工作
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
测试:
2.3 在动作条上共享内容
2.3.1 动作提供者(action provider)
下面要介绍如何对动作条使用一个动作提供者。动作提供者( action provider)是为动作条增加的一个动作项,可以处理它自己的外观和行为。
我们将重点介绍如何使用共享动作提供者。共享动作提供者允许用户与其他应用(如Gmail)共享应用中的内容。例如,你可以使用共享动作提供者让用户向他们的某个联系人发送一个特色披萨的详细信息。
共享动作提供者会定义自己的图标,所以你不需要自行增加。单击这个图标时,它会为你提供一个应用列表,可以使用其中所列的这些应用来共享内容。
2.3.2 用意图共享内容
要让共享动作提供者共享内容,需要为它传递一个意图。所传入的意图定义了你想要共享的内容及其类型。
例如,如果定义了一个意图,要用一个ACTION_SEND动作传递文本,这个共享动作会在你的设备上提供一个应用列表,其中列出的应用都能够共享这种类型的数据。
1.你的活动创建了一个意图,并把它传递到共享动作提供者
这个意图描述了需要共享的内容,它的类型和一个动作。<这里面有三个信息,内容本身,类型和动作>
2.用户单击共享动作时,这个共享动作使用意图为用户提供一个应用列表,其中的应用都能处理这种数据。
用户选择一个应用,共享动作提供者将这个意图传递给可以处理它的应用活动。
2.3.3 为menu_main.xml增加一个共享动作提供者
要为动作条增加一个共享动作,可以把它包含在菜单资源文件中。
需要使用<item>元素向菜单资源文件增加共享动作。不过,这次需要制定你在使用一个共享动作提供者。为此,要增加一个android:actionProviderClass属性,并设置andriod.widget.ShareActionProvider.
下面是增加共享动作的代码:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item android:id="@+id/action_create_order"
android:title="@string/action_create_order"
android:icon="@drawable/ic_action_new_event"
android:orderInCategory="1"
android:showAsAction="ifRoom" />
<item android:id="@+id/action_share"
android:title="@string/action_share"
android:orderInCategory="2"
android:showAsAction="ifRoom"
android:actionProviderClass="android.widget.ShareActionProvider" />
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>
下面就指定要共享什么内容。
2.3.4 用意图指定内容
单击共享动作时,要让它共享内容,需要在活动代码中告诉它要共享哪些内容。为了做到这一点,可以使用共享动作提供者的setShareIntent()方法,为它传递一个意图。
下面的代码可以在单击共享动作时让它共享一些默认文本:
public class MainActivity extends Activity {
//增加一个ShareActionProvider私有变量
private ShareActionProvider shareActionProvider;
//....
//实现这个方法会把菜单资源文件中的菜单项增加到动作条
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);// 参数1:菜单资源文件 参数2:是一个Menu对象,表示动作条
MenuItem menuItem=menu.findItem(R.id.action_share);
shareActionProvider=(ShareActionProvider)menuItem.getActionProvider();//得到共享动作提供者的一个引用,并赋给这个私有变量。然后调用setIntent()方法
setIntent("This is example text");
return super.onCreateOptionsMenu(menu);
}
private void setIntent(String text){
Intent intent=new Intent(Intent.ACTION_SEND);//创建一个意图
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,text);
// 使用共享动作提供者的setShareIntent()方法来传递这个意图
shareActionProvider.setShareIntent(intent);
}
}
只要想要共享的内容发生改变,就需要调用共享动作提供者的setShareIntent()方法。
举例来说,如果你查看一个照片应用中的照片,就要确保共享的是当前的照片。
运行这个应用时,会在动作条中显示共享动作。单击这个共享动作时,它会提供一个应用列表,可以从中选择一个应用接受我们想要共享的意图。选择应用时,它会共享默认文本。
2.4 支持向上导航
2.4.1 活动体系结构
如果应用中包含一个活动层次结构,可以在动作条上启用UP(向上)按钮,利用这个层次关系在应用中当行。
举例来说,在我们的应用中,MainActivity的动作条中包含一个动作项,它会启动第二个活动OrderActivity。如果启用了OrderActivity动作条中的向上按钮,用户通过单击这个按钮就能返回MainActivity。
听上去向上导航可能与后退按钮是一样的,不过实际上他们完全不同。利用后退按钮,用户可以根据已完成的活动历史后退。向上按钮则有所不同,它存储基于应用的层次结构。
使用向上按钮会沿着应用的层次结构向上导航,单击子活动的向上按钮会沿着层次结构进入这个活动的父活动。
2.4.2 设置活动的父活动
利用向上按钮,用户可以在应用的活动层次结构中向上导航。可以在AndroidManifest.xml中指定各个活动的父活动来声明这个层次结构。例如,我们希望用户按下向上按钮时能从orderActivity导航到MainActivity,所以这说明MainActivity是orderActivity的父活动。
从API 16开始,要使用android:parentActivityName属性指定父活动。
对于较老的Android版本,则需要包含一个<meta-data>元素,其中包括父活动的名字。下面在AndroidManifest.xml中同时展示了这两种方法:
最后,需要在OrderActivity中启用向上按钮。
2.4.3 增加向上按钮
要在活动代码中启用向上按钮。首先使用活动的getActionBar()方法得到动作条的一个引用。然后调用动作条的setDisplayHomeAsUpEnabled()方法,并传入一个true值。
ActionBar actionBar=getActionBar();
acitonBar.setDisplayHomeAsUpEnabled(true);
注意: 如果启用一个活动的向上按钮,必须指定它的父活动。
如果没有指定父活动,调用setDisplayHomeAsUpEnabled()方法时会得到一个空指针异常。
想启动OrderActivity中的向上按钮,所以需要在OrderActivity.java的onCreate()方法中增加一些代码。
public class MainActivity extends Activity {
//增加一个ShareActionProvider私有变量
private ShareActionProvider shareActionProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar=getActionBar();
actionBar.setDisplayShowHomeEnabled(true);//这会在动作条中启用向上按钮
}
//...
}
运行应用的结果:
现在可以知道什么是动作条:
3.总结
- 要为支持API11或更高级别的应用增加动作条,可以应用某个Holo或Material主题。
- 要向支持API 7或更高级别的应用增加动作条,可以应用一个AppCompat主题并使用ActionBarActivity类。如果使用ActionBarActivity,就必须使用AppCompat主题。
- ActionBarActivity和AppCompat主题都在v7 appcompat支持库中提供。
- AndroidManifest.xml中的android:theme属性指定要应用哪个主题。
- 在样式资源文件中使用<style>元素定义样式。parent属性指定这个样式从哪里继承属性。
- 样式资源文件的默认文件夹是app/src/main/res/values。如果希望在API 21上使用,要把样式资源文件放在applsrclmain/reslvalues-v21文件夹中。
- 要为菜单资源文件增加菜单项为动作条增加动作项。
- 通过实现活动的onCreateOptionsMenu()方法,可以在菜单资源文件中为动作条增加动作项。
- 通过实现活动的onOptionsItemSelected()方法,可以指定单击动作项时要做些什么。
- 可以为动作条增加共享动作提供者来共享内容。要增加共享动作提供者,可以把它包含在菜单资源文件中。调用共享动作提供者的setShareIntent()方法传入一个意图,描述想要共享的内容。
- 可以为动作条增加—个向上按钮,在应用的层次结构中向上导航。层次结构在AndroidManifest.xml中指定。可以使用ActionBarSetDisplayHomeAsUpEnabled()方法启用向上按钮。