今天我们来聊一聊有关AppCompat,作为Android Jetpack系列文章的开篇。说到Android Jetpack,我们先看一下这张图:



从图中我们可以看到,整个Android Jetpack分为了四大部分,而我们今天要讲述的就是Foundation中的AppCompat小节,官方将该部分翻译为“基础”。

Google官方网站:

https://developer.android.com/jetpack

按照Google官方的描述,AppCompat就是指v7 appcompat库。

“This library adds support for the Action Bar user interface design pattern. This library includes support for material design user interface implementations.”

意思是:此库添加了对操作栏用户界面设计模式的支持。这个库包括对Material Design用户界面实现的支持。也就是说,我们可以借助该库,对Material Design有更便捷和兼容性更好的实现。

进入AppCompat章节后,我们发现它又被分为了4个部分,这4个部分被称为“key class”,也就是重点类,它们分别是:

  • ActionBar:提供Actionbar用户界面模式的实现;
  • AppCompatActivity:添加可用作使用支持库操作栏实现的Activity的基类;
  • AppCompatDialog:添加一个可用作AppCompat主题的Dialog的基类;
  • ShareActionProvider:添加对可包含在ActionBar中的标准化共享操作(如电子邮件或发布到社交应用程序)的支持。

想要使用这些类,我们需要添加v7支持库。

到现在为止,支持库的最新版本是28,添加的库名称和版本如下:

com.android.support:appcompat-v7:28.0.0

今天我们就先来聊一聊ActionBar,也是这里面最为复杂的一个部分。

依稀记得,伴随着Google I/O 2014的召开,早在Android 5.0的时代,Google 官方推出了ToolBar组件,在那之后,ToolBar就登上了历史舞台,扮演着重要的角色。之前我在CSDN上面也发表过相关主题的文章,因为发布的时机刚好是ToolBar登场之际,所以获得了很多的阅读量。快5年过去了,回头再看那几篇连载,感觉文笔很是稚嫩。今天借着讲述Jetpack,再次聊聊ToolBar那些事,相信你我都会有新的收获。

首先解决疑问:

  1. 问:既然有了ActionBar,为何还要用ToolBar? 答:使用AppCompat Toolbar能兼容更广泛的设备(ActionBar要求最低Android 3.0,ToolBar要求最低Android 2.1,但只有Android 5.0及以上才能在不使用AppCompat兼容包的前提下支持Material Design),以及各式各样的自定义需求。

  2. 问:ToolBar上面都应该包含哪些内容? 答:根据Google的指导,应用栏区域应具备以下要素:1)一个专用区域,可以标识您的应用并指示用户在应用中的位置;2)以可预测的方式访问搜索等重要操作;3)支持导航和视图切换(通过标签页或下拉列表)。

一、添加ToolBar

想要添加一个ToolBar,总共3步走:

1. 更改application主题样式,操作对象:styles.xml。

对于新建的Android项目,AndroidManifest.xml中已经定义了所使用的theme,即:

android:theme="@style/AppTheme"

此时,我们修改styles.xml文件即可,将默认的继承值改掉,如下所示:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

2. 在Activity布局中添加ToolBar,操作对象:layout布局文件

<android.support.v7.widget.Toolbar
android:id="@+id/activity_main_tb"
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" />

对高度掌握不好火候的同学,直接如上使用ActionBar的高度就可以了。

android:evevation指“仰角”,这部分知识请参考:

https://developer.android.com/training/material/shadows-clipping

这里就不再赘述了。

如果你的项目已经迁移到Android X,你的布局文件代码片应该是:

<androidx.appcompat.widget.Toolbar
android:id="@+id/activity_main_tb"
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" />

3. 在Activity类中找到ToolBar,并应用它,操作对象:Activity类

这一步并不复杂,参考普通的Android控件。类似地,我们通过findViewById()找到ToolBar,并做执行一些设定,即可完成该步骤,示例如下:

private Toolbar topTb;
topTb = findViewById(R.id.activity_main_tb);
setSupportActionBar(topTb);

一旦我们setSupportActionBar()后,日后我们就可以通过getSupportActionBar()方法来获取ToolBar实例,也可以使用兼容包提供的ActionBar的各种API方法了。

到此,我们就完成了ToolBar的添加,还算简单吧?

二、ToolBar外观的自定义

不出意外的话,我们运行的结果将会和下图类似:



大绿底,大黑字,实在不怎么好看。

那么,如果我们想要自定义配色方案,该如何做呢?参考下图:



这些值我们都可以在color.xml中定义,并在styles.xml中引用。下图是一个重新定义配色方案后的截图:



相关的代码片:

color.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#002FA7</color>
<color name="colorPrimaryDark">#001F67</color>
<color name="colorAccent">#003FB7</color>
<color name="textColorPrimary">#FFFFFF</color>
</resources>

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorPrimary">@color/textColorPrimary</item>
</style>

