关键字:Toolbar、材料设计、ActionMenu
项目地址:AboutMaterialDesign
关于官方文档的介绍部分,我已经在上一篇写过,如果没有使用过 Toolbar 的话,可以先看看这篇:链接
好,那么下面,我们接着之前的 ActionMenu 内容测试。
先上几个效果图:
GIF.gif 效果图.png
一、测试效果1 - ActionMenuView
GIF.gif这里主要有几个问题:
- 首先是我遇到的:
- 改变单个 item 默认宽度
- 图片点击时,背景色变化的属性
- 添加上述属性后,出现默认背景
- menuItem 默认靠右
- 其次是没有遇到,但是可能会有问题的
- 布局是 上Toolbar 下LinearLayout,颜色浅的时候 toolbar 的 Z 轴可能会有比较明显的分割
- 其他,忘了 = =
1.1 正确显示 MenuItem
- 首先,为了让 MenuItem 全部展示在 Toolbar 上面,我们需要在 menu.xml 中,把所有 item 的 showAsAction 属性设置为 always 。去掉设置在 Toolbar 中所有的视图,logo title subTitle 等等属性都应该从 xml 中剔除。然后我们会得到下面的效果:
-
好吧,上面的效果你可能复现不出来,因为不同的机型展示大概会不同,起码我这里确实是有两种情况。
-
那么这里为什么已经去掉的 title 属性还是显示出来了呢?我们知道,如果不给 Toolbar 设置 title 那么 Toolbar 会自动获取 app_name 作为自己的 title。为此,我在 onCreate 中调用了 mToolbar.setTitle(null) 方法,但是结果并没有改变。
通过一系列测试,我发现,这个获取 app_name 作为自己的 title 是在 onCreate - onResume 之间发生的,因此,我在 onResume 中调用了 mToolbar.setTitle(null) 期望能解决这个问题:
@Override
protected void onResume() {
super.onResume();
mToolbar.setTitle(null);
}
效果如下:
效果图.png
后来发现一个方法,不用在 onResume 里单独处理这个逻辑,放 onCreate 里就可以了,效果相同:
getSupportActionBar().setDisplayShowTitleEnabled(false);//不显示title
getSupportActionBar().setDisplayHomeAsUpEnabled(false);//不显示NavigationIcon
getSupportActionBar().setDisplayShowHomeEnabled(false);//不显示logo
- 现在我们已经去除了无用的视图,但是 MenuItem 还是默认靠右的布局,这一点在 Toolbar 中可以看到相关源码。这一点,我没有想到更聪明的办法。不过我没有选择反射,最终我决定自定义一个 ActionMenuView 放到 Toolbar 中去。可以代码动态构建,也可以直接放到 xml 中去。
<android.support.v7.widget.Toolbar
android:background="@color/colorPrimary"
android:id="@+id/activity_test1_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title=""
app:navigationIcon="@drawable/ic_back_light"
app:popupTheme="@style/CustomPopupTheme"
>
<android.support.v7.widget.ActionMenuView
android:id="@+id/activity_test1_toolbar_actionMenuViewId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"></android.support.v7.widget.ActionMenuView>
</android.support.v7.widget.Toolbar>
- 然后,在代码中,我们利用来动态更改 menu 的方法:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.clear();
getMenuInflater().inflate(R.menu.menu_action2, mActionMenuView.getMenu());
return super.onCreateOptionsMenu(mActionMenuView.getMenu());
}
效果图.png
1.2 更改 MenuItem 默认宽度
这个样式目前我只找到了一个有效属性 android:actionButtonStyle
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:actionButtonStyle">@style/CustomActionButtonStyle</item>
</style>
<!-- Toolbar ActionButton 样式 -->
<style name="CustomActionButtonStyle" parent="@android:style/Widget.Holo.ActionBar">
<item name="android:minWidth">72dp</item><!-- 默认值 56 -->
<item name="android:padding">0dp</item>
<item name="android:background">@drawable/selector_bg_toolbar_action_btn</item>
</style>
效果图.png
- 宽度已经更改成功了,但是新的问题出来了,我们发现图标多了一些东西。查看了一下代码,发现是 Widget.Holo.ActionBar 默认的背景图,包括上面一条灰色,下面一条蓝色,根据提示,找到了这个属性 android:background 顺便把点击效果也做了。
<!-- Toolbar ActionButton 样式 -->
<style name="CustomActionButtonStyle" parent="@android:style/Widget.Holo.ActionBar">
<item name="android:minWidth">56dp</item><!-- 默认值 56 -->
<item name="android:padding">0dp</item>
<item name="android:background">@drawable/selector_bg_toolbar_action_btn</item>
</style>
-
不过奇怪的是,它只对我的 state_press 属性有响应, state_hovor state_focus 貌似没有
GIF.gif
二、测试效果2 - ActionLayout
效果图.png我们知道,通常情况下, ActionMenu 在 Toolbar 中的作用是显示图片和文字。但是在很多时候,仅仅是图片文字,已经不能满足我们的需求,这个时候,我们需要 ActionLayout 这个属性,为我们导入自定义布局。
例如上图,为一个嵌套在 Toolbar 中的 SearchView。图中除了箭头,其他全都是一个自定义 layout 布局的内容。
附上 menu_action.xml 代码:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:title="搜索框"
android:id="@+id/menu_action_search"
android:orderInCategory="1"
app:showAsAction="always"
app:actionLayout="@layout/layout_menu_search"
/>
</menu>
注意,这里 actionLayout 属性需要引用 app 下的标签,而不是 android 下的标签,否则无法按照视图内容显示。
三、为什么我要去尝试 ActionMenu 实现这些效果
如题,事实上,这些东西本没有必要。因为 Toolbar 本身是一个容器,对于自定义的布局,我们只需要将它自带的所有布局隐藏,然后把自己的布局添加进来就可以了。例如:
<android.support.v7.widget.Toolbar
android:id="@+id/activity_test2_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/ic_back_light"
android:background="@color/colorPrimary"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="title"
android:textSize="20sp"
android:textColor="@android:color/white"/>
</android.support.v7.widget.Toolbar>
但是,上面的方法写几个 demo 大概并没有什么问题,但是在一个庞大的工程里,通常没有办法这么容易地解决一个问题。我们更提倡动态地添加,更提倡新建和复用而不是修改原来的代码。对于同一个问题,我们期待自己拥有更多的解决方案来适应不同的场景。
想努力让自己和自己的作品更好,想对每一行代码负责,想进步。
带着这样的愿景,我在想要不要奖励自己一点什么。
谢谢观赏
网友评论