この記事はand factory Advent Calendar 2020の11日目の記事です。
昨日は@tokiyanさんの [BigSur] アプリケーションを開くためのアクセス権限がありません。の対処法 でした。
はじめに
Viewを角丸にする・色を変えるなど、Drawableを書く機会は多いと思います。
この記事では、私が個人的によく使っているDrawableの書き方のサンプルを紹介したいと思います。
色と同時にEffectを指定する
backgroundにcolorを指定し、foregroundにRippleEffectを指定する、なんて書き方をしている人は多いのでは無いでしょうか。
もちろんそれでも可能ですが、Effectを付け忘れること心配や、foreground指定がAPIレベルが23以上でないと使えないといった問題もあります。
そんな時に、Backgroundの色とEffectを同時に指定したDrawableを用意してしまうと便利です。
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/blue" />
</shape>
</item>
</ripple>
shapeのみで使うパターンにrippleを被せただけです。
これをbackgroundに指定すれば、背景色 @color/blue
と、RiipleEffectが同時に適応できます。
なお、 ?android:attr/colorControlHighlight
はデフォルトのRiipleEffectのカラーです。
角丸などの変形View+Effect
角丸のViewなどをDrawableで作っても、Effectがそれをはみ出してしまう例をよく見ると思います。
あれはRipleEffectがView全体に広がってしまうのが原因です。
これも先程と同じ様にrippleを被せると、Effectがその範囲だけに広がってくれます。
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item>
<shape android:shape="rectangle">
<corners android:radius="@dimen/button_radius" /> <!-- 角の丸み -->
<solid android:color="@color/blue" />
</shape>
</item>
</ripple>
Effect Only
ベタ塗りや枠の描画は行わず、Effectだけを適応するDrawableを作ることもできます。
複雑なViewの上部にFrameLayoutをかぶせて、そこにEffectを適用したい場合に使えます。
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask"> <!-- maskを指定する -->
<shape android:shape="rectangle">
<solid android:color="@color/white" />
</shape>
</item>
</ripple>
id/mask
以下の要素でEffectがMaskされます。
これは塗りつぶしているので、EffectだけのDrawableになります。
円形Effect Only
先程のを応用すると、円形のEffectだけのDrawableなんかもできます。
円形のViewをはみ出すようなEffectを付けたい場合などに使えると思います。
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="oval"> <!-- ovalを指定 -->
<solid android:color="@color/white" />
</shape>
</item>
</ripple>
Viewに沿ったovalになるので、長方形、正方形のViewでそれぞれ形が変わります。
Effectを動的に作る
動的にViewを作りつつ、背景色を変え、Effectも付ける、なんていう時にはDrawableを動的に書く必要がでてきます。
#ffffff
などを引数にして、以下の様に作る事ができます。
fun TextView.setCustomDrawable(textColor: String, backgroundColor: String, borderColor: String) {
if (textColor.isNotBlank() && backgroundColor.isNotBlank() && borderColor.isNotBlank()) {
setTextColor(Color.parseColor(textColor))
// 角丸と色の設定
val pressedDrawable = GradientDrawable().apply {
setColor(Color.parseColor(backgroundColor))
cornerRadius = context.resources.getDimensionPixelSize(R.dimen.radius).toFloat() // radiusは定義しているとします
setStroke(4, Color.parseColor(borderColor)) // `1`はStorkeのWidth
}
// `?android:attr/colorControlHighlight` の取得
val typedValue = TypedValue()
context.theme.resolveAttribute(android.R.attr.colorControlHighlight, typedValue, true)
val color = ContextCompat.getColor(context, typedValue.resourceId)
// RippleEffectの設定
val rippleDrawable = RippleDrawable(ColorStateList.valueOf(color), pressedDrawable, pressedDrawable)
this.background = rippleDrawable
}
}
placeholderを自作する
少し毛色を変え、placeholderに使えるDrawableについてです。
対象として、アプリのロゴを入れたplaceholderを使う場合を想定しています。
placeholderを設定する箇所毎に、サイズの違う画像をデザイナーが用意してそれを使用する、なんていう事があると思います。
そんな時は、placeholder用のアプリロゴだけ用意してもらい、Drawableで必要サイズの画像を用意してしまえば、
画像分の容量が削減でき、デザイナーの負担も減ると思います。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/darker_gray" /> <!-- 背景色を指定 -->
<size
android:width="100dp"
android:height="100dp" />
</shape>
</item>
<item
android:width="24dp"
android:height="24dp"
android:drawable="@drawable/icon_logo"
android:gravity="center" />
</layer-list>
また、これで作成した画像は scaleType="fitXY"
で配置すると、伸縮するのが背景色部分になり、ロゴのサイズ自体は変わりません。
これで更に細かく画像を用意する必要が減ると思います。
おわりに
Drawableをうまく活用すると、結構いろいろなViewが作れます。
是非Drawableを活用し、UIのブラッシュアップや、容量・手間の削減に役立ててください。