Design Library出来已经快有一个月了,当时大概看了一下介绍这个新版本变化的译文,内容不多,给我印象最深的就是Percent lib、AppBarLayout 和NavigationView的变化,当然还有Design Lib的一些控件内部实现的变化没有介绍,从而使得在使用新版本的控件时候难免因为版本的不同会发生一些异常,而本人正好在上个星期对一个项目换库时发现了这个问题,什么问题呢?

NavigationView使用注意的问题

就是NavigationView的内部实现发生了改变,它在23.1.0版本之前内部实现是ListView实现的,而在23.1.0(包括这个版本)之后改为由RecyclerView实现,在一般我们使用时候并不会发生什么异常,而我们如果需要添加一个headerView的时候,这时候就需要注意了,如果我们需要获取headerView里面的控件的话,按之前的做法我们只需要直接findViewById()或者通过navigationView.findViewById()就能获取到并使用,而在23.1.0版本之后,由于内部实现发生了改变,此时如果通过findViewById()或者通过navigationView.findViewById()获取headerView里面的控件的话,则会报NullPointerException空指针异常,说明在23.1.0版本之后按这样的方法并不能获取到headerView内控件的实例。

那么我们就来看看NavigationView源码,来看看它的内部实现到底是不是改变了呢?
我找来了两个版本的Design包:分别为23.0.1版本和23.1.0版本。
我们先来看看旧版本的(23.0.1)NavigationView的源码实现:
贴几个主要的,通过一层一层查看,我们发现了导航栏菜单的实现类NavigationMenuView ,它继承于ListView

1
public class NavigationMenuView extends ListView implements MenuView {...}

而23.1.0版本改变了这个实现,采用RecyclerView实现:

1
public class NavigationMenuView extends RecyclerView implements MenuView {...}

在23.1.0以后正确做法是不在xml布局中addHeaderLayout,而是在代码中通过inflateHeaderView()添加,这个方法会返回当前inflate的View实例,通过它我们可以找到headerView内的控件:

1
2
3
4
5
6
7
8
View headerView = mNavigationView.inflateHeaderView(R.layout.header);
mHeaderButton = (Button) headerView.findViewById(R.id.btn_header);
mHeaderButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this"click button!", Toast.LENGTH_SHORT).show();
    }
});

Design Library 23.1.0的新变化

TextInputLayout添加字符计数功能

平时我们使用EditText用来写入长文本时,通常会在右下角显示一个文本,用来显示当前EditText目前有多少字符了,以前我们实现这个功能通过都是用TextWatcher来监听文本的变化来计算,而新版本的Design包为TextInputLayout添加了这个功能,我们只需要在xml中设置

1
app:counterEnabled="true"

来开启计数功能,它默认是不开启的,或在代码中设置:

1
2
TextInputLayout textInputLayout = (TextInputLayout) findViewById(R.id.til);
        textInputLayout.setCounterEnabled(true);

这样我们的EditText就有计数功能了,效果为:

当然我们还可以设置最大字数限制:
在xml中设置:

1
app:counterMaxLength="100"

在代码中设置:

1
2
3
TextInputLayout textInputLayout = (TextInputLayout) findViewById(R.id.til);
textInputLayout.setCounterEnabled(true);
textInputLayout.setCounterMaxLength(100);

显然如果需要设置最大的字数,肯定是需要先开启计数功能,设置counterEnabled为true
效果为:

当然这个最大字数的限制仅仅只是个提示作用,意思就是我们输入的字符数量达到这个限额的时候,还可以继续输入,如:

所以,禁止输入的逻辑需要我们自己来实现,我们可以通过结合TextWatcher来实现限制最大字数的逻辑,通过判断当达到最大限额数量时候禁止继续输入

假如你如果想同时使用错误提示和计数这两个功能,那么当然也可以,只不过计数就放到了右下角了,效果如图:

当然还有其它的一些api,虽然并不是新增的,顺便也一起说明一下:

app:hintAnimationEnabled=”true” —设置hint过度到左上角显示是否使用动画过度,默认为true,如果设为false则过度非常生硬
app:hintTextAppearance=”” —设置hint的字体样式,值为一个style
app:errorTextAppearance=”” —设置错误提示的字体样式
app:counterTextAppearance=”” —设置计数字体的样式
app:counterOverflowTextAppearance=”” —这个api比较有趣,这个触发的时机是达到最大输入字数时候,这时计数的字体样式会变为这里设置的样式

下面就演示app:counterOverflowTextAppearance这个api的效果,比如我们可以为它设置当字数达到上限的时候,计数字体就变大和显示另外一种颜色:

这样就非常明显的可以看到区别了。

AppBarLayout新的滚动Flag—snap

按照Google给的解释来说,这个Flag主要是为了确保滚动结束时,View将不会以滚动的中间状态显示,即不会让滚动时未完成的部分显示出来,相反,它会滚动到最近的边缘位置,使其以完全可见或滚动完全的状态显示在屏幕上,这段话可能难以联想到这种效果,那么就以实际效果来看看设置这个snap标志和不设置的区别:

