由上图可以看到ShapeableImageView也没有什么神秘的,不过是ImageView的一个子类而已,但是从效果图来看,在不写shape、不引入三方库的情况下,还是挺容易实现预期效果的,而且扩展性良好。
关于xml属性,我也做了一个整理,属性不多,只有4个
前面为了整体的排版,埋了几个伏笔,下面来一一解答。
会涉及到源码,但是经过去繁从简,看起来也非常轻松的。
前面可以看到我们设置圆角其实是用的style,那为什么不直接用attrs呢,不是更加直观方便吗,带着疑问来看看源码是怎么处理的。
直接看ShapeableImageView的次构造方法:
常规 *** 作,获取自定义属性。
关键的两行代码:
也就是说我们给shapeAppearance设置的style,并不是ShapeableImageView自己来处理的,而是由ShapeAppearanceModel来构建的,然后又交给MaterialShapeDrawable来绘制的。
这个类就厉害了,有点像Flutter中的Decoration,可以构建出花里胡哨的效果。
来看ShapeAppearanceModel部分源码:
可以看到有各种边和角的属性,这里注意两个点:
也就意味着,边和角除了默认,是可以自定义的,这就有极大的想象空间了,比如这样:
再比如这样:
源码(有删减):
没什么特别的,你只需要知道除了可以设置描边之外,还可以设置背景、阴影等其他属性。
这里借github一张图
又是自定义view的常规 *** 作,有一半画笔是在边界外面的,所以需要设置padding为strokeWidth的一半。
有细心的同学会发现啊,第一个常规的ShapeableImageView还是有一点圆角的,没错,属于默认的,跟踪一下源码来看一下:
第一个是颜色,很明显不是我们要找的,继续看shapeAppearanceMediumComponent
只是一个简单的属性,继续查找关联引用
又引用了一个style,继续看ShapeAppearance.MaterialComponents.MediumComponent这个style
哦豁,看到了熟悉的属性cornerSize,藏的还挺深,继续看看数值是多少
默认4dp。
那如果不想要这个圆角怎么办呢,可以学习源码仿写一个,不过上面也看到了,有点绕,不如直接写个style搞定:
然后引用
效果:
ok,到这里就差不多了,虽然还有很多相关知识点没有提及,但是也不少了,不如自己去尝试一番,慢慢消化。
https://github.com/yechaoa/MaterialDesign
在使用 ImageView 的过程当中,经常需要通过 scaleType 来对原始的图像进行处理,使得它能在空间中合理地展示。
首先,我们简单介绍一下 scaleType 的分类:
这种情况下,对应的模式只有一种:
最终,在这种情况下,我们可以同 setImageMatrix(Matrix matrix) 来改变。
这一类属性的特点就是 通过拉伸或者压缩图片,使得原图片中所有元素都能够展现,并且至少填满控件 x,y 轴的其中一个 。
一共有四类:
下面三种都会 维持原图的比例 ,使得它们的 x,y 都小于等于控件的宽高,只是最终的图形放的位置不同。
下面的三种类型都会使得控件的中心和图片中心重合:
它不要求原始图片填满 x,y 轴的任意一个,因此, 如果原图的长宽都小于等于控件的长宽,不会进行放大 *** 作,这也是它和 ScaleType.FIT_CENTER 的区别 。
下面,我们通过一个简单的 Demo 来展示一下各种类型的具体表现,我们有两个大小一样的 ImageView 和两个大小不同的原图,其中左边的 ImageView 要比原图小,右边的 ImageView 要比原图大。
在 ImageView 当中,设置图片的接口主要有下面几个函数:
我们就以平时常用的 setImageBitmap 为例,分析一下它整个的流程:
上面的关键方法在 updateDrawable 当中:
在 configureBounds 里就会根据我们所配置的 scaleType 来决定 mDrawable 如何显示,在这里面有一个重要的变量 mDrawMatrix ,我们前面说到的所有变换都是通过它来实现的,当然,我们除了可以让系统自己根据 scaleType 来生成 matrix ,也可以通过 setImageMatrix 手动的指定自己的变换:
那么这个 mDrawMatrix 是在什么时候使用的呢,我们看一下 onDraw 方法:
我们总结一下,整个 scaleType 的原理就是在 configureBounds 中配置了 mDrawMatrix ,而在 onDraw 当中会根据 mDrawMatrix 来对图层进行变换,在这个变换之后的图层上进行绘制 mDrawable ,之后再恢复图层。
上面,我们看到的都是 src 设置的效果,我们回忆一下,通过设置 android:background 也可以设置一个图片给它,其实 background 是 View 的属性,在我们之前分析 View 的绘制流程的时候, draw(canvas) 中有一步就是绘制背景:
我们来看一下设置背景的边界的函数,可以看到,这里没有考虑 padding 值,也就是说我们通过 background 设置的图片是填满整个控件,并且不考虑 padding 的:
最后再结合一下第四节的知识,我们是先绘制背景,然后才在 ImageView 的 onDraw 函数当中在 canvas 上绘制的,因此, src 的图片一定会绘制在 backgroud 之上。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)