constraintlayout布局新特性_进阶ConstraintLayout-2.0新特性
1.Group 1.1版本加入
Group属性用来控制ConstraintLayout布局内,被Group关联的view的可见性。笔者试了一下,是真的只能控制可见性,别的啥也干不了。
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="button1,button2" />
2.Layer 2.0加入
Layer可以看做是控制它所关联的View从而能形成一个伪边界。为何是伪边界?如下图,Layer可以在关联View后,给Layer设置一个背景。看起来就像寻常的ViewGroup包裹这些View,给ViewGroup设置背景。但是Layer并不是一个ViewGroup,且与它所关联的View处于同一个层级,因此能很好的减少一层布局。
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/layer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/frame"
android:padding="32dp"
app:constraint_referenced_ids="button4,button5,button3" />
avatar
所以,在不需要对背景做整体View动画如旋转、透明度、位移的情况下,Layer和Group结合可以很好的解决背景和整体可见性的问题,这种场景下,能很大程度的减少View布局嵌套。
3.ConstraintHelper
Group和Layer都是一种Helper,继承于ConstraintHelper,顾名思义,可以看做是View的帮助类,但是ConstraintHelper本身又是继承于View,所以虽然作为Helper,但是可以直接在XML里使用,并使用相关属性和属性API。
观察ConstraintHelper源码:
public abstract class ConstraintHelper extends View {
//helper所关联View id集合
protected int[] mIds = new int[32];
//helper所关联View数量
protected int mCount;
protected Context myContext;
protected Helper mHelperWidget;
protected boolean mUseViewMeasure = false;
protected String mReferenceIds;
//helper所关联View集合
private View[] mViews = null;
private HashMap mMap = new HashMap();
}
那么Helper是如果关联上View进而管理它们的呢?
(1)构造器里调用初始化init()函数
ConstraintLayout_Layout_constraint_referenced_ids通过该属性可以获得Helper所关联的View id串。进而调用setIds,addID等函数,解析出每一个真正的View所对应的id。并id信息存储于mIds等集合中。
protected void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = this.getContext().obtainStyledAttributes(attrs, styleable.ConstraintLayout_Layout);
int N = a.getIndexCount();
for(int i = 0; i < N; ++i) {
int attr = a.getIndex(i);
if (attr == styleable.ConstraintLayout_Layout_constraint_referenced_ids) {
this.mReferenceIds = a.getString(attr);
this.setIds(this.mReferenceIds);
}
}
}
}
(2)Helper绘制过程
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (this.mUseViewMeasure) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
this.setMeasuredDimension(0, 0);
}
}
public void onDraw(Canvas canvas) {
}
onMeasure里其实啥也没干,mUseViewMeasure默认为false,因此如果自定义Helper不设置这个值的话,Helper在xml里的宽高并没有影响,也没有任何作用,最终设置进去的都是0。
onDraw里直接是空,Helper虽然是View,但是并没有绘制上的性能损耗。
那么如何使用Helper来帮助我们管理View呢?答案就是在Helper提供的几个updateXX,updateXX与Helper的绘制生命周期所关联,因此自定义的Helper想要达到效果,必须触发绘制过程或者绘制过程的对应阶段。
public void updatePreLayout(ConstraintLayout container) {
}
public void updatePreLayout(ConstraintWidgetContainer container, , Helper helper, SparseArray map
}
public void updatePostLayout(ConstraintLayout container) {
}
public void updatePostMeasure(ConstraintLayout container) {
}
public void updatePostConstraints(ConstraintLayout constainer) {
}
(3)自定义Helper
Group和Layer都是属于一种自定义Helper,均继承与ConstraintHelper。所以再来看它们分别都干了些啥,导致有那些功能的。
Group
public void updatePreLayout(ConstraintLayout container) {
//获得当前Helper的可见属性
int visibility = this.getVisibility();
float elevation = 0.0F;
if (VERSION.SDK_INT >= 21) {
elevation = this.getElevation();
}
if (this.mReferenceIds != null) {
this.setIds(this.mReferenceIds);
}
//遍历关联的View,将helper的可见属性一一赋给它们
for(int i = 0; i < this.mCount; ++i) {
int id = this.mIds[i];
View view = container.getViewById(id);
if (view != null) {
view.setVisibility(visibility);
if (elevation > 0.0F && VERSION.SDK_INT >= 21) {
view.setElevation(elevation);
}
}
}
}
Layer
Layer是如何包裹住关联的View?
public void updatePostLayout(ConstraintLayout container) {
this.reCacheViews();
this.mComputedCenterX = 0.0F / 0.0;
this.mComputedCenterY = 0.0F / 0.0;
LayoutParams params = (LayoutParams)this.getLayoutParams();
ConstraintWidget widget = params.getConstraintWidget();
widget.setWidth(0);
widget.setHeight(0);
//计算Layer中心点的位置
this.calcCenters();
int left = (int)this.mComputedMinX - this.getPaddingLeft();
int top = (int)this.mComputedMinY - this.getPaddingTop();
int right = (int)this.mComputedMaxX + this.getPaddingRight();
int bottom = (int)this.mComputedMaxY + this.getPaddingBottom();
//跟据计算的中间点的位置Layout自身,自此Layer的大小和位置就确定,再设置Background就是顺其自然的事了
this.layout(left, top, right, bottom);
if (!Float.isNaN(this.mGroupRotateAngle)) {
this.transform();
}
}
protected void calcCenters() {
if (this.mContainer != null) {
//Float.isNaN() isNaN->is Not Number 测量一个值是不是科学数字
// 默认mComputedCenterX = 0.0F / 0.0是非法数字
if (this.mNeedBounds || Float.isNaN(this.mComputedCenterX) || Float.isNaN(this.mComputedCenterY)) {
if (!Float.isNaN(this.mRotationCenterX) && !Float.isNaN(this.mRotationCenterY)) {
this.mComputedCenterY = this.mRotationCenterY;
this.mComputedCenterX = this.mRotationCenterX;
} else {
View[] views = this.getViews(this.mContainer);
int minx = views[0].getLeft();
int miny = views[0].getTop();
int maxx = views[0].getRight();
int maxy = views[0].getBottom();
//遍历子View,min值能算出Layer的left和top
//max值能算出layer的right和bottom,不由得感叹真是奇思妙想
for(int i = 0; i < this.mCount; ++i) {
View view = views[i];
minx = Math.min(minx, view.getLeft());
miny = Math.min(miny, view.getTop());
maxx = Math.max(maxx, view.getRight());
maxy = Math.max(maxy, view.getBottom());
}
this.mComputedMaxX = (float)maxx;
this.mComputedMaxY = (float)maxy;
this.mComputedMinX = (float)minx;
this.mComputedMinY = (float)miny;
if (Float.isNaN(this.mRotationCenterX)) {
this.mComputedCenterX = (float)((minx + maxx) / 2);
} else {
this.mComputedCenterX = this.mRotationCenterX;
}
if (Float.isNaN(this.mRotationCenterY)) {
this.mComputedCenterY = (float)((miny + maxy) / 2);
} else {
this.mComputedCenterY = this.mRotationCenterY;
}
}
}
}
}
Layer还支持对关联View的位移、旋转、缩放等操作,但是使用的时候得小心,这些操作的中心点都是基于Layer的中心点
public void setRotation(float angle) {
this.mGroupRotateAngle = angle;
this.transform();
}
public void setScaleX(float scaleX) {
this.mScaleX = scaleX;
this.transform();
}
public void setScaleY(float scaleY) {
this.mScaleY = scaleY;
this.transform();
}
public void setPivotX(float pivotX) {
this.mRotationCenterX = pivotX;
this.transform();
}
public void setPivotY(float pivotY) {
this.mRotationCenterY = pivotY;
this.transform();
}
public void setTranslationX(float dx) {
this.mShiftX = dx;
this.transform();
}
public void setTranslationY(float dy) {
this.mShiftY = dy;
this.transform();
}
private void transform() {
if (this.mContainer != null) {
if (this.mViews == null) {
this.reCacheViews();
}
this.calcCenters();
double rad = Math.toRadians((double)this.mGroupRotateAngle);
//每次操作都会关联位移、缩放、旋转操作叠加效果,因此可以使用Layer对子View整体做一些动画
float sin = (float)Math.sin(rad);
float cos = (float)Math.cos(rad);
float m11 = this.mScaleX * cos;
float m12 = -this.mScaleY * sin;
float m21 = this.mScaleX * sin;
float m22 = this.mScaleY * cos;
for(int i = 0; i < this.mCount; ++i) {
View view = this.mViews[i];
int x = (view.getLeft() + view.getRight()) / 2;
int y = (view.getTop() + view.getBottom()) / 2;
// 默认情况下,mComputedCenterX和mComputedCenterY是Layer的中心点
float dx = (float)x - this.mComputedCenterX;
float dy = (float)y - this.mComputedCenterY;
//小心这里计算出的位移距离是对各种效果的叠加
float shiftx = m11 * dx + m12 * dy - dx + this.mShiftX;
float shifty = m21 * dx + m22 * dy - dy + this.mShiftY;
view.setTranslationX(shiftx);
view.setTranslationY(shifty);
view.setScaleY(this.mScaleY);
view.setScaleX(this.mScaleX);
view.setRotation(this.mGroupRotateAngle);
}
}
}
constraintlayout布局新特性_进阶ConstraintLayout-2.0新特性相关推荐
- servlet3.0新特性_查看Servlet 3.0的新增功能
servlet3.0新特性 随着JEE6规范上市,在企业应用程序领域中如何开发应用程序方面发生了一些重大变化. 在本文中,我将介绍有关Web应用程序开发的一些更改. 首先,请告别web.xml部署描述 ...
- .NET2.0和microsoft新知识体系-ASP.NET 2.0新特性
ASP.NET技术从1.0版本升级到1.1变化不是很大.然而,从ASP.NET 1.x升级到2.0,却不是件轻而易举的事情.ASP.NET 2.0技术增加了大量方便.实用的新特性.图1-1所示列举了A ...
- 我的世界java版特性_我的世界Java版特性展望直面会爆料
在今年我的世界MineconEarth的Java版特性展望直面会上,官方人员曝光了非常多Java版未来会加入的特性,现在就让我们一起来了解一下Java版未来的更新计划吧! [我的世界pc版交流群1]欢 ...
- 九州云腾双因素认证系统_“等保2.0”新标准落地 双因子认证(2FA)成标配...
2019年5月13日,国家标准新闻发布会正式发布网络安全等级保护制度2.0标准(以下简称"等保2.0"),新标准将于2019年12月1日开始实施,这意味着"等保2.0&q ...
- constraintlayout布局新特性_安卓ConstraintLayout布局
layout_constraintLeft_toLeftOf // 左边左对齐 layout_constraintLeft_toRightOf // 左边右对齐 layout_constraintRi ...
- HTML中三维特性,前端进阶系列(三):HTML5新特性
HTML5 是对 HTML 标准的第五次修订.其主要的目标是将互联网语义化,以便更好地被人类和机器阅读,并同时提供更好地支持各种媒体的嵌入.HTML5 的语法是向后兼容的.现在国内普遍说的 H5 是包 ...
- mysql数据库的新特性_【数据库】MySQL新特性归档介绍
MySQL 8.0.17发布了,看了下release note,发现果真如之前预期的那样,恢复了redo log归档(redo log archiving)功能.之所以说是"恢复" ...
- ES11新特性_绝对全局对象globalThis---JavaScript_ECMAScript_ES6-ES11新特性工作笔记067
我们打印一下这个globalThis这个对象去看看,这个是始终指向全局对象的一个系统变量可以直接使用. 可以看到在js中显示是window对象对吧 然后我们在node.js的环境中去试试,可以看到
- ES11新特性_可选链操作符---JavaScript_ECMAScript_ES6-ES11新特性工作笔记064
然后我们去看一下es11提供的这个可选链操作符 可以看到如果我们有个main方法,然后有个config参数 然后我们调用这个main方法 然后写入,db和cache,传入这个对象. 然后我们之前调用的 ...
- ES10新特性_字符串扩展方法_trimStart--trimEnd---JavaScript_ECMAScript_ES6-ES11新特性工作笔记058
我们来看一下,在es10中,还引入了,trimStart--trimEnd 分别用来清除一个字符串的左侧的空白和,右侧的空白,超级简单,不多说了. 技术交流QQ群[JAVA,C++,Python,.N ...
最新文章
- Java-并发-LockSynchronized
- apache评分表的意义_APACHE评分系统及评分表
- openssl 开启AES-NI指令集性能增加
- Windows2003使用WEB方式修改域用户密码
- 使用DLL封装窗体和业务类
- js 根据固定位置获取经纬度--腾讯地图
- 算法题存档20190127
- 苹果和谷歌在印度下架数十款中国应用;贾跃亭宣布破产重组完成;Tails 4.8 发布| 极客头条...
- 怎么用sql按条件把表分离_在做sqlserver数据库sql优化时,这25条事项需要注意
- 社交网络分析算法(SNA)
- 腾讯云TRTC —— 实时音视频完整案例 音视频+共享屏幕直播
- RB女歌手宇西个人单曲《盛宴》上线 诠释独自疗伤的故事
- 真香!有了这个搜索大法,GitHub玩到飞起来!
- python标准库复数运算包cmath
- 原型模式——java实现原型模式的几种写法
- 100句正能量的句子经典语句
- (trigger)触发器的定义和作用
- jmeter 察看结果树
- 三种常用的嵌入式操作系统
- DELL机器不能安装一键还原精灵装机版的解决方法(已解决)