设置snap

为了代码简短,我只截取了AppBarLayout的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="256dp"
    android:theme="@style/AppTheme.AppBarOverlay">
 
    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentScrim="@color/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
 
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:src="@mipmap/bg"
            app:layout_collapseMode="parallax"
            app:layout_collapseParallaxMultiplier="0.7" />
 
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
    </android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>

效果为:

不设置snap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:theme="@style/AppTheme.AppBarOverlay">
 
            <android.support.design.widget.CollapsingToolbarLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:contentScrim="@color/colorPrimary"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">
 
                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="centerCrop"
                    android:src="@mipmap/bg"
                    app:layout_collapseMode="parallax"
                    app:layout_collapseParallaxMultiplier="0.7" />
 
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin"
                    app:popupTheme="@style/AppTheme.PopupOverlay" />
            </android.support.design.widget.CollapsingToolbarLayout>
        </android.support.design.widget.AppBarLayout>

效果为:

根据上面两个效果的对比,很明显的就可以发现,snap标志主要的作用就是不会让滚动时未完成的部分显示出来,效果图中加了snap标志的很明显,当往上滚动一点距离的时候,它会弹回来,而滚动到快要到结束状态的时候,则是滚动到最近的边缘位置,使其隐藏起来,此时往下滑动一下,Toolbar就显示出来了,而不加snap标志的效果,则是可以显示滚动时未完成的部分。

支持从AppBarLayout内开始滚动

AppBarLayout现在允许用户滚动从AppBarLayout内,而不是只能从滚动视图内滚动 ,另外可以通过添加DragCallback这种行为可以控制是否可以从AppBarLayout内滚动
为了更好的理解,来两张效果图吧:
23.1.0版本:

23.0.1以前版本:
为了有23.0.1以前版本的效果,我特意找来了我一个在23.0.1以前版本上写的demo来演示

从这两个效果中就可以看出,在旧版本上,我们在AppBarLayout中进行滚动时,发现不能滚动,而在新版本23.1.0上滚动时,却可以在AppBarLayout内进行滚动,这就是新版本的改进

NavigationView可以扩展自定义视图

通过使用app:actionLayout或MenuItemCompat.setActionView()能够为抽屉的菜单项添加自定义视图,这使得NavigationView得到了更好的扩展性
来看一张效果图:

在menu.xml中设置:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
    <group android:checkableBehavior="single">
        <item
            android:icon="@mipmap/ic_launcher"
            android:title="one"
            app:actionLayout="@layout/action" />
            ...
    </group>
</menu>

或者在代码中设置:

1
2
MenuItem menuItem = mNavigationView.getMenu().getItem(1);
MenuItemCompat.setActionView(menuItem,R.layout.action);

可以看到菜单项在后面添加了自定义的视图,这更能方便我们扩展功能,就比如博主本人前段时间写的简邮App,菜单项都是一些收件箱、发件箱、草稿箱等,而这些正好需要有提醒邮件数量的功能,之前由于NavigationView扩展性太差,导致这个功能没有加入,而在23.1.0的版本上,对NavigationView的扩展性做了改进,看到图中第二个item项的蓝色区域了吧,这个区域就是随便我们怎么定制视图,从而使得NavigationView和一些第三方的抽屉可以媲美了

Percent百分比布局库新增支持宽高比

百分比布局库按我的理解就是:

百分比布局库是以父ViewGroup的宽高为基础,根据子View(ViewGroup)所设置的百分比来动态设置子View(ViewGroup)的宽高

以往百分比布局只支持分别设置宽和高的百分比来设置的,而这次新增的功能,是可以通过设置宽高比来设置了,通过设置只有一个单一的宽度或高度和使用app:aspectRatio设置宽高比,那么PercentFrameLayout或PercentRelativeLayout会自动调整其它尺寸

Palette支持从一个Bitmap的特定区域提取颜色

Palette可以从图像中获取颜色,现在新增了一个方法setRegion(),支持从一个位图的一个特定区域提取

RecyclerView的动画系统变得更好

通过使用ItemAnimator新增的canReuseUpdatedViewHolder()方法,你可以选择重用现有ViewHolder,使得其支持Item的内容动画
之前我们定义RecyclerView的Item动画往往是通过继承RecyclerView.ItemAnimator来实现的,而新版本则推荐我们继承于RecyclerView.SimpleItemAnimator类来实现我们的动画,因为这个类封装新的api同时也提供了旧的api的支持,而且有些方法已经从这个版本中移除了,比如以前我们是通过recyclerView.getItemAnimator().setSupportsChangeAnimations(false)这个方法来设置Item的内容改变时的动画支持,而新版本中这个方法将不再有效,而是需要通过下面的代码设置:

1
2
3
4
ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
  ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}

[转]Material Design Library 23.1.0的新变化与代码实战的更多相关文章

  1. Material Design Library 23.1.0的新变化与代码实战

    Design Library出来已经快有一个月了,当时大概看了一下介绍这个新版本变化的译文,内容不多,给我印象最深的就是Percent lib.AppBarLayout 和NavigationView ...

  2. 自定义 Material Design风格的提示框

    关闭 自定义 Material Design风格的提示框 2016-04-24 10:55 152人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. 其实在14年谷歌 ...

  3. 【Android】进入Material Design时代

    由于本文引用了大量官方文档.图片资源,以及开源社区的Lib和相关图片资源,因此在转载的时候,务必注明来源,如果使用资源请注明资源的出处,尊重版权,尊重别人的劳动成果,谢谢! Material Desi ...

  4. Android Material Design-Creating Apps with Material Design(用 Material Design设计App)-(零)

    转载请注明出处:http://blog.csdn.net/bbld_/article/details/40400031 翻译自:http://developer.android.com/trainin ...

  5. 用户登录(Material Design + Data-Binding + MVP架构模式)实现

    转载请注明出处: http://www.cnblogs.com/cnwutianhao/p/6772759.html MVP架构模式 大家都不陌生,Google 也给出过相应的参考 Sample, 但 ...

  6. 仿知乎app登录界面(Material Design设计框架拿来就用的TexnInputLayout)

    在我脑子里还没有Material Design这种概念,就我个人而言,PC端应用扁平化设计必须成为首选,手当其冲的两款即时通讯旺旺和QQ早就完成UI扁平化的更新,然而客户端扁平化的设计本身就存在天生的 ...

  7. 使用Material Design Tint和视图详解

    视图 首先来讲Material Design 视图的概念,在新的api中,新添加了z轴的概念,z轴垂直于屏幕,用来表现元素的层叠关系,z值(海拔高度)越高,元素离界面底层(水平面)越远,投影越重,这里 ...

  8. Android material design support library -- CollapsingToolbarLayout简介

    本文是codetrick上material design support library教程的第三篇,主要讲的是CollapsingToolbarLayout的概念和应用方法. 原文链接:Materi ...

  9. Material Design 开发利器:Android Design Support Library 介绍

    转自:https://blog.leancloud.cn/3306/ Android 5.0 Lollipop 是迄今为止最重大的一次发布,很大程度上是因为 material design —— 这是 ...

随机推荐

  1. Jenkins的Windows Slave分布式构建和部署

    1.新建的Slave:系统管理-->管理节点-->新建节点 远程工作目录 即是 节点服务器 站点文件存放目录 在配置节点时 启动方法 配置的选项中的 Launch agent via Ja ...

  2. Oracle中用随机数更新字段----将一张表的数据插入另一张表----环境设置

    DECLARE CURSOR recordCursor IS SELECT longitude,latitude FROM WR_WIUST_B_SEC FOR UPDATE; recordRow r ...

  3. 性能:15个JavaScript本地存储技术的函数库和工具

    当构建更复杂的JavaScript应用程序运行在用户的浏览器是非常有用的,它可以在浏览器中存储信息,这样的信息可以被共享在不同的页面,浏览会话. 在最近的过去,这将有可能只被cookies文本文件保存 ...

  4. vim--golang代码补全

    我想说,我折腾了很久编辑器,试了九种办法 最后我只成功了一种 但我依然想就我混乱的逻辑做下整理 一.一开始,我试图入手ipad编码软件,大概9美金吧,叫Textastic.我试图用它的近亲来试验Tex ...

  5. Linux中crontab的坑爹环境变量问题

    手动在CentOS中执行sh脚本,调用java程序,一切正常: 将该sh加入crontab中定时调度之后,挂了,完全没有执行到的感觉啊!!! 查看crontab执行日志: cat /var/log/c ...

  6. WebApi参数传递

    c# webapi的参数传递方式:1.查询字符串(query string):2.内容主体(content body) 当然也有cookie或url部分或头部信息(header)等其它传方式,这里仅讨 ...

  7. Part 1 What is SSMS?

    note that,SSMS is a client tool and not the server by itself,it is a developer machines connects to ...

  8. C++将类的构造函数、析构函数声明为private或者protected的用途

    如果将构造函数.析构函数声明为private或者protected,表示不能从类的外部正常调用构造和析构函数了. 这种用法的通常使用的场景如下: 1.如果不想让外面的用户直接构造一个类A的对象,而希望 ...

  9. 关于iOS6应用中第三方类库不支持armv7s的问题解决

    今天编译ios6+cocos2d v2 .1 beta2制作的游戏,出现下面的错误: ld: file is universal (3 slices) but does not contain a(n ...

  10. JS动画 | 用TweenMax实现收集水滴效果

    之前在CodePen上接触了TweenMax, 被它能做到的酷炫效果震撼了. (文末放了5个GSAP的效果GIF) 最近要做一个"收集水滴"的动效, 于是就试用了一下TweenMa ...