前言
项目中对于图片的长宽比有很严格的需求,如果比例不一致,那么在App上显示会影响体验,于是要求长宽比一致。但是比例并不是固定的,有的图需要1:1比例,有的图需要14:9比例,有的图又需要9:16的比例。
起初我的想法是,自定义View在onMeasure里利用比例,将计算后的宽高设置给View就好了。但是这么一想,比例不一致啊。现在需要3种比例,我要自定义3个View,那如果后面有其他的一些比例呢?我不是又得写啦~
抱着偷懒的态度,我设想用自定义属性来解决这个问题,自己设置比例,这样只用自定义一个View,然后根据传入的比例再行计算即可。
自定义属性
添加属性
在res/value
文件夹下定义一个attr.xml
文件,添加如下代码:
1 |
|
radio即是代表比例,这里是高比宽。我是先获取宽,然后根据比例计算高。
设置属性
在xml顶层布局中添加xmlns:app="http://schemas.android.com/apk/res-auto"
,然后利用app:radio
设置属性,示例代码如下:
1 | <?xml version="1.0" encoding="utf-8"?> |
这里我设置的1.779,即高是宽的1.779倍,显示一个瘦窄的长方形。
获取属性
在自定义View中通过如下代码获取radio
属性:
1 | public CertainScaleImageView(Context context, AttributeSet attrs) { |
radio自定义View的一个属性,通过TypedArray获取相应的值并保存起来,TypedArray用完需要调用recycle()
。
计算宽高
获取属性之后,我们需要通过这个比例来计算宽高,代码如下:
1 | @Override |
获得宽度值,然后根据radio计算高度,然后调用setMeasuredDimension
即可。
总结
通过onMeasure,我们可以自行控制View要显示的区域。
在调用setMeasuredDimension
时,我们不仅需要计算它确切的高宽,还要给他设置一个MODE
。MODE
有三类:
- MeasureSpec.EXACTLY:精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width=”50dp”,或者为match_parent是,都是控件大小已经确定的情况,都是精确尺寸。
- MeasureSpec.AT_MOST:最大尺寸,当控件的layout_width或layout_height指定为wrap_content时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。
- MeasureSpec.UNSPECIFIED:未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。