MaterialDesign设计0:定义阴影与裁剪视图
来源:互联网 发布:如何做网络推广员 编辑:程序博客网 时间:2024/05/01 02:45
最近在读谷歌的官方文档,整理一下,以备不时之需。部分内容如有错误,欢迎留言指正。
前言
本篇博客解读MaterialDesign中的视图高度 和剪裁视图。视图高度说的通俗点,就是我们在MaterialDesign中看到的View的阴影效果。官方给定的示意图:
该效果图分为上下两个View,上图阴影较大,下图阴影较小,从阴影效果带来的直观感受来看,上面的View明显比下面的View要“高”一些。这种感觉和生活中的常识是一致的:假设阳光下有一张纸,放在桌子上时的阴影几乎只有边缘部分,而当我们把它拿起时,阴影会随着我们拿起的高度升高而随之变大。
谷歌便把这种感官添加到了View中:默认情况下的View(放在桌子上的纸),应该如下图所示,只有一条淡淡的阴影(2dp),当我们对View进行类似单击等操作时(拿起桌子上的纸),View的阴影发生改变(升高了6dp),从而使用户有一种View被“拿起来”等待操作的感觉。
下面我们来看看各类View在MD中的阴影效果,先放效果图:
- Button按钮:自带阴影交互效果,所以这里这里就不拿Button举例子了。
背景可绘制View:如TextView、CardView、ImageView等可以设置背景的View。
以下内容都基于背景可绘制的View进行讲解,为什么要求背景可绘制呢?因为有了背景才有阴影,你想想空气这类透明的事物会产生阴影效果吗?所以这里要求View的背景是可绘制的,并且背景不能为透明。
动手操作:设置阴影交互
组成:阴影交互效果由两部分组成:默认高度(elevation)和动态转换高度(translationZ),即官方文档中说的“Z轴高度 = elevation + translationZ“
设置默认高度elevation,以TextView为例子
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:background="#03A9F4" android:clickable="true" android:elevation="2dp" android:gravity="center" android:text="TextView有阴影" android:textSize="20sp"/>
background——>设定背景,一定要注意背景不能为透明
clickable——>让其能响应用户的点击
elevation——>2dp的默认阴影效果。
*注意:CardView中的默认阴影效果需要调用app:cardElevation=”2dp”
对比效果如下
仔细看,是能看出来下图的2dp阴影的。但是此时单击TextView并没有使阴影变大。设置动态转换高度translationZ
阴影变大的操作,是通过translationZ属性来操作的。translationZ指的是View在Z轴上的显示高度(也就是把View”拿起来”的高度)。默认的translationZ应该为0(因为默认的View没有被”拿起来”),只有当我们和View产生交互时,才应该让translationZ的值增加,产生更大的阴影效果。
因此,translationZ这个属性不是让我们在Veiw的布局中直接使用固定值的,而是应该根据View的不同交互状态而做出大小的调整。Google文档方案为”selector+属性动画”来动态改变translationZ的数值。
下面我们建立一个selector命名为
selector_view_raise.xml
,里面根据View的不同状态设置不同的属性动画<selector xmlns:android="http://schemas.android.com/apk/res/android"> <!--按下状态,translationZ变为6dp--> <item android:state_pressed="true"> <objectAnimator android:duration="@android:integer/config_shortAnimTime" android:propertyName="translationZ" android:valueTo="6dp" android:valueType="floatType"></objectAnimator> </item> <!--默认状态,translationZ变回0dp--> <item> <objectAnimator android:duration="@android:integer/config_shortAnimTime" android:propertyName="translationZ" android:valueTo="0dp" android:valueType="floatType"></objectAnimator> </item></selector>
把定义好的
selector_view_raise.xml
设置到TextView中,即可产生阴影交互android:stateListAnimator="@animator/selector_view_raise"
如果不想要View的阴影交互行为,请将 android:stateListAnimator 属性设置为 @null。
- 运行后点击TextView,即可出现文章开头展示的动态效果
只要是背景可绘制View,都可产生阴影交互。阴影的效果,会根据绘制的背景边缘进行自动填充。下面我们来自定义一个背景,看看效果
自定义shape的阴影交互
上面例子中只使用的颜色作为背景。除了颜色,我们还可以自定义shape,用shape作为View的背景,阴影会根据我们定义的shape边缘,自动产生阴影效果。
定义一个圆角shape命名为
shape_background_blue.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/colorPrimary"></solid> <corners android:radius="5dp"></corners></shape>
设置View的background属性
android:background="@drawable/shape_background_blue"
该View将自动绘制一个带有圆角的阴影
剪裁视图和使用揭露动画
在5.0后,我们可以对边界为矩形、圆形和圆角矩形的View进行剪裁操作。可使用View.setClipToOutline() 方法或 android:clipToOutline 属性将视图裁剪至其轮廓区域,也可调用View.setClipBounds(Rect)来裁剪制定的区域。
谷歌指出,裁剪View是一个成本高昂的操作,因此不可以把剪裁操作作为属性动画(比如想把一个正方形一点点的剪成一个圆)。 如果要实现类似效果,请使用揭露效果动画。
下面我们先来看一下揭露效果 + 裁剪操作
通过效果图我们可以发现:
1.首次点击搜索按钮时,蓝色区域收起,再次点击,蓝色展开
2.点击裁剪按钮,蓝色区域被裁剪为左下角的1/4
3.再次点击搜索按钮,被裁剪后的蓝色区域收起,再次点击,蓝色展开
编写布局,这一步比较简单,我用了3个ImageView来分别显示蓝色区域、搜索按钮、裁剪按钮。大家copy过去就可以了,图标自行替换
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/iv_blue_scope" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@color/colorPrimary" /> <ImageView android:id="@+id/iv_search" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:background="@android:drawable/ic_menu_search" /> <ImageView android:id="@+id/iv_cut" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:background="@drawable/ic_content_cut_black_24dp"/></LinearLayout>
找到控件,对控件设置单击事件
//控件ImageView iv_blue_scope;ImageView iv_search;ImageView iv_cut;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_0); iv_blue_scope = (ImageView) findViewById(R.id.iv_blue_scope); iv_search = (ImageView) findViewById(R.id.iv_search); iv_cut = (ImageView) findViewById(R.id.iv_cut); iv_search.setOnClickListener(this); iv_cut.setOnClickListener(this);}//单击事件public void onClick(View view) { int id = view.getId(); switch (id) { case R.id.iv_search: //揭露ImageView exposeImageView(); break; case R.id.iv_cut: //裁剪操作 clipImageView(); break; }}
在单击事件中,我们先来看揭露操作exposeImageView(),对于揭露操作,官方给了很简明的示例,我这里就是根据官方的示例,进行了部分的修改。直接上代码了,注意看注释
private void exposeImageView() { //获取剪裁中心点,即扩散点,此处以View的右上角为中心点 int cx = iv_blue_scope.getRight(); int cy = iv_blue_scope.getTop(); //获取最终剪裁的半径,以View的最长边为准 int finalRadius = Math.max(iv_blue_scope.getWidth(), iv_blue_scope.getHeight()); //创建动画 Animator anim = null; //根据View的当前显示状态进行展开和收起的操作 if (iv_blue_scope.getVisibility() == View.INVISIBLE) { //创建圆形的揭露动画,从指定View(iv_blue_scope)的中心点( cx, cy,)开始,揭露半径从0到View的最长边(finalRadius) anim = ViewAnimationUtils.createCircularReveal(iv_blue_scope, cx, cy, 0, finalRadius); //显示View,开启动画 iv_blue_scope.setVisibility(View.VISIBLE); anim.start(); } else { //创建圆形的反向揭露动画,揭露半径从最长边到0即可 anim = ViewAnimationUtils.createCircularReveal(iv_blue_scope, cx, cy, finalRadius, 0); //注意,这里需要先展示动画,等动画结束后才可以把View隐藏掉。所以要对动画进行侦听 anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); iv_blue_scope.setVisibility(View.INVISIBLE); } }); anim.start(); } }
裁剪View,我这里是裁剪了部分区域,未执行剪裁到边界的操作,因为大部分的View边界和View大小一致,剪裁到边界相当于不剪裁。
private void clipImageView() { //获取iv_clipped的中心坐标 int cx = (iv_blue_scope.getLeft() + iv_blue_scope.getRight()) / 2; int cy = (iv_blue_scope.getTop() + iv_blue_scope.getBottom()) / 2; //实例化裁剪区域,此处我们裁剪该View的左下角的1/4区域 Rect rect = new Rect(iv_blue_scope.getLeft(), cy, cx, iv_blue_scope.getBottom()); //根据以上区域裁剪iv_clipped iv_blue_scope.setClipBounds(rect);}
源码:MaterialDesignDemo
- MaterialDesign设计0:定义阴影与裁剪视图
- <三>定义阴影与裁剪视图
- <六>定义阴影与裁剪视图
- 定义阴影和裁剪视图
- MaterialDesign——普通View的阴影设置和裁剪视图
- 创建Material Design风格的Android应用--定义阴影和裁剪视图
- Android Material Design-Defining Shadows and Clipping Views(定义阴影和裁剪视图)-(四)
- 创建Material Design风格的Android应用--定义阴影和裁剪视图
- Android Material Design-Defining Shadows and Clipping Views(定义阴影和裁剪视图)-(四)
- Android5.0的Palette(调色板)、视图阴影、着色和裁剪介绍
- android5.0:阴影和裁剪
- MaterialDesign 的设计方法与素材
- Android5.0特性阴影效果和裁剪
- 视图特点与定义
- MaterialDesign-沉浸式设计
- MaterialDesign设计(上)
- MaterialDesign设计(中)
- MaterialDesign设计(下)
- ngnix做Https访问设置及依据URL后缀分流访问
- mysql 优化--定位慢查询
- Error:Execution failed for task ':app:mergeDebugResources'. > Error: java.lang.RuntimeException: Som
- 滑动RecyclerView时隐藏部分控件
- iOS 创建语言提示成功后自动消失
- MaterialDesign设计0:定义阴影与裁剪视图
- 瑞利分布噪声图像
- 【Struts2+Hibernate4】开发学生信息管理功能(一)
- android实现大文件断点上传
- cvs的基本用法
- 银联系统开发的感悟
- git 远程版本库,github提供服务原理,git自动更新发送邮件
- 【腾讯TMQ】Google是如何做Chrome浏览器的性能测试的?
- TCP 协议的握手连接