细心的读者会发现,后面的截图中,右上角多了菜单项,这又是如何实现的呢?我们继续往后看。

三、给ToolBar增加动作

首先我们来看看如何给ToolBar增加菜单,我们依然分为3步完成。

1. 编写菜单xml文件,操作对象: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_main_info"
android:title="@string/menu_main_activity_info"
app:showAsAction="never" /> <item
android:id="@+id/menu_main_search"
android:title="@string/menu_main_activity_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
</menu>

如上,我们可以看到有两个item,分别对应Info和搜索,我们使用"app:showAsAction"的值来控制这个菜单是否显示,常见的值有always,ifRoom,never。从字面上也很好理解,这里就不多解释了。

2. 接下来是Java代码片段:

private SearchView tbSearchSv;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_activity_menu, menu);
MenuItem searchItem = menu.findItem(R.id.menu_main_search);
tbSearchSv = (SearchView) searchItem.getActionView();
return super.onCreateOptionsMenu(menu);
}

细心的朋友会发现有这一行:

app:actionViewClass="android.support.v7.widget.SearchView"

它是做什么的呢?



对了!它就是搜索栏,是原生的搜索栏。所以某些情况下,这个搜索栏是不用自己去实现的,系统已经给我们提供了SearchView!

典型的APP:网易云音乐、知乎上方的搜索都是这样的。

3. 为菜单设置监听器,我们先来看最普通的Info按钮,我们只需在Java代码中Override指定的方法就可以了,如下所示:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_main_info:
Toast.makeText(MainActivity.this, R.string.menu_main_activity_info, Toast.LENGTH_LONG).show();
break;
}
return super.onOptionsItemSelected(item);
}

对于搜索栏,首先我们想到的是,如何获取用户输入的内容呢?

其实很简单,玄机在于SearchView,只需对SearchView添加监听器就可以了。

tbSearchSv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) { return false;
} @Override
public boolean onQueryTextChange(String s) { return false;
}
});

这里要注意,设置监听器前,要确保SearchView(这里的tbSearchSv)已经被实例化,否则,会出现空指针异常崩溃。

关于SearchView,还有一写额外的设置,比如:

// 设置提交按钮是否可见(默认不可见)
tbSearchSv.setSubmitButtonEnabled(true);

// 设置左侧是否显示搜索图标(默认不可见)
tbSearchSv.setIconifiedByDefault(false);



更多可使用的API请参考官方文档:

https://developer.android.google.cn/reference/android/widget/SearchView

不过,我们这里还需要做最后一点善后。如果你是一路下来照着本篇文章敲代码的话,在搜索框打开的情况下按一下返回键,你期待的是什么?是不是取消搜索操作,停留在当前界面?然而实际上是……退出了APP。

所以我们这里要对返回键的默认动作做一个“拦截”,具体可参考如下代码片:

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (!tbSearchSv.isIconified()) {
tbSearchSv.setIconified(true);
return true;
}
break;
}
return super.onKeyUp(keyCode, event);
}

这里SearchView的isIconfied()方法可以返回当前的SearchView展开状态。

四、返回上一层

ToolBar还有一个比较常见的功能就是左上角的返回按钮,提供返回上一层操作,很多的APP开发者都习惯于自定义一个ImageButton或类似的空间,然后使用美工提供的图像素材,设置监听器,写Selector……一套下来,费时费力。

其实Google已经为开发者提供了现成的非常易用的返回逻辑处理。要实现这些处理,两步就搞定了。

1. 在ToolBar对象上启用返回钮

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

这里注意,虽然之前将ToolBar通过setSupportActionBar()方式当做参数被set了一次,但是ToolBar类本身并不提供setDisplayHomeAsUpEnabled()方法,因此,我们还需要getSupportActionBar(),先获取ActionBar对象,然后使用该对象,而不是直接使用ToolBar对象。

2. 在AndroidManifest.xml中定义要跳转的Activity

如题,我们在AndroidManifest.xml中,对子Activity做处理,这里不要忘记兼容低版本的系统。

<activity
android:name=".MainActivity"
android:parentActivityName=".SecondActivity">
<!-- 兼容 Android4.0 及以下版本-->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".SecondActivity" />
</activity>

将SecondActivity改为入口Activity,然后重新运行程序,将实现如下效果:



到此,关于ToolBar常见用法的梳理告一段落。源码请自取:

https://github.com/wh1990xiao2005/JetpackDemo

我会在接下来的文章中,和大家分享关于ToolBar的剩余内容,以及AppCompat兼容包中的其他知识,希望对你我都有帮助。

共勉!

