约束布局的布局方式
constranitLayout布局内视图的方位介绍
app:layout_constraintBaseline_toBaselineOf="@+id/TextView1"/>
其他的属性如下:
layout_constraintLeft_toLeftOf,layout_constraintRight_toLeftOf,layout_constraintRight_toRightOf,layout_constraintTop_toTopOf,layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf,layout_constraintBottom_toBottomOf,layout_constraintStart_toEndOf,layout_constraintStart_toStartOf,layout_constraintEnd_toEndOf
2 角度定位
… />
3 边距
和普通视图的margin属性一样用法,但约束布局中有app:layout_goneMargin=“XXdp”,在相对位置的视图为gone的时候,生效margin属性,如下:
4 居中和偏移
居中显示方式,相对于parent视图,上下左右分别对齐:
app:layout_constraintBottom_toBottomOf=“parent”
app:layout_constraintLeft_toLeftOf=“parent”
app:layout_constraintRight_toRightOf=“parent”
app:layout_constraintTop_toTopOf=“parent”
视图本身的定位需要有头有尾,左右,上下需要成对出现,才能生效。设置水平0.3偏移(居中是0.5偏移)
app:layout_constraintLeft_toLeftOf=“parent”
app:layout_constraintRight_toRightOf=“parent”
app:layout_constraintHorizontal_bias="0.3
bias范围是0-1之间,
layout_constraintHorizontal_bias 水平偏移,layout_constraintVertical_bias 垂直偏移
5 尺寸约束
官方不推荐在ConstraintLayout中使用match_parent,设置为0dp之后,使用左右上下对齐,可以保证撑满整个屏幕
在设置宽高比的值的时候,还可以在前面加W或H,分别指定宽度或高度限制。 例如:
app:layout_constraintDimensionRatio="H,2:3"指的是 高:宽=2:3
app:layout_constraintDimensionRatio="W,2:3"指的是 宽:高=2:3
6 链
头部第一个视图设置layout_constraintHorizontal_chainStyle来改变整条链的样式。chains提供了3种样式,分别是:
CHAIN_SPREAD —— 展开元素 (默认);
CHAIN_SPREAD_INSIDE —— 展开元素,但链的两端贴近parent;
CHAIN_PACKED —— 链的元素将被打包在一起。
题外:
弹性布局FlexboxLayout
该布局和css flex布局功能几乎一样,但是没有视图回收功能,在布局大量的子视图的是性能差。
flex布局属性:flexDirection,flexWrap,justifyContent,alignItems,alignContent
flex子视图属性:layout_order,layout_flexGrow,layout_flexShrink,layout_alignSelf,layout_flexBasisPercent
FlexboxLayoutManager
该视图管理器可以和recycleview配合使用,布局属性和功能和flexboxLayout一样,但是具有视图回收功能,性能比较好。
RecyclerView初始化:
mRecyclerView = (RecyclerView)findViewById(R.id.test_recyclerView);
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);
layoutManager.setFlexDirection(FlexDirection.ROW);
layoutManager.setAlignItems(AlignItems.STRETCH);
layoutManager.setJustifyContent(JustifyContent.FLEX_START);
mRecyclerView.setLayoutManager(layoutManager);
adapter 的onBindViewHolder函数:
ViewGroup.LayoutParams lp = te.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
FlexboxLayoutManager.LayoutParams flexboxLp = (FlexboxLayoutManager.LayoutParams) lp;
flexboxLp.setFlexGrow(1.0f);
flexboxLp.setAlignSelf(AlignItems.FLEX_START); //子视图可以覆盖父容器的align的属性
}
效果如下:
约束布局的辅助对象
1 Optimizer
当我们使用 MATCH_CONSTRAINT 时,ConstraintLayout 将对控件进行 2 次测量,ConstraintLayout在1.1中可以通过设置 layout_optimizationLevel 进行优化,可设置的值有:
none:无优化
standard:仅优化直接约束和屏障约束(默认)
direct:优化直接约束
barrier:优化屏障约束
chain:优化链约束
dimensions:优化尺寸测量
2 Barrier
一个屏障,用于隔断你所引用的视图的边缘,无大小,不占空间
3 Group
视图分组,可以对批量的视图进行显示和隐藏操作
4 Placeholder
占位视图,app:content="@+id/textview" 属性可以设置占位视图应该显示为id是textview的视图。
5.Guideline
辅助线,辅助定位的作用,在视图中无大小,不占空间,只用作约束定位。
android:orientation 垂直vertical,水平horizontal
layout_constraintGuide_begin 开始位置
layout_constraintGuide_end 结束位置
layout_constraintGuide_percent 距离的百分比
性能测试
构建如下布局,采用约束布局和普通布局,然后对比measure到layout结束所消耗的时间。视图树结构,左边是约束布局,右边是普通布局:
measure()->layout()->draw(),假设有n个视图,这个过程遵从树的遍历过程,那么约束布局的 measureLayout大概需要执行 n* measureLayout方法,
普通视图大概需要执行 2nmeasureLayout方法,在relativelayout布局中,还会主动measure子视图两次(一次是水平measure,一次是正常measure),因此普通视图效率会更低,上面的
视图树,理论来说约束布局对比普通视图会减少一半的measureLayout时间,理论是理论,来实践下吧。
1.addOnFrameMetricsAvailableListener
该方法设置给window对象,每次frame更新之后会回调方法,方法有个参数是FrameMetrics,可以查看很多耗时信息,这里只使用它的LAYOUT_MEASURE_DURATION数据。
1.强制measurelayout过程:
2.每次回调之后,累加耗时,100次求取平均值。
经过多次测试,结果如下,简单布局就是上述所说的布局样式,复杂布局是将上述布局放入到recycleview中铺满屏幕:
可以看到,在不复杂的情况下,使用约束布局和理论差不多两倍关系,在复杂场景下,约束布局也比普通布局更加有优势。
更多FrameMetrics信息查看:https://developer.android.com/reference/android/view/FrameMetrics
其实FrameMetrics的信息,用adb也可以收集出来,使用adb shell dumpsys gfxinfo com.example.myapplication framestats命令输出FrameMetrics统计信息,
用echart表格可以展示如下:
dumpsys命令详情:https://developer.android.com/studio/command-line/dumpsys
2.systrace的使用
使用该工具可以统计对应进程,运行时间,以及追踪函数调用等等功能。该工具最大的好处可以用来查看是哪个函数对UIThread造成了卡顿,可以针对性的优化。
使用该工具的前提条件如下:
第一,android 4.1及以上的设备
第二,开启调试模式,安装你的应用
第四,需要安装python2
首先进入你的systrace目录:cd D:/android-sdk/platform-tools/systrace
在执行命令:python systrace.py --t 10 -o mynewtrace.htm -a cn.com.egova.egovamobile,
-t代表抓取时间,-o代表统计数据保存的文件位置,-a代表抓取的进程
上述命令可以收集智信的相关数据。
我在MorePluginManageActivity中进行滑动10s,统计数据如下,可以看到红色的F是超过16ms的一帧,从上往下是函数调用链,从左往右是时间轴,其中obtainView ,setupGridItem
函数占据了Choreographer#doFrame操作的大部分,在代码里面搜索可以知道这是grideview的adapter的内部函数,也就是自定义的 PluginGridAdapter,TopGridAdapter耗时过长
在代码中设置Trace.traceBegin开始,Trace.traceEnd结束,代码会将Trace包裹的这段代码的统计信息输出到统计文件中,在随后的html页面中可以进行展示
systrace的使用以及参数配置请查看:https://developer.android.com/studio/profile/systrace/command-line