一、ActionBar(标题栏)
android.app.ActionBar
是 Android 3.0(API 11) 引入的界面顶部导航控件。如果需要在 3.0 以下使用 ActionBar,需要先引入 Support Library ,然后使用 Support Library 里的android.support.v7.app.ActionBar
。需要注意的是,使用不同包下的 ActionBar 时,操作的 API 也不相同。
使用系统提供的 ActionBar,可以自适应不同大小的手机屏幕、指明当前用户正在操作的界面、提供界面导航、搜索、下拉菜单等功能,是 Activity 设计中非常重要的元素。
由于 ActionBar 是受 Framework 层的控制,而不是 Activity 内容的一部分,某种程度上限制了 Android app 开发的灵活性,因此在 Android 5.0(API 21) 时引入了直接在 Activity 内容中设计的 ToolBar。
接下来以 android.support.v7.app.ActionBar
进行介绍,使用
android.support.v7.app.ActionBar
必须为 AppCompatActivity 的子类,且主题必须为 AppCompat 家族的主题。
1、ActionBar 的显示与隐藏
// == 显示 ==
// 使用带 ActionBar 的主题
android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
// == 隐藏 ==
// 方式1:指定无 ActionBar 主题
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
// 方式 2:Java 代码
getSupportActionBar().hide();
// 方式 3:在 setContentView 方法前调用 supportRequestWindowFeature 方法
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
注意:
requestWindowFeature(Window.FEATURE_NO_TITLE) 是针对 android.app.ActionBar
的隐藏,而 supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 是针对 android.support.v7.app.ActionBar
的隐藏。
2、 ActionBar 返回键
// 1、显示系统默认的返回键
ActionBar actionBar = getSupportActionBar();
if (actionBar != null)
actionBar.setDisplayHomeAsUpEnabled(true);
// 2、修改返回键图标
// 通过配置主题修改
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!-- 返回键图标 -->
<!-- 需要调用 ActionBar 的 setDisplayHomeAsUpEnabled 方法才能生效 -->
<item name="homeAsUpIndicator">@drawable/ic_navigate_before_black</item>
</style>
// 通过 Java 代码修改
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true); // 需要调用这个方法才能生效
actionBar.setHomeAsUpIndicator(R.drawable.ic_navigate_before_black_24px);
}
// 3、重写 Activity 的 onOptionsItemSelected 方法监听返回键点击
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
}
return true;
}
3、ActionBar 动作键
// 第一步:新建 res/menu 目录用于存放动作菜单文件
<?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"
android:title="menu"
android:icon="@drawable/ic_menu_black"
app:showAsAction="always"
/>
</menu>
// 第二步:重写 Activity 的 onCreateOptionsMenu 方法加载菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar,menu);
return true;
}
// 第三步:重写 Activity 的 onOptionsItemSelected 方法对菜单点击监听@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu:
Toast.makeText(ScreenAty.this, "menu", Toast.LENGTH_LONG).show();
break;
}
return true;
}
4、修改 ActionBar 背景
// 1、通过主题修改
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- 标题栏背景 -->
<item name="colorPrimary">#ff0000</item>
<!-- 状态栏背景-->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!-- 操作控件颜色,如 EditText 的光标、RadioButton 等 -->
<item name="colorAccent">@color/colorAccent</item>
</style>
// 2、通过 Java 代码
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.GREEN));
5、自定义 ActionBar 布局
ActionBar actionBar = getSupportActionBar();
View customAcbView = getLayoutInflater().inflate(R.layout.view_acb,null);
ActionBar.LayoutParams alp = new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT,ActionBar.LayoutParams.MATCH_PARENT, Gravity.CENTER);
actionBar.setCustomView(customAcbView,alp);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
actionBar.setElevation(0);
二、ToolBar
android.widget.ToolBar
是在 Android 5.0(API 21) 推出的导航控件,可以说它的出现就是替代原来的 ActionBar。和 ActionBar 一样,Google 也提供了向下兼容的 Support Library。如需在 Android 5.0(API 21) 以下使用 ToolBar,需要先引入 Support Library,然后使用 Support Library 库中提供的 android.support.v7.widget.ToolBar
。同样地,使用不同的 ToolBar 操作 API 也不相同。
ToolBar 可直接在 Activity 内容中编辑,因此具有比 ActionBar 更好的灵活性; 同时,ToolBar 支持 material design 风格。
接下来以 android.support.v7.widget.ToolBar
进行介绍。
1、添加 ToolBar
ToolBar 的使用可以像一般控件那样添加到窗口控件中的任何位置。可在 xml 布局文件中直接添加,也可以在代码中添加,由于导航栏一般都是位于一个界面的顶部,所以我们通常在 xml 布局文件中添加。
** 添加方式 1:xml 布局文件中添加 ToolBar**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="#ff0000" />
</LinearLayout>
** 添加方式 2:Java 代码动态添加 ToolBar **
xml 布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
</LinearLayout>
Java 代码
// ToolBar 父容器
ll = (LinearLayout) findViewById(R.id.ll);
// ToolBar 高度
int toolBarHeight = 80;
TypedValue typedValue = new TypedValue();
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, typedValue, true)){
toolBarHeight = TypedValue.complexToDimensionPixelSize(typedValue.data, getResources().getDisplayMetrics());
}
// 设置 ToolBar
Toolbar toolbar = new Toolbar(this);
toolbar.setBackgroundColor(Color.RED);
toolbar.setLayoutParams(new Toolbar.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, toolBarHeight));
// 可添加到任意位置
ll.addView(toolbar,0);
注意:
由于 ToolBar 与 ActionBar 都是起导航的作用,所以我们在使用了 ToolBar 之后可将 ActionBar 隐藏。但是两者完全可以共存(亲测)。网上有人说使用 ToolBar 必须将 ActionBar 隐藏掉,其实没那么绝对。
但是如果调用了setSupportActionBar(android.support.v7.widget.ToolBar toolbar)
、setActionBar(android.widget.ToolBar toolbar)
方法将 ToolBar 设置到系统 ActionBar 时,就必须隐藏掉系统 ActionBar,而且必须是使用设置无 ActionBar 主题的方式来隐藏(参见上面 ActionBar 的隐藏方式),否则会报以下错误:
java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
2、设置 ToolBar 属性
方式 1:xml 布局文件中直接设置
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="#ff0000"
toolbar:title="ToolBar"
toolbar:navigationIcon="@drawable/ic_navigate_before_black"
toolbar:subtitle="456"
toolbar:contentInsetLeft="0dp"
toolbar:contentInsetStart="0dp"
toolbar:contentInsetEnd="0dp"
toolbar:contentInsetRight="0dp"
>
</android.support.v7.widget.Toolbar>
</LinearLayout>
注意:
在 xml 布局文件中设置 ToolBar 属性时命名空间需要改为非 「android」 的其它任意字符,如上面代码中改为了 toolbar。否则属性将不会生效。
方式 2:Java 代码中设置
Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
toolbar.setTitle("ToolBar");
toolbar.setBackgroundColor(Color.RED);
toolbar.setNavigationIcon(R.drawable.ic_navigate_before_black);
// ...
3、为 ToolBar 添加动作项
res/menu/toolbar.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"
android:title="menu"
android:icon="@drawable/ic_menu_black"
app:showAsAction="always"
/>
</menu>
添加方式 1:
当调用了setSupportActionBar(android.support.v7.widget.ToolBar toolbar)
或 setActionBar(android.widget.ToolBar toolbar)
方法将 ToolBar 设置到系统 ActionBar 时:
// 重写 Activity 的 onCreateOptionsMenu(Menu menu) 方法渲染菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar,menu);
return true;
}
// 监听方式 1:重写 Activity 的 onOptionsItemSelected(MenuItem item) 方法
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.menu:
Toast.makeText(ScreenAty.this,"menu",Toast.LENGTH_LONG).show();
}
return true;
}
// 监听方式 2
Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.menu:
Toast.makeText(ScreenAty.this,"menu",Toast.LENGTH_LONG).show();
}
return true;
}
});
添加方式 2
未调用setSupportActionBar(android.support.v7.widget.ToolBar toolbar)
或 setActionBar(android.widget.ToolBar toolbar)
方法将 ToolBar 应用到系统 ActionBar 中。
// 直接调用 inflateMenu 方法添加菜单
Toolbar toolbar = (Toolbar) findViewById(R.id.toolBar);
toolbar.inflateMenu(R.menu.toolbar);
// 只能使用这种方式监听
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItekwmClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.menu:
Toast.makeText(ScreenAty.this,"menu",Toast.LENGTH_LONG).show();
}
return true;
}
});
4、自定义 ToolBar 布局
由于 ToolBar 继承至 ViewGroup,所以它可以包含任意子 View。如果我们的子 View 也是一个容器控件,那么我们就可以在这个容器控件中自由地摆放其它 View,从而达到自定义 ToolBar 布局。但这样做的前提是不要再设置 ToolBar 的标题、子标题、menu 等占位的属性。具体代码如下所示:
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="#ff0000"
toolbar:contentInsetLeft="0dp"
toolbar:contentInsetStart="0dp"
toolbar:contentInsetEnd="0dp"
toolbar:contentInsetRight="0dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:layout_centerInParent="true"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
三、Status Bar(状态栏)、Nav Bar(导航栏)
Status Bar 一直都存在于 Android 设备中,Nav Bar 是 Android 4.0(API 14) 才引入的,虽然它们的引入都比较早,但在早期的系统中,它们各自的很多属性都不能被操作,慢慢地相关属性的操作才随系统的升级添加进来。
对 Status Bar、Nav Bar 的操作方式大致相同,因此放在一起介绍。
1、隐藏
方式 1:通过配置主题
// 同时隐藏 Status Bar、Nav Bar,需是 Activity 的直接子类且 minSdkVersion >= 11
android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen"
方式 2:通过 Java 代码
// 隐藏 Status Bar
if (Build.VERSION.SDK_INT < 16) {// Android 4.1 以下设备
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}else{// Android 4.1 及以上设备
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
// 隐藏导航栏,Android 4.0 以上
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
// Status Bar、ActionBar、Nav Bar 同时隐藏
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION );
2、漂浮(API >= 16)
使 Status Bar、Nav Bar 漂浮,即 Activity 布局内容可以显示在 Status Bar、Nav Bar下面。
// Status Bar 漂浮
if (Build.VERSION.SDK_INT >= 16)
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
// Nav Bar 漂浮
if (Build.VERSION.SDK_INT >= 16)
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
3、修改颜色(API >= 21)
方式1:通过配置主题
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- ActionBar -->
<item name="colorPrimary">@color/colorPrimary</item>
<!-- Status Bar-->
<item name="colorPrimaryDark">@android:color/transparent</item>
<!-- EditText、CheckBox 等交互控件 -->
<item name="colorAccent">@color/colorAccent</item>
<!-- Nav Bar,需要配置在 values-v21 目录中-->
<item name="android:navigationBarColor">#0000ff</item>
</style>
方式 2:通过 Java 代码
// Status Bar
if (Build.VERSION.SDK_INT >= 21) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(Color.BLUE);
}
// Nav Bar
if(Build.VERSION.SDK_INT >= 21)
activity.getWindow().setNavigationBarColor(Color.YELLOW);
4、透明(API >= 19)
方式 1:通过配置主题
在 res 目录下新建 values-v19 、values-v21目录,并在 values-v19 、values-v21 目录下新建一个和 values 目录相同的用于主题配置的文件(一般是 styles.xml)。 注意:values-v19、values-v21 目录下有的主题,在 values 目录下也应该有一套,不然低版本运行时会报找不到主题的错误。
res/values-v19/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 方式1 -->
<style name="transparentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Status Bar -->
<item name="android:windowTranslucentStatus">true</item>
<!-- Nav Bar-->
<item name="android:windowTranslucentNavigation">true</item>
</style>
<!-- 方式2使 Status Bar 透明, 应用的界面必须为 Activity 的子类,不能为 AppCompatActivity 的子类-->
<style name="transparentStatusBarHoloTheme" parent="@android:style/Theme.Holo.Light.NoActionBar.TranslucentDecor">
<!-- Status Bar-->
<item name="android:windowTranslucentNavigation">false</item>
</style>
</resources>
res/values-v21/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="transparentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Status Bar-->
<item name="colorPrimaryDark">@android:color/transparent</item>
<!-- Status Bar-->
<item name="android:statusBarColor">@android:color/transparent</item>
<!-- Nav Bar -->
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>
res/values/styles.xml
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="transparentTheme" parent="AppTheme">
</style>
<style name="transparentStatusBarHoloTheme" parent="AppTheme">
</style>
</resources>
方式 2:通过 Java 代码
// Status Bar
if(Build.VERSION.SDK_INT >= 19){
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
// Status Bar
if(Build.VERSION.SDK_INT >= 21){
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(Color.TRANSPARENT);
}
// Nav Bar
if (Build.VERSION.SDK_INT >= 19)
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
注意:
当 Status Bar 、Nav Bar 透明后,有可能会占据原来的位置,此时默认会显示 Activity 顶级View(DecorView)的背景(白色),这时不要误以为透明未成功。下面的代码可设置 DecorView 的背景:
activity.getWindow().getDecorView().setBackgroundColor(ContextCompat.getColor(this,android.R.color.darker_gray));
五、沉浸模式(API >= 19)
所谓沉浸模式,就是将系统栏(状态栏、ActionBar、ToolBar、导航栏)全部隐藏掉,使界面只剩下 Activty 的内容。是 Android 4.4 引入的一种模式。
1、进入沉浸模式
if (Build.VERSION.SDK_INT >= 19) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE);
}
2、退出沉浸模式
if (Build.VERSION.SDK_INT >= 19) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
3、沉浸模式的分类
View.SYSTEM_UI_FLAG_IMMERSIVE
进入此沉浸模式后,当用户在状态栏或导航栏区域向屏幕中心滑动时,系统栏会重新显示出来,显示后就不会再自动隐藏。
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
进入此沉浸模式后,当用户在状态栏或导航栏区域向屏幕中心滑动时,Status Bar、Nav Bar
又会重新显示,过一会儿又会自动隐藏。如果退出沉浸模式是通过调用上面退出沉浸模式方法,则不会再自动进入沉浸模式。
六、总结
- 文章中同一操作有的有多种方式,可根据具体情况选择最佳方式。
- 本文介绍的大部分系统栏的操作和具体系统相关,难免会有错误的结论,望大家批评指正,我会尽快加以验证。
网友评论