Android Jetpack之AppCompat(一)的更多相关文章

  1. Android Jetpack All In One

    Android Jetpack All In One 在2018年,我们推出了Android Jetpack作为一组库,以帮助开发人员遵循最佳实践,减少样板代码以及编写可在Android版本和设备之间 ...

  2. Android关于Theme.AppCompat相关问题的深入分析(转)

    http://www.jianshu.com/p/6ad7864e005e 先来看这样一个错误: No resource found that matches the given name '@sty ...

  3. Android增加v7 appcompat源码

    1.File ---- Import---- Existing Android Code Into Workspace 2.选择 <sdk>/extras/android/support/ ...

  4. Android Jetpack 组建介绍(二)——Lifecycler

    参考Android Jetpack架构组件之 Lifecycle(源码篇) 源码分析 关于Lifecycle的使用考上一篇文章Android Jetpack框架之 Lifecycles(使用篇),从使 ...

  5. Android Jetpack 组建介绍(一)——Lifecycler

    转自带你领略Android Jetpack组件的魅力 Android Jetpack 对于任何一个产品来说,我们开发中都会面对哪些问题?如:产品交互.用户体验.代码结构.数据获取.数据存储.网络优化. ...

  6. xamarin android 报错 Could not load assembly 'Xamarin.Android.Support.v7.AppCompat

    严重性 代码 说明 项目 文件 行 禁止显示状态 错误 Exception while loading assemblies: System.IO.FileNotFoundException: Cou ...

  7. Android Jetpack 概述

    Android Jetpack Overview Android Jetpack Jetpack is a set of libraries, tools and architectural guid ...

  8. Android Jetpack - 使用 Navigation 管理页面跳转

    在今年的 IO 大会上,发布了一套叫 Android Jetpack 的程序库.Android Jetpack 里的组件大部分我们都接触过了,其中也有一些全新的组件,其中一个就是 Navigation ...

  9. 带你了解Android Jetpack

    1.Jetpack主要特性有以下三点: 1.加速开发组件可单独使用,也可以协同工作,当使用kotlin语言特性时,可以提高效率. 2.消除样板代码Android Jetpack可管理繁琐的Activi ...

随机推荐

  1. CXF整合spring

    近公司需要弄webservics,还说不用框架整合(提倡使用hessian,他们既然说与操作系统有兼容问题,由于人员单薄,不得不屈服,哎),我想了老半天没弄明白他说的不用框架整合spring,尝试过直 ...

  2. Flask开发微电影网站(二)

    1.安装数据库连接依赖包 pip install flask-sqlalchemy 2.创建movie数据库 在CentOS虚拟机,进入MaridDB数据库提示符,创建movie数据库 create ...

  3. python函数调用的四种方式 --基础重点

    第一种:参数按顺序从第一个参数往后排#标准调用 # -*- coding: UTF-8 -*- def normal_invoke(x, y): print "--normal_invoke ...

  4. JS 总结----基础部分

    javascript基础:1.每个属性都可以加ID2.写函数的时候注意 == 和 = 不要写错了3.html里面怎么写js里面就怎么写,但是有一例外 className 比如oDiv.class = ...

  5. CSS简写总结

    CSS简写就是指将多行的CSS属性简写成一行,又称为CSS代码优化或CSS缩写.CSS 简写的最大好处就是能够显著减少CSS文件的大小,优化网站整体性能,更加容易阅读. 下面介绍常见的CSS简写规则: ...

  6. 手机端实现fullPage——全屏滚动效果

    封装了一个小插件模拟fullPage的全屏滚动效果,比较简单. 特点: 1.  纯js实现,小巧轻便. 2.  兼容性好.苹果.安卓都没问题,暂时没遇到问题机型. 缺点: 1.  仅封装了基础功能,H ...

  7. 7. 整合shiro,搭建粗粒度权限管理

    shiro是一个易用的权限管理框架,只需提供一个Realm即可在项目中使用,本文就将结合上一篇中搭建的权限模块.角色模块和用户模块来搭建一个粗粒度的权限管理系统,具体如下:1. 添加shiro依赖和与 ...

  8. React从入门到放弃之前奏(3):Redux简介

    安装 npm i -S redux react-redux redux-devtools 概念 在redux中分为3个对象:Action.Reducer.Store Action 对行为(如用户行为) ...

  9. 开机出现loading Operating System的解决方案

    今天清理机箱之后开机发现电脑屏幕出现以下界面,提示的内容是"正在加载操作系统,磁盘启动失败,请插入系统盘..",出现这种状况的原因有以下几种: 1.主引导的扇区的损坏或者信息的错乱 ...

  10. 使用limit查询的同时取得总的记录数:SQL_CALC_FOUND_ROWS和FOUND_ROWS()

    通常我们都用如下的sql来进行列表 SELECT COUNT(*) FROM users WHERE name LIKE 'a%';SELECT name, email FROM users WHER ...