こんにちは、GANMA!のAndroidアプリを担当しているゆのうえです。
Androidで丸い画像を表示するには色々な方法があります。 RoundedImageViewやPicassoなどのライブラリを利用して表示しているケースも多いのではないでしょうか。
単に丸くするだけならこのように
class RoundImageView : ImageView { constructor(context: Context) : this(context, null) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : this(context, attrs, defStyleAttr, 0) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) private val paint = Paint().apply { isAntiAlias = true } private var viewWidth = 0 private var viewHeight = 0 override fun onDraw(canvas: Canvas?) { val c = canvas ?: return (drawable as? BitmapDrawable)?.bitmap?.let { image -> val shader = BitmapShader( Bitmap.createScaledBitmap(image, c.width, c.height, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) paint.shader = shader; val circleCenter = viewWidth.toFloat() / 2; canvas.drawCircle(circleCenter, circleCenter, circleCenter, paint); } } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) viewWidth = MeasureSpec.getSize(widthMeasureSpec) viewHeight = MeasureSpec.getSize(heightMeasureSpec) } }
簡単に実装することもできます。 ただ、このサンプルや先述のライブラリはelevationに対応していません。 丸画像でelevationを表現するにはどうすればいいのでしょう?
CardViewにImageViewをネストする
elevation付きで角が丸いViewというと、Support LibraryにCardViewがあります。 CardViewでImageViewをラップしてやると、こうなります。
これで一応はelevationに対応した丸画像を表現できるのですが、画像表示にいちいちCardViewを利用するのには違和感があります。
CardViewの実装を見る
では、CardViewはどのように角丸の影を表示しているのでしょう。 CardViewの実装を見てみると、最初に背景画像としてRoundRectDrawableというDrawableを設定しています。
final RoundRectDrawable background = new RoundRectDrawable(backgroundColor, radius); cardView.setCardBackground(background);
最近のAndroidは角を丸めたDrawableを背景にすると、そのDrawableの形状に合わせてelevationに対応した影がつくようになっているようです。 ちなみにApiバージョン20以前のCardViewではDrawable上に自力で影の描画を行っています。
どうやらこれを真似してImageViewの背景にしてやれば、elevation付き丸画像が実現できそうです。
完成
実際に作成したもので表示した画像がこちらです。
分かりにくいので拡大。
うっすらとですが、ちゃんと影が付いています。
コードは後ほどライブラリとして公開予定です。