一个Toolbar的UI可以做成什么样?做出什么效果?这是我最近在研究的问题。
目录
除带导航栏的Toolbar、带侧滑菜单栏的Toolbar、滚动页面隐藏Toolbar外,用的都是该xml布局:
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 必须用androidx.appcompat.widget.Toolbar,而不是用ToolBar,用ToolBar有些问题无解 -->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="@color/purple_700"/>
</androidx.constraintlayout.widget.ConstraintLayout>
带导航图标的Toolbar
相关方法 | 描述 |
---|---|
setNavigationIcon(Drawable icon) | 设置导航图标 |
setNavigationOnClickListener(OnClickListener listener) | 设置点击导航按钮监听 |
实现效果:
带标题的Toolbar
相关方法 | 描述 |
---|---|
setTitle(String title) | 设置标题 |
setTitleTextColor(int color) | 设置标题文字颜色 |
setTitleMarginEnd(int margin) | 以px为单位设置标题结束边距 |
setTitleMarginStart(int margin) | 以px为单位设置标题起始边距 |
setTitleMarginTop(int margin) | 以px为单位设置标题头部边距 |
setTitleMarginBottom(int margin) | 以px为单位设置标题底部边距 |
setTitleMargin(int start, int top, int end, int bottom) | 以px为单位设置标题边距 |
setTitleTextAppearance(Context context, int resId) | 设置指定TextAppearance资源的文本颜色、大小、样式、提示颜色和突出显示颜色 |
getTitleMarginEnd() | 获得以px为单位标题的结束边距 |
getTitleMarginStart() | 获得以px为单位标题的起始边距 |
getTitleMarginTop() | 获得以px为单位的标题的顶部边距 |
getTitleMarginBottom() | 获得以px为单位标题的底部边距 |
实现效果:
带小标题的Toolbar
相关方法 | 描述 |
---|---|
setSubtitle(CharSequence subtitle) | 设置副标题文本 |
setSubTitleTextColor(int color) | 设置副标题文本颜色 |
setSubTitleTextAppearance(Context context, int resId) | 设置指定TextAppearance资源的文本颜色、大小、样式、提示颜色和突出显示颜色 |
getSubtitle() | 获得副标题文本 |
实现效果:
带Logo的Toolbar
相关方法 | 描述 |
---|---|
setLogo(int resId) | 设置Logo图标 |
setLogoDescription(CharSequence description) | 设置工具栏标志的描述 |
getLogoDescription() | 获得工具栏标志的描述 |
getLogo() | 返回一个Drawable类型的Logo |
实现效果:
带进度条的Toolbar
相关方法 | 描述 |
---|---|
setTitle(String title) | 设置标题 |
setTitleTextColor(int color) | 设置标题文字颜色 |
setNavigationIcon(Drawable icon) | 设置导航图标 |
setProgress(int progress) | 设置进度条当前进度 |
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="@color/purple_700"/>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="5dp"
app:layout_constraintTop_toBottomOf="@id/toolbar"
app:layout_constraintLeft_toLeftOf="@id/toolbar"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
实现效果:
带菜单的Toolbar
相关方法 | 描述 |
---|---|
setPopupTheme(int resId) | 设置菜单弹出时使用的主题 |
setOverflowIcon(Drawable icon) | 设置溢出按钮的图标 ,默认是3个小黑点 |
inflateMenu(int resId) | 将菜单资源扩充到此工具栏中 |
setOnMenuItemClickListener(OnMenuItemClickListener listener) | 点击菜单的监听事件 |
setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) | 设置菜单回调,必须在访问菜单之前调用 |
getPopupTheme() | 获取弹出菜单的主题的资源标识符 |
getOverflowIcon() | 获取Drawable类型的溢出菜单图标 |
在Toolbar上建一个菜单,那就得建一个menu的文件夹与xml文件
鼠标右击res
文件夹→New
→Android Resource Directory
在弹出的窗口,Resource type
选择menu
即可
点击OK后会在res
文件夹下生成一个menu
文件夹,在这里新建一个xml文件,粘贴一下内容
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/share"
android:title="分享"/>
<item
android:id="@+id/save"
android:title="保存"/>
</menu>
紧接着Toolbar
调用inflateMenu
方法绑定创建的xml
布局即可实现,只是这个时候还没有对这个菜单做个性化,它是默认的3点黑色圆点的效果,使用setOverflowIcon(Drawable icon)
方法对其设置图标后,就成了下面的样子。
点击三个小圆点效果:
两个菜单的Toolbar
设置一个Toolbar
有多个菜单,不需要修改Java代码,只要在menu
文件的对应item
下添加app:showAsAction="always"
即可,showAsAction
有五个参数,分别是:
相关方法 | 描述 |
---|---|
never | 从不在导航栏上显示,一直放在一处菜单列表里面 |
always | 总是在导航栏上显示菜单图标 |
ifRoom | 如果导航栏右侧有空间,该项就直接显示在导航栏上,不再放入溢出菜单 |
withText | 如果能在导航栏上显示,除了显示图标,还要显示该项的文字说明 |
collapseActionView | 操作视图要折叠为一个按钮,点击该按钮再展开操作视图,主要用于SearchView |
实现效果:
标题居中的Toolbar
标题居中这一样式实现并不是用Toolbar
的setTitleGravity
方法,当然也没这样的方法给你。实现标题居中,主要还是得靠Toolbar里的子组件:
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题"
android:textSize="16sp"
android:textColor="@color/white"
android:layout_gravity="center"
android:visibility="invisible"/>
在Toolbar
里加上TextView
,我们提前在布局上将TextView
居中于父组件之中,需要将标题居中的时候调用setVisibility
方法,放置View.VISIBLE
参数即可将标题居中的样式展示出来。
实现效果:
值得注意的是,在设置各种各样的Toolbar
子组件时,切互将子组件的宽度设置为match_parent
,子组件的宽度过大,会使Toolbar
的一些样式被子组件所覆盖。
带搜索框的Toolbar
带搜索框的Toolbar
,使用的是SearchView
实现。实现的这一效果,特别需要注意,一定要加上setSupportActionBar(Toolbar toolbar)
且将它放在Toolbar
初始化后的一行。
接着,重写onCreateOptionsMenu(Menu menu)
方法,使用Menu
的打气筒绑定一个menu
,写一个initSearchView(menu: Menu)
方法设置SearchView
的一些样式
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_toolbar3,menu)
initSearchView(menu!!)
return super.onCreateOptionsMenu(menu)
}
fun initSearchView(menu: Menu){
val item = menu.findItem(R.id.search)
// 获取搜索框对象
val searchView = item.actionView as SearchView
searchView.isIconified = true
// actionView.setIconifiedByDefault(getIntent().getBooleanExtra("collapse",true));
// 设置是否显示搜索按钮
searchView.isSubmitButtonEnabled = true
// 从系统服务获取搜索的管理器
val systemService = getSystemService(SEARCH_SERVICE) as SearchManager
// 创建搜索结果页面的组件名称对象
val componentName = ComponentName(this, BackButtonActivity::class.java)
// 从结果页面注册的activity结点获取相关搜索信息,即searchable.xml定义的搜索控件
val searchableInfo = systemService.getSearchableInfo(componentName)
// 设置搜索框的可搜索信息
searchView.setSearchableInfo(searchableInfo)
// 从搜索框中获取名叫search_src_text的自动完成编辑框
val search_text: SearchAutoComplete = searchView.findViewById(R.id.search_src_text)
// 设置文本颜色
search_text.setTextColor(Color.BLACK)
// 设置自动完成编辑框的提示文本颜色
search_text.setHintTextColor(Color.BLACK)
// 设置文本类型
searchView.inputType = InputType.TYPE_CLASS_TEXT
// 设置搜索提示文本
searchView.queryHint = "请输入搜索内容"
// 为搜索框设置文本变化监听
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
// 搜索关键词完成输入
Toast.makeText(this@BackButtonActivity, "最终输入结果:$query", Toast.LENGTH_SHORT).show()
return false
}
override fun onQueryTextChange(newText: String): Boolean {
// 搜索关键词发生变化
Toast.makeText(this@BackButtonActivity, "关键词发生改变:$newText", Toast.LENGTH_SHORT).show()
return false
}
})
}
哦,对了,这玩意还得在AndroidManifest.xml
的application
节点下加点代码
<activity android:name="使用SearchView的Activity">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
实现效果:
点击搜索按钮效果:
由于SearchView
的控件是private
与protected
属性,并不能调用相关的取消、确定图标组件,理论上说是无法修改这些icon
,使得能修改的样式极其有限,使用范围也大大缩减。
带导航栏的Toolbar
带导航栏的Toolbar
效果与Toolbar
标题居中同理,皆是在Toolbar
组件里面加一个子组件,只是这个子组件加的是TabLayout
,这个时候还没能实现TabLayout
居中的效果,TabLayout
的文本默认是靠左的,需要再嵌套一个布局,将TabLayout
放在布局里面,用上android:gravity="center"
就可以居中了。
xml代码:
<LinearLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".custon.Custon1Activity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/purple_700">
<LinearLayout
android:id="@+id/linear"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpage"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
实现效果:
带侧滑菜单栏的Toolbar
第一次做侧滑菜单,参考了几年前的一个例子,用的是动画+监听屏幕滑动+屏幕滑动后的各种操作。那个例子给我的体验就是,真TM复杂,效果还差的离谱,不优化完全用不了呀!
直到DrawerLayout
的出现,问题也随之迎刃而解~
带侧滑菜单栏需要以androidx.drawerlayout.widget.DrawerLayout
为根布局,DrawerLayout
官网给的解释是实现一个材质设计抽屉小部件。
在以DrawerLayout
为根Layout
的xml
文件可以编写两个界面,分别是Toolbar
界面与侧滑菜单界面,要想展示侧滑菜单,必须在侧滑界面的第一层加上android:layout_gravity="left"
以表示从左边出现。
随后监听Toolbar
的点击事件,当用户点击时执行drawer.openDrawer(GravityCompat.START)
展示侧滑菜单。
<androidx.drawerlayout.widget.DrawerLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".custon.Custon2Activity"
android:id="@+id/drawer">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
<!-- layout_gravity必须设置,值标识侧滑的方向 -->
<LinearLayout
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:orientation="vertical"
android:background="@android:color/white">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="侧滑菜单"/>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
实现效果:
滚动页面隐藏Toolbar(一)
CoordinatorLayout
定位顶级应用程序小部件,如AppBarLayout
、FloatingActionButton
。
布局代码就贴出来了,想说也不懂说啥,全是xml代码,(⊙︿⊙)
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".custon.Custon3Activity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" >
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:contentInsetStart="0dp"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
实现效果:
本文代码:Toolbar使用解析
滚动页面隐藏Toolbar(二)
使用的组件:
AppBarLayout
:实现了材料设计应用栏概念的许多功能,即滚动手势。
CoordinatorLayout
:实现折叠应用栏的包装器。
NestedScrollView
:支持在新旧版本的 Android 上同时充当嵌套滚动父项和子项。默认情况下启用嵌套滚动。
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="180dp"
android:fitsSystemWindows="true"
android:theme="@style/AppBarOverlay">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/toolbar"
android:background="@drawable/a">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/PopupOverlay" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<!-- 滚动文本 -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".ScrollingActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="@string/large_text" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
实现效果:
参考文献:
1、简书文章:Toolbar的使用
2、《Android Studio 开发实战 从零基础到APP上线》第二版第7章组合控件
3、《第一行代码》第3版第12章—最佳的UI体验,Material Design实战