ボタンの外観を変えるには、
void setBackgroundColor(int color) void setBackgroundDrawable(Drawable d) void setBackgroundResource(int resid)
なんかを使う。
ただし、これらで画像や色を指定をした場合、カーソル表示や決定の反応なんかはなくなってしまう。
それは寂しいし、第一、なにを選択しているのかわからず、ユーザーライクではない…。
それじゃ、どうするかっていうと、xml指定することになる。
でも、動的に変えたい場合もあるよね?
たとえば、ユーザーに色変更させたい、Webからダウンロードしたものにしたい、etc…。
そんなときはどうするか?
結論からいうと、Button class をベースに新規class を作るのが早道みたいだ。
でも一応、調べてみたことを書いておくよ。
それと、サンプルのソースも。
外観設定の仕組み(xml)
おおざっぱにいうと、仕組みはこんな感じみたい。
button.xml (ファイル名任意) android:background ↑ style.xml (ファイル名任意) <item android:state_focused="true" android:color="@color/color1" /> <item android:state_pressed="true" android:state_enabled="false" android:color="@color/color2" /> ……
で、android:background に相当するmethod が、先のsetBackgroundになる。
focuse やpress を設定するmethod はない。
それじゃ、style.xml に相当するものを用意し、設定すればよいのだろうか…?
StateListDrawable
StateListDrawable については、実は確かめてない。
だからこの項目は、推測のものになるので、読みとばしてくれていいよ。(^_^;
ざっと見のリファレンスからすると、StateListDrawableは、xmlみたいな設定を作成・編集するものみたいだ。
DrawableContainer の継承で、大元はDrawable だから、Drawable指定の引数に使用できるハズ。
きっと、setBackgroundDrawable(Drawable d) に渡せば、xml指定と同じことができると思う。
StateListDrawable にあるmethod の…
void addState(int[] stateSet, Drawable drawable) Add a new image/string ID to the set of images.
の第一引数・stateSet はおそらく、Button 内で定義されている↓なんかだろう。
(Button) int[] ENABLED_FOCUSED_SELECTED_STATE_SET Indicates the view is enabled, focused and selected.
おそらく、↓みたいな指定をすればいいのかな?
stateListDrawable.addState( Button.ENABLED_FOCUSED_SELECTED_STATE_SET, drawable );
そんで最終的に、mutate()でDrawable として出力するんじゃないかな?
Drawable mutate() Make this drawable mutable. (StateListDrawable)
そのDrawable をsetBackgroundDrawable した後に、
(Button) void refreshDrawableState() Call this to force a view to update its drawable state.
…は実行しなくてもいいのかな…?
ちなみに、テキストカラーではColorStateList がStateListDrawable に相当するんじゃないかな?
…と。調べてみたのはココまで。
ここから先は実証実験ってことになるんだけど…。
その試行錯誤のコストは、結果に見合わない気がしたんだ。(^_^;
なぜなら、色々やってみて失敗するより、任意のButton class を作ってしまう方がてっとり早く確実だから。
iアプリなんかだと、アプリ容量が懸念されるところだけど、Android はそんな心配さらさらないからね。
StateListDrawable については、ココで打ち切ることにした。
任意のButton class を作る
結局のところ、xml指定しない場合、この方法がよいみたいだ。
そんなに難しいことでもないしね。
classを初めてイジる人には、ちょうどいいお題じゃないかな?
サンプルのソースはこんな感じで作ってみた。
素のボタンとそう変わりないから、Buttonを置き換えるだけで使えるよ。
package com.migimaki.android; import android.widget.Button; import android.content.Context; import android.graphics.Color; import android.graphics.Rect; import android.view.animation.AlphaAnimation; import android.view.animation.CycleInterpolator; import android.view.animation.TranslateAnimation; import android.util.Log; public class MyBut extends Button { public MyBut ( Context c ){ super( c ); //-- // 背景色設定 setBackgroundColor(Color.argb(128, 0, 0, 255)); // 青 //-- } // Event : Focus Changed public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect){ if ( isFocused() ){ // 背景色設定 setBackgroundColor(Color.argb(128, 0, 255, 0)); // 緑 //// TranslateAnimation translate = new TranslateAnimation( 0, 100, 0, 0 ); translate.setDuration(4000); translate.setInterpolator(new CycleInterpolator(1)); startAnimation(translate); ////-- } else { // 背景色設定 setBackgroundColor(Color.argb(128, 0, 0, 255)); // 青 //// AlphaAnimation alpha = new AlphaAnimation( 1, 0.75f ); alpha.setDuration(4000); alpha.setInterpolator(new CycleInterpolator(1)); startAnimation(alpha); ////-- } } }
選択されていない状態は青。
選択されると、緑。
と、ボタンの背景色が変わる。
決定された状態は、リスナー側のonClick()内でやることになる。
class内でやる方が美しいんだけど、イマイチ、その意味を見いだせなかった。
それと、onTouchEvent なんかでやってみたら、onClickが発生しなくなってしまったんだ。
色々イジくるより、onClick でやる方がてっとり早い。
オマケで、Animation のエフェクトをつけてみた。
フォーカスが外れると、半透明で点滅。
選択されると、横方向に揺れる。
縦にボタンを連ねた状態で、カーソル・キーでフォーカスを連続移動させると、階段を登るみたいでちょっとおもしろい。