ActionBar/Toolbar定制ui

最近项目对ui走查,由于谷歌的那套交互框架已经写好了,系统控件那边对样式定制失败,把锅甩给我们上层,鉴于时间紧,任务重,就没打算对框架级进行修改,单单就ActionBar/Toolbar进行样式修改,在修改的过程中,发现ActionBar/Toolbar这块的坑真多,尤其是各种间距问题。废话不多说了开始正题。
首先上效果图吧:
效果图-1
效果图-2
效果图-3
关于样式这块我也是第一次这么大动作的修改,部门大牛修改样式这块都是看官方文档,我渣就面向百度编程,各种姿势百度,然而也于事无补,综合百度的各种解决方案发现大多都是根据主题样式逐层向上查找对应的属性来定制看效果样式。
首先说一下下面的解决方案不是最优解,只是一种为了达成效果的一种手段,因为我在公司不是这么做的,这是我在家里自己倒腾的demo,所以界面挺lowbee的,各位dalao看官勿喷。这里我就从效果图-1开始介绍我的这次踩坑经历吧。
效果图-1要求没有返回图标,title的左间距是16dp, 右边的选项菜单图标之间的间隔是10dp,右侧的图标距离屏幕右侧10dp。网上找的各种资料基本都是说在主题样式中配置 actionBarStyle属性,但是怎么试都没有效果无赖之下就在代码里面进行了跟踪看下拿货到底是个啥鸟。照样使用Android studio自带的工具看了下。
效果图-4
在这里看到那个title是TextView,但是当运行时却发现坑爹啊,
int actionBarId = resources.getIdentifier(“com.docext.datepicker:id/action_bar_container”, null, null);
ViewGroup actionBarView = getWindow().getDecorView().findViewById(actionBarId);
debug看到那个title其实是AppCompatTextView,父布局是Toolbar, 这下就尴尬了,点开Toolbar文件,发现有如下属性,效果图-5
原来都是Toolbar的样式,向上点入系统样式看到有关Toolbar的样式

<!-- Toolbar styles -->
        <item name="toolbarStyle">@style/Widget.AppCompat.Toolbar</item>
        <item name="toolbarNavigationButtonStyle">@style/Widget.AppCompat.Toolbar.Button.Navigation</item>

继续点击进去看

<!-- toolbarStyle styles -->
<style name="Base.V7.Widget.AppCompat.Toolbar" parent="android:Widget">
        <item name="titleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Title</item>
        <item name="subtitleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle</item>
        <item name="android:minHeight">?attr/actionBarSize</item>
        <item name="titleMargin">4dp</item>
        <item name="maxButtonHeight">@dimen/abc_action_bar_default_height_material</item>
        <item name="buttonGravity">top</item>
        <item name="collapseIcon">?attr/homeAsUpIndicator</item>
        <item name="collapseContentDescription">@string/abc_toolbar_collapse_description</item>
        <item name="contentInsetStart">16dp</item>
        <item name="contentInsetStartWithNavigation">@dimen/abc_action_bar_content_inset_with_nav</item>
        <item name="android:paddingLeft">@dimen/abc_action_bar_default_padding_start_material</item>
        <item name="android:paddingRight">@dimen/abc_action_bar_default_padding_end_material</item>
    </style>

于是在此基础上开始定制自己需要的效果,最终结果文末会给出。
右侧OptionMenu其实最终都是被填充到Toolbar的属性变量ActionMenuView mMenuView; 中了, 由 actionButtonStyle 属性来控制。
效果图-2返回按钮间距也是由actionBarStyle控制,至于编辑模式下的返回按钮我重写了样式文件的一个属性

<!-- closeItemLayout styles -->
    <style name="Base.Widget.AppCompat.ActionMode" parent="">
        <item name="background">?attr/actionModeBackground</item>
        <item name="backgroundSplit">?attr/actionModeSplitBackground</item>
        <item name="height">?attr/actionBarSize</item>
        <item name="titleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionMode.Title</item>
        <item name="subtitleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionMode.Subtitle</item>
        <item name="closeItemLayout">@layout/abc_action_mode_close_item_material</item>
    </style>        
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/action_mode_close_button"
    style="@style/ActionModeCloseButtonStyleX"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginEnd="0dip"
    android:layout_marginRight="0dip"
    android:clickable="true"
    android:contentDescription="@string/abc_action_mode_done"
    android:focusable="true"
    android:background="@null"
    app:srcCompat="?attr/actionModeCloseDrawable" />

这里有个坑就是Title是父控件下的第一个子控件,间距是相对屏幕左侧。效果图-3是编辑模式下,部分样式是由actionModeStyle来控制,右侧的OptionMenu的样式是由父样式的actionButtonStyle来控制。
上面的做法可能导致ActionBar背景颜色不一致问题,这里我就简单采用了硬编码的方式定制了背景颜色。基类中在onCreateView()中调用如下代码

    protected void setActionBarBackground() {
        Resources resources = getResources();
        int actionBarId = resources.getIdentifier("com.docext.datepicker:id/action_bar_container", null, null); //("android:id/action_bar_container", null, null);
        ViewGroup actionBarView = getWindow().getDecorView().findViewById(actionBarId);
        if (actionBarView != null) {
            actionBarView.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
        }
    }

这种硬编码方式其实是很危险的,比如前段时间颜色使用这种方法定制AlertDialog的title下面的分割线的颜色,也是使用这种方式,可是不同的安卓版本可能会去除了那个分割线,导致设置失败,不过那个可以按照如下方式来完全定制dialog
// 也可以自定义布局
// alertDialog.show(); // 需要先show, 在设置布局
// Window window = alertDialog.getWindow();
// window.setContentView(R.layout.dialog_main_info);
// setView()只会覆盖AlertDialog的Title与Button之间的那部分,而setContentView()则会覆盖全部。
// setContentView()必须放在show()的后面,不然会报错。
// 如果你要在代码里修改AlertDialog的大小,可以用以下代码实现:mAlertDialog.getWindow().setLayout(150, 320); 不然改动会没有效果。

公司项目的实现是自定义左侧返回箭头,标题,副标题那块,右侧是使用Menu节点下的layout属性,来控制布局控件的样式的。实践中发现虽然右侧的layout布局是放在了一个自定义的布局中,但在调试的过程中发现自定义的布局内部的ImageView被提取放在了android.support.v7.widget.ActionMenuView里面,其父控件就是android.support.v7.widget.Toolbar刚好又可以单独的对此页面进行主题样式控制其actionBarStyle属性。不过试了下貌似不行,在常规模式下设置了paddingEnd虽然当前页面的OptionMenu有右间距但是进入ActionMode状态时那个右间距依然存在,只能单独为该Menu写个layout控制间距了。好了废话不多说了,最后附上样式源代码:

<resources>
    <!-- Base application theme. Theme.AppCompat.Light.DarkActionBar-->
    <style name="AppBaseTheme" 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>
        <!-- 控制 ActionBar 高度 字体样式 水平间距 -->
        <item name="actionBarStyle">@style/ActionBarBaseStyleX</item>
        <item name="toolbarStyle">@style/ToolbarBaseStyleX</item>
        <!-- 控制 ActionMenu 水平间距 -->
        <item name="actionButtonStyle">@style/ActionButtonStyleX</item>
        <item name="actionModeBackground">@drawable/action_mode_background</item>
        <item name="actionModeCloseDrawable">@mipmap/action_mode_back_img</item>
        <!--<item name="android:windowBackground">@color/colorPrimary</item>-->
    </style>
    <style name="AppTheme" parent="@style/AppBaseTheme">
        <!-- 控制 ActionBar 高度 字体样式 水平间距 -->
        <item name="actionBarStyle">@style/ActionBarStyleX</item>
        <item name="actionModeStyle">@style/ActionModeStyleX</item>
       <!-- <item name="actionOverflowButtonStyle">@style/ActionOverflowButtonStyleX</item>-->
        <!-- Toolbar styles -->
        <item name="toolbarStyle">@style/ToolbarStyleX</item>
        <!-- 控制 Toolbar 返回按钮的样式 -->
        <item name="toolbarNavigationButtonStyle">@style/ToolbarNavigationButtonStyleX</item>
    </style>
    <style name="ActionBarBaseStyleX" parent="@style/Base.Widget.AppCompat.ActionBar">
        <item name="titleTextStyle">@style/ActionBarTitleStyle</item>
        <item name="subtitleTextStyle">@style/ActionBarSubTitleStyle</item>
        <!-- actionBar 高度 -->
        <!--<item name="height">46dp</item>-->
        <!-- 控制 toolbar 左右间距  marginStart = 0dp 时 title 的 paddingLeft 是 16dp -->
        <item name="android:layout_marginStart">-6dp</item>
       <!-- <item name="android:layout_marginEnd">5dp</item>-->
        <!--<item name="android:paddingStart">5dp</item>-->
        <item name="android:paddingEnd">5dp</item>
        <!-- 去除 actionBar阴影 -->
        <item name="elevation">0dp</item>
       <!-- <item name="android:paddingRight">5dp</item>-->
        <!-- 控制 toolbar 上下间距 -->
        <!-- <item name="android:layout_marginTop">0dp</item>
        <item name="android:layout_marginBottom">0dp</item>-->
    </style>

    <style name="ActionModeStyleX" parent="@style/Widget.AppCompat.ActionMode">
        <!-- 控制 ActionMode 下 ActionBar 高度 -->
        <item name="titleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionMode.Title</item>
        <item name="subtitleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionMode.Subtitle</item>
        <item name="closeItemLayout">@layout/action_mode_close_item</item>
        <!-- 控制 toolbar 左右间距 actionbar 已经设置过 -->
        <!--<item name="android:layout_marginStart">10dp</item>
        <item name="android:layout_marginEnd">10dp</item>
        <item name="android:width">32dp</item>
        <item name="android:height">32dp</item>
        <item name="android:minWidth">32dp</item>
        <item name="android:paddingStart">-10dp</item>
        <item name="android:paddingEnd">0dp</item>-->
        <item name="android:maxWidth">44dp</item>
        <item name="android:maxButtonHeight">44dp</item>

        <item name="actionModeCloseButtonStyle">@style/ActionModeCloseButtonStyleX</item>
    </style>

    <style name="ActionModeCloseButtonStyleX" parent="@style/Widget.AppCompat.ActionButton.CloseMode">
        <item name="android:minWidth">32dp</item>
        <!-- 控制 ActionMode 模式下返回按钮水平padding -->
        <item name="android:paddingStart">5dp</item>
        <item name="android:paddingEnd">5dp</item>
    </style>
    <style name="ToolbarBaseStyleX" parent="Widget.AppCompat.Toolbar">
        <!-- 设置无效 -->
        <!--<item name="android:height">56dp</item>-->
        <item name="titleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Title</item>
        <item name="subtitleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle</item>
        <!-- 控制 actionBar 图标的最小高度, 但对其方式 top | bottom, 导致没意义 最小宽度设置无效 -->
      <!--
        <item name="android:minHeight">32dp</item>
        <item name="android:minWidth">32dp</item>
      -->
        <!-- 设值会影响 subTitle 的显示 -->
        <item name="titleMargin">0dp</item>
        <item name="maxButtonHeight">44dp</item>
        <item name="contentInsetStart">0dp</item>
    </style>
    <style name="ToolbarStyleX" parent="@style/ToolbarBaseStyleX">
        <!-- ① 控制 actionTitle 与 navIcon 的间隔 受②处paddingStart | paddingEnd 取值影响 -->
        <item name="contentInsetStartWithNavigation">52dp</item>
    </style>
    <!-- 控制 Toolbar 返回按钮的样式 -->
    <style name="ToolbarNavigationButtonStyleX" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
        <!-- 去除按压水波纹效果 -->
        <item name="android:background">@null</item>
        <!-- 无效 -->
        <!--<item name="android:width">32dp</item>
        <item name="android:height">32dp</item>-->
        <item name="android:scaleType">centerInside</item>
        <!-- 控制返回图标的宽度 -->
        <item name="android:minWidth">32dp</item>
        <!-- ② 控制返回图标左右padding -->
        <item name="android:paddingStart">10dp</item>
        <item name="android:paddingEnd">10dp</item>

    </style>

    <style name="ActionBarStyleX" parent="@style/ActionBarBaseStyleX">
        <!-- 控制 toolbar 左间距 会导致背景色不正常 -->
        <item name="android:layout_marginStart">0dp</item>
        <!-- 影响父布局水平padding间距 比如BackButton的水平margin,会导致背景不一致问题 -->
        <item name="android:paddingStart">0dp</item>
        <!--<item name="android:paddingEnd">0dp</item>-->
        <!-- 去除 actionBar阴影 -->
        <item name="elevation">0dp</item>
    </style>

    <!-- 三点图标的样式 -->
    <style name="ActionOverflowButtonStyleX" parent="@style/Widget.AppCompat.ActionButton.Overflow">
        <item name="android:minWidth">32dp</item>
        <item name="android:minHeight">32dp</item>
    </style>

    <!-- 控制 ActionMenu 水平间距 -->
    <style name="ActionButtonStyleX" parent="@android:style/Widget.Holo.ActionBar">
        <!-- 控制 menu 图片水平 padding -->
        <item name="android:paddingStart">5dp</item>
        <item name="android:paddingEnd">5dp</item>
    </style>

    <style name="ActionBarTitleStyle" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
        <item name="android:textSize">15sp</item>
        <item name="android:textColor">#a0000000</item>
    </style>

    <style name="ActionBarSubTitleStyle" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle">
        <item name="android:textSize">10sp</item>
        <item name="android:textColor">#30000000</item>
    </style>
    <!-- 出现过 Action Bar Styles -->
    <style name="OriginActionBar" parent="Base.Widget.AppCompat.ActionBar"></style>
    <style name="BaseAppCompat" parent="Base.V7.Theme.AppCompat"></style>
    <style name="BaseLightAppCompat" parent="Base.V7.Theme.AppCompat.Light"></style>
</resources>

Toolbar的参考文章:http://www.jianshu.com/p/7b5c99e1cfa3

猜你喜欢

转载自blog.csdn.net/hard_working1/article/details/78714986
今日推荐