Little Strange Software

スマホアプリの開発を行う LittleStrangeSoftware のブログです。

続・kotlinでコードから動的に<SHAPE>の装飾を変更するには?

前回のあらすじ

  どうも!LSSです!
 前回の記事にて、「SHAPEによるボタン等の装飾をkotlinのコードから設定するには」という事で、以下のように書きました。

 

xmlでの記載 kotlinでの記載
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android=
"http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<gradient
android:angle="270"
android:startColor="#FFFFFF"
android:centerColor="#666666"
android:endColor="#555555"

android:type="radial"
android:gradientRadius="135dp"
android:centerX="0.2"
android:centerY="0.2"
/>

<corners android:radius="10dp"/>
<stroke android:width="1dp"
android:color="#666666"/>

</shape>
</item>
</selector>
fun bt1redraw(){

val dp2px = getResources().getDisplayMetrics()
val gd0 = GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf( Color.parseColor("#FFFFFF") ,
Color.parseColor("#666666") ,
Color.parseColor("#555555")
)
)
gd0.setGradientType(GradientDrawable.RADIAL_GRADIENT)
gd0.setGradientRadius(135 * dp2px.density)
gd0.setGradientCenter(0.2f ,0.2f )

gd0.setCornerRadius(10f * dp2px.density)
gd0.setStroke((1 * dp2px.density).toInt() ,
Color.parseColor("#666666"))

bt1.setBackgroundDrawable(gd0)

}

 

  ですが、さすがにちょっと投げっぱなし感?だったので、今回は続編という事で、もう少し掘り下げて記事にしたいと思います。

 


<shape android:shape="rectangle">

 こちらはxmlにのみ書いてて、kotlinのほうの設定は書いていませんでしたね。
 これも多分コードから設定できるんだと思いますが、とりあえず割愛します。

 で、このrectangleですが、こちらは四角形を意味します。
 このandroid:shape="rectangle"で、「形状は四角形ですよ~」と言ってるわけですね。
 ここで設定できる内容は、rectangleの他に次のようなものがあります。


 oval 楕円形
 line 直線
 ring 輪  

 

 「直線」ってどういう事よ!?って気になったので、試してみると…

f:id:little_strange:20190917214030p:plain

 こんなん出ました~
…これ、形状というより取り消し線ですねぇ。

 

 次は、gradientタグにつけるオプションです。

 


android:angle="270"

 これは、グラデーションの方向を角度で示したものです。

 この数字を"0"にすると、「左から右(→)」という素直な方向のグラデ―ションになり、"90"にすると、反時計回りに90度回転して「下から上(↑)」というグラデーションになります。

 "180"は「右から左(←)」で、"270"は「上から下(↓)」って事になります。

で、これをkotlinのコードから指定する時の記載ですが、xmlだと"270"としていたものが、kotlin上はTOP_BOTTOMとなります。
「上から下(↓)」って事ですね。

 なお、kotlinで記載する際には他に、

 LEFT_RIGHT
 BOTTOM_TOP
 RIGHT_LEFT

がある他、

 BL_TR
 BR_TL
 TR_BL
 TL_BR

という指定が使えます。

 T=Top=上、B=Bottom=下、L=Left=左、R=Right=右、と読み替えると、例えばBL_TRは、「下左から上右」、自然な日本語だと「左下から右上」に向かうグラデーションになります。

 xmlでの数字の指定も45度単位で設定できるので、8つの方向を選べるって事ですね。(と長々書きましたが、自分のサンプルではグラデーションの形状を「放射状」にしているため、その場合は意味のない設定となるようです^^;。)

 


android:startColor="#FFFFFF"

 同じくgradientタグにつけるオプションで、これは「グラデーションの開始色」を指定しています。
 ちなみに#FFFFFFは白色です。

 同様に、android:centerColor="#666666"は「グラデーションの中間色」、android:endColor="#555555"は「グラデーションの最終色」で、この3色を指定してあげると、グラデーションは

「開始色から始まり、だんだん中間色に近づき、だんだん最終色になっていく」

という変化になります。

  これをコードから指定する場合、

val gd0 = GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf( Color.parseColor("#FFFFFF") ,
Color.parseColor("#666666") ,
Color.parseColor("#555555")
)

の部分になるのですが、
「グラデ―ションの方向、開始色、中間色、最終色」は、
kotlinから設定する場合には「GradientDrawableのインスタンス作成時に一気に決めてしまう!」もののようです。

 


android:type="radial"

 こちらも、xml上ではgradientタグのオプションの一つとしてタグ内に記載するもののひとつで、グラデーションの形状を設定する部分です。

"radial"は「放射状」のグラデーション、中心から外に向かって色が変化していきます。

 ここで設定できるのは他に"linear"と、"sweep"があります。

"linear"は直線的に色が変化(ごくごく普通のグラデーションといえばこれかな、って感じの)、"sweep"は「走査」と他サイトの説明にありましたが、どう言えばいいんだろ…言葉で表現するのは難しいですが

f:id:little_strange:20190917223755p:plain

ぶっちゃけ、sweepはこんな感じになります^^;;;

 

 kotlinでの指定は、 

gd0.setGradientType(GradientDrawable.RADIAL_GRADIENT)

 のように、あらかじめ作ったGradientDrawableオブジェクトに対してsetする事で指定してやれば良いみたいです。

 


android:gradientRadius="135dp"

  これはandroid:type="radial"の時にのみ有効となるオプションで放射の大きさを指定します。自分の出したサンプルの場合、ここの指定によって光が大きくなったり小さくなったりします。

 kotlinでの指定は、

gd0.setGradientRadius(135 * dp2px.density)

のように、あらかじめ作ったGradientDrawableオブジェクトに対してsetする事で指定してやれば良いみたいです。(コピペ便利!)

 


android:centerX="0.2" android:centerY="0.2"

 次にこの指定。これは「グラデーションの開始位置をずらす」指定です。

 グラデーションの開始位置は この設定をしないと、左上から始まりますが、
centerXを0~1の間の小数で指定すると開始位置が右にずれ、
centerYを0~1の小数で指定すると開始位置が下にずれます。

 それぞれを0.5にすると、どまんなかから始まるグラデになります。

 

 kotlinでの指定は、

 gd0.setGradientCenter(0.2f ,0.2f )

のように、あらかじめ作ったGradientDrawableオブジェクトに(以下略)。

 

  gradientタグのオプションの説明(=グラデーションの説明)は以上です! 

 


 <corners android:radius="10dp"/>

 さて、新しいタグですが、こちらが本題とも言える(?)「角丸」の設定です。

 この 数値で角丸の大きさを変更でき、0にすると角丸ではなくなります。

 

 kotlinでの指定は、 

gd0.setCornerRadius(10f * dp2px.density)

 のように、あらかじめ作ったGradientDrawableオブジェクトに対してsetする事で指定してやれば良いみたいです。

 

※どうでもいい余談ですが、自分の場合、初めてこれを試そうとした時、
xmlcournersと書いてしまい、なぜ反映されないのかひとしきり悩んだという、
つい最近の思い出があります^^;;;;;

  


<stroke android:width="1dp" android:color="#666666"/>

 最後にこのstrokeですが、これは「外枠」についての設定です。

 widthで外枠の太さを決め、colorで枠の色を指定するのですね。

 

  kotlinでの指定は、 

gd0.setStroke( (1* dp2px.density).toInt() ,
Color.parseColor("#666666"))

 のように、あらかじめ作ったGradientDrawableオブジェクトに対してsetする事で指定してやれば良いみたいです。(コピ…もういいか^^;。)

 


bt1.setBackgroundDrawable(gd0)

  これはkotlinコードの最後の記述です。

 bt1(というidのボタン)に、設定し終わったgd0(というGradientDrawableオブジェクト)の効果を反映してね!っていう命令です。

 xmlで言うと、ボタンのbackgroudにSHAPEを記述したxmlを設定する部分にあたる、って事ですね。

 


 

  いかがでしたでしょうか?

 自分も勉強しはじめたばかりの身で、つらつらと書いたものですが、もしいつかこの記事が誰かの役に立てばいいな~と思いながら、今回はここまでにします。 

  読んでくださってありがとうございます!

 

<2019/9/18 追記>

https://developer.android.com/reference/android/graphics/drawable/GradientDrawable.html?hl=ja

多分ここに書かれてる情報が、今回の記事内容関連で詳細にあたる部分っぽい。
…自分にはまだ読み解く技量はありませんが^^;