zoukankan      html  css  js  c++  java
  • Material适配2

    版权声明:

    欢迎转载,但请保留文章原始出处

    作者:GavinCT

    出处:http://www.cnblogs.com/ct2011/p/4493439.html

    继续Material系列,先从Toolbar讲起

    ActionBar --> Toolbar

    在使用ActionBar的时候,一堆的问题:这个文字能不能定制,位置能不能改变,图标的间距怎么控制神马的,由此暴露出了ActionBar设计的不灵活。
    在上一篇中,我们只是简单使用了AppCompatActivity,他使用的仍然是ActionBar
    官方在21以后提供了ToolBar。
    Toolbar之所以灵活,是因为它其实就是一个ViewGroup,我们在使用的时候和普通的组件一样,在布局文件中声明。

    主题使用

    使用Toolbar时,如果单纯的当作控件来使用,主题是不需要单独设置的。
    但是如果想用他来替代ActionBar,
    那么需要配置为Theme.AppCompat.NoActionBar主题,
    或者在主题中加入

    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    

    (两个都必须有,上一篇已经提到没有windowNoTitle时会报错)
    这里推荐使用第一种方式。

    常用的配置

    Toolbar因为经常被用来替代ActionBar,所以一般项目里都会抽取出来,以便include。
    可能有人会说,既然还是用来替换ActionBar,那我项目里直接不动ActionBar不就完了?
    对,一般情况下是没有问题的,但是有些界面需要借助Toolbar灵活性的时候,你就被迫要换成Toolbar了。
    先来看Toolbar常用代码:

    include_toolbar.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            android:minHeight="?attr/actionBarSize" />
    

    配置中需要注意的是theme和popupTheme,我们来仔细看下,先从View的theme说起。

    View的theme

    Android 5.0引入一个全新的特性,允许你对view设置theme,这种设置会影响控件及其包含的子控件。
    使用AppCompat v22.1.x 后,也可以给你 layout 里的任意视图设置主题。
    只要使用 android:theme 这个属性就好,新版本的兼容库可以在 compat 和 framework 之间无缝地切换功能。

    实现原理

    这是因为有ContextThemeWrapper类,这个类API v1的时候就有了。
    他包裹(wrap)一个存在的Context(这里指你的Activity),之后覆盖(overlay)一个新的主题在当前Context的主题之上,这也是为什么叫ThemeOverlay。

    Toolbar常用的ThemeOverlay

    • ThemeOverlay.AppCompat.Light.ActionBar
    • ThemeOverlay.AppCompat.Dark.ActionBar

    android:theme 与 app:theme

    在AppCompat v21里,提供了一个快速方便的方法设置Toolbar的主题,使用app:theme。

    而新版本22.1.x中,AppCompat 允许对 Toolbar 使用android:theme代替app:theme
    最好的一点是:它会自动继承父视图的theme ,并且兼容所有APIv11以上的设备。
    示例:

    <Toolbar
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
        <!-- This TextView inherits its theme from the parent Toolbar -->
        <TextView android:text="I'm light!" />
    
    </Toolbar>
    

    对于运行 API v10 甚至更老的设备来说,你也可以使用android:theme属性, 不过它不会继承父视图theme。
    这就意味着你要么重新考虑你的布局,要么为每一个子视图都设置上 android:theme 属性。(这样做效率真的很低)

    总结一下:

    • 兼容 API 11 以上,推荐使用android:theme
    • 如果兼容更老的版本,推荐继续使用app:theme

    app:popupTheme

    有时候我们有需求:

    ActionBar文字是白的,ActionBar Overflow弹出的是白底黑字

    让ActionBar文字是白的,那么对应的theme肯定是Dark。
    可是让ActionBar弹出的是白底黑字,那么需要Light主题。
    这时候popupTheme就派上用场了。

    <android.support.v7.widget.Toolbar
    	android:id="@+id/toolbar"
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:background="?attr/colorPrimary"
    	app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    	android:minHeight="?attr/actionBarSize" />
    

    注意:
    使用app:popupTheme="@style/ThemeOverlay.AppCompat.Light"而不是android:popupTheme

    作为ActionBar使用

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.blah);
    
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
    

    独立使用

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.blah);
    
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    
        // Set an OnMenuItemClickListener to handle menu item clicks
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                // Handle the menu item
                return true;
            }
        });
    
        // Inflate a menu to be displayed in the toolbar
        toolbar.inflateMenu(R.menu.your_toolbar_menu);
    }
    

    一般使用疑问

    1. 没有了splitActionBarWhenNarrow,用两个Toolbar模拟是否可以?

    不可以,这种方式是有问题的。
    两个Toolbar放在布局中后,下面的Toolbar不能顶到最左边。
    stackoverflow : How to center action menu on toolbar 中有详细的描述。
    问题中给出了SplitToolbar的解决方案,但我尝试后发现这种解决方案仍然有轻微的偏移。

    2. 使用Toolbar后,NavigationIcon不垂直居中?

    NavigationIcon

    Toolbar的layout_height属性,要用“?attr/actionBarSize”而不是“?android:attr/actionBarSize”,替换后可解决NavigationIcon不垂直居中的问题。
    原因是系统的actionBarSize比AppCompat中的要小。使用“?android:attr/actionBarSize”调用了较小的那个。

    ActionMode配置

    使用AppCompatActivity启动

    需要声明的是,这种方法更加简便一些,有无Toolbar都适合使用。(感谢dongorigin指正)
    直接在AppCompatActivity或者ActionBarActivity中调用startSupportActionMode启动即可。
    注意这里的ActionMode是support包里的ActionMode。
    这时如果你运行程序触发ActionMode,可能会看到ActionMode和ActionBar分立成两栏,并没有浮在ActionBar上面。
    解决的办法很简单,在主题中加入

    <item name="windowActionModeOverlay">true</item>
    

    即可。

    给ActionMode配置主题

    有些同学使用了Dark主题下的Toolbar,并且主题使用了Theme.AppCompat.Light.NoActionBar,这时候会发现ActionMode是Light主题,很难看。
    那么怎么能配置成Dark主题呢?

    <item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
    

    弹出菜单自定义主题

    <item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
    

    ActionMode背景色替换

    <!--action Mode背景-->
    <item name="actionModeBackground">@color/theme_color_action_mode</item>
    

    使用Toolbar启动

    代码示例:

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    toolbar.startActionMode(mActionModeCallback)
    

    注意这里的ActionMode是view包下的,不是support v7下的。

    保证ActionMode浮在ActionBar上及ActionMode背景色替换与上面方式一致,这里不再赘述,请参考上文。

    如何实现和Inbox一样的ActionMode

    ActionMode_Inbox

    可以看到,ActionMode开启时,顶部的Status Bar颜色也跟着改变了

    这种功能Theme中并没有提供属性来修改。
    但是联想到入门篇提到的代码设置status bar颜色,这里就不难实现了。

    代码共享下:

    private int mOldStatusBarColor = -1;
    private void setActionModeStatusBarColor(int colorResId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mOldStatusBarColor = mActivity.getWindow().getStatusBarColor();
            setStatusBarColorCore(mActivity.getResources().getColor(colorResId));
        }
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void setStatusBarColorCore(int color) {
        mActivity.getWindow().setStatusBarColor(color);
    }
    private void resetStatusBarColor() {
        if (mOldStatusBarColor != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            setStatusBarColorCore(mOldStatusBarColor);
            mOldStatusBarColor = -1;
        }
    }
    

    开启时调用set,销毁时调用reset即可。

    P.S. : 上面的计数可以通过setTitle来完成。

    网上提供的错误方式(已踩坑,请绕行)

    保持Activity调起,使用android:windowActionModeOverlay属性。
    看似让ActionMode浮在了ActionBar上,但其实存在很大问题。
    这种方式在4.4以下会使用Holo风格(overflow图标可以看出来,不是三个原点,是三个方块),且ActionMode比ActionBar小一些(可以看到蓝色底边是ActionBar)

    ActionMode

    其他Material适配必备贴

    常用效果及实现

    官方参考App及示例

    参考资料

  • 相关阅读:
    uniapp数据循环带参数拼接方法
    UniApp页面跳转
    layui表单提交时关闭默认刷新页面
    js计时器
    Jquery 鼠标移入移出事件
    jquery常用ajax请求
    易宝网上支付接口的实现
    不使用缓存和不同缓存下程序的效率测试
    Mysql常见指令--常用的命令
    PHP冒泡与快速排序法
  • 原文地址:https://www.cnblogs.com/ct2011/p/4493439.html
Copyright © 2011-2022 走看看