在上一篇文章【ImageView】自定义ImageView系列(二)——功能全面的带边框圆形图片中,介绍了一个较为优秀的的自定义圆形ImageView开源库:
Pkmmte/CircularImageView
使用它,能够实现带边框的圆形图片功能。
GitHub上还有一个star量比较高的开源库,大家也可以借鉴学习使用:
hdodenhof/CircleImageView
通过前面两篇文章,自定义控件实现圆形ImageView的功能就能很熟练地使用了。有了前面的基础,接下来介绍的圆角图片功能的实现就不会那么陌生了。使用案例同样是GitHub上的开源代码:
SelectableRoundedImageView
在正式解剖这个开源项目之前,鸟哥想在这篇文章中给大家分享一下原作者Joonho对于做这个开源库的介绍。鸟哥觉得看一下这个开源库的需求存在和知识组成,不仅能够对SelectableRoundedImageView的实现有一个更好的了解,同时确实能够在产品开发中学到一些设计思想和技术思路。
- Author:Joonho
- Title:How I made SelectableRoundedImageView library (looking for a good way to implement the CardView)
- Address:How I made SelectableRoundedImageView library (looking for a good way to implement the CardView)
Executive Summary
I wanted to make an app that uses newly introduced CardView and I wanted to put an ImageView on top of it, as demonstrated in Material Design spec like below.
But then I found Android framework’s ImageView class doesn’t support rounded corners just for left-top and right-top corners nor other open-source libraries. So I made one.
I believe that CardView looks much better when ImageView inside it get rounded only left-top and right-top corners, even though Google’s Android app, such as Play Newsstand, Play Movie, aren’t implemented that way. But other some prominent app, such as Pinterest, has implemented beautiful CardView in Google’s Material Design way.
I got basic idea of this implementation from PaintDrawable class, and I could learn valuable lessons about how ImageView.ScaleType works from this work. This article is all about the journey I took from basic idea to full implementation.
Getting the Idea
(Note: There is a good Android open-source project, developed by Vince, which supports rounded corners. Unfortunately, you can only apply the same radius on every corner, because it uses Canvas.drawRoundRect() method which takes only one parameter as radius. So it couldn’t meet my needs, because I wanted to make it get rounded only top-left and top-right corners.)
So basically it was something like connecting the dots.
First, I knew that we can draw rounded rect with BitmapShader and Canvas.drawRoundRect method which I learned from Romain Guy’s blog article.
Also, I have seen rounded rect demo in Android framework’s ApiDemos app that displays rect images with different radii on every corner. You can check below screen in ApiDemos -> Graphics -> RoundRects.
So, I thought ‘Maybe I can make ImageView get rounded on every corner with different radii, if I can successfully combine these two!’.
And it really was. The ApiDemos app used GradientDrawable class and its instance method setCornerRadii to apply different radii on each of the four corners. So, if there is Drawable class which has setCornerRadii method and also supports Paint setting(Because we can apply BitmapShader to Paint), the job would be easily get done. So I searched it, and hooray! PaintDrawable class was just the right one that I looked for.
I first tried to implement this library using PaintDrawable, but after some digging, I realized I didn’t even need to use PaintDrawable class. I found that PaintDrawable class extended ShapeDrawable class, which draws itself using Canvas.drawPath method when its shape is RoundRectShape.
How do they use CardView? and What is the best way for using it?
So, check below screenshots. I collected only those which put ImageView on top of CardView.
-
Google Play Newsstand
-
Google Map
-
Google Play Movie
So, as you can see, ImageViews don’t get rounded when not only it is placed on top but also placed on left or right. Let’s see another implementation of CardView.
- Pinterest
So, Pinterest made ImageView get rounded. What do you think about this? Which way is better for using it?
Well, there is no “right” answer for this matter. But I believe that CardView looks much better when it is rounded.
First, I think it is about identity of CardView, meaning what a widget called CardView should look like, and feel like. Of course, there can be adjustment and variation, but it should have good reason for that, and go along with the original concept of the widget. Material Design Spec guides “Cards have rounded corners.” and “(square corners) is a tile, not a card.”.
Second, it looks better when it is rounded in aesthetic regards. Well, I can’t prove this, but the fact that all the sample images of CardView in Material Design Spec document are rounded could be strong indication for this. Another grounds for this is CardView clips its children that intersect with rounded corners from Lollipop and after.
So, I delivered all my thoughts. You can set different radii on every corner of ImageView with my SelectableRoundedImageView library. I hope this library can help you guys a little.
(TO-DO. Arrange how each of ImageView.ScaleTypes works)
(TO-DO. Compare my approach of implementation with others including path clipping and redrawing)
补充:下一篇再仔细分析一下 SelectableRoundedImageView
的实现细节,欢迎关注。
鸟哥公众号二维码【技术鸟】,
打开微信扫一扫,
欢迎关注留言!