ボタンの外観を変える

 ボタンの外観を変えるには、xmlで設定し、それをsetBackgroundResource() method で適用することになる。
 ※.「xmlナシ」については→XMLなしで、ボタンの外観を変える

setBackgroundResource

 引数に、設定xmlを指定するだけ。
 たとえばこんな感じ。

	but.setBackgroundResource( R.drawable.button_style );

 ※.xmlファイル名は任意

XMLの設定

 ただ単に外観を変えるだけなら、xmlの設定は必要ない。
 setBackgroundDrawable()やsetBackgroundResource() を使えばいい。
 設定xmlが必要になるのは、状態によって変化させたいとき。
 たとえば、ボタンにフォーカスが当たった、ボタンを選択された。
 これらの「状態」と、その時の「色・画像」を設定したものが、設定内容となる。

 単純に選択/非選択だけの設定ならこんな感じになる。

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

	<item android:state_focused="true">
		<color android:color="#ff00ff00" />
	</item>
	<item>
		<color android:color="#ff0000ff" />
	</item>

</selector>

 全てを設定すると、こんな感じ。

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:state_enabled="false" >
		<color android:color="#00ffffff" />
	</item>
	
	<item android:state_pressed="true" >
		<color android:color="#80ff0000" />
	</item>
	<item android:state_focused="true">
		<color android:color="#8000ff00" />
	</item>
	<item>
		<color android:color="#800000ff" />
	</item>
</selector>

 上から順に…

  • 選択できない(非活性) … 透明(白)
  • 押された瞬間 … 赤(半透明)
  • 選択された … 緑(半透明)
  • 選択されていない(通常) … 青(半透明)

 実行すると、「clickしたのに、緑色になる…」なんて風に思うかもしれない。
 でもよく見てほしい。
 clickした瞬間は赤になるハズだ。
 どうもstate_pressed は、clickした瞬間を表しているらしい。
 決定状態を作るには、リスナーのonClickでやる以外はなさそうだ。

設定は優先順位順で、itemタグのパラメータは状態を現す

 プログラム言語に読み替えると、こんな感じになる。

	if ( state_enabled == false ){
		color="#00ffffff";
	}
	else if ( state_pressed == true ){
		color="#80ff0000";
	}
	else if ( state_focused == true ){
		color="#8000ff00";
	}else{
		color="#800000ff";
	}

 なので、表記の順番には気をつけなくてはいけない。

 また、パラメータは複数つけることもできる。
 たとえば

	<item android:state_enabled="true"
		 android:state_pressed="true"
		 >
		<color android:color="#80ff0000" />
	</item>

 選択できる状態で、押された … 半透明・赤
 といった感じ。

by the way…

 色の指定には、他のxml から引用することもできる。

	<color android:color="@color/blue_t" />

 color.xml の中に記述されている、blue_t の値
 といった感じだね。
 仮設定や、色の名前でつけたい、色を統一したい、なんていうときに便利だね。

 色ではなく画像を指定したい、という場合は…
 すまないけど、他の方の解説を見てほしい。(^_^;

Posted in ボタン. Tags: , . ボタンの外観を変える はコメントを受け付けていません。 »

XMLなしで、ボタンの外観を変える

 ボタンの外観を変えるには、

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 のエフェクトをつけてみた。
 フォーカスが外れると、半透明で点滅。
 選択されると、横方向に揺れる。
 縦にボタンを連ねた状態で、カーソル・キーでフォーカスを連続移動させると、階段を登るみたいでちょっとおもしろい。

Posted in ボタン. Tags: , , , , . XMLなしで、ボタンの外観を変える はコメントを受け付けていません。 »

選択肢メニューを作ってみた

タイトル画面には、それぞれのモードへ行くためのボタンが必要だね。
フツウにボタンを配置してもいいんだけど、それだとタイトル画面専用になっちゃう。
別にかまわないんだけど、せっかくなんで、汎用選択肢メニューとして作ってみた。

仕 様

  • 選択肢ボタンは、選択肢専用 ViewGroup に属する。
  • ボタン生成と共に、それぞれへユニークなIDがふられる。
  • ボタンを押されると、それぞれのIDをハンドラ へ送る。
  • ハンドラはすぐにViewGroup とボタンを非表示にする。


 で、メニュー(ハンドラ) が保持するIDを見れば、なにが選択されたかわかる。
 もしくは、メニューからリスナーへの通知にしてもいいね。

 …って、ListView そのものじゃん! Σ
 じゃ、ListView をベースに作ればいいか…と、ちょっとやってみたがうまくいかない。
 どうもXMLを使わないと面倒らしい…。

「AndroidでListView」
 XMLを使わない場合だと、自前でBaseAdapterクラスを拡張して、getView()の中でList内の要素を生成しないといけないらしい

 おそらく、BaseAdapter がボタンからの通知を統括してたりするんだろうね。
 当初の予定どおり、自前で作るとするか。
 まぁ、Open & Close のエフェクトとかを考えたら、その方が融通効きそうだし。

プロトタイプ

 で、こんな感じで作ってみた。

package com.migimaki.android;

import android.content.Context;
import android.widget.LinearLayout;
import android.view.Gravity;
import android.graphics.Color;
import android.widget.TextView;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;

import android.util.Log;


public class SelectMenu extends LinearLayout implements OnClickListener{

	private Context context = null;
	private onSelectListener _listener = null;		//リスナー

	//
	public int chois = 1;	// 選択回数カウンター。残り値分、選択可能。
	
	public boolean selected = false;	// 選択されたか?
	public int select_id = -1;	// 選択されたボタンID
	//--
	
	//==
	
	
	public SelectMenu ( Context c ){
		super( c );
		context = c;
		//--
		setOrientation(LinearLayout.VERTICAL);		// View配置設定 : 縦並び
	}


	// init & make Menu
	public void init( String menuMes, String butName[] ){
		chois = 1;
		selected = false;
		select_id = -1;
		//--
		setGravity(Gravity.CENTER);		// センター配置
		
		// Padding
	//	setPadding( 100, 100, 200, 200 );
	//	setPadding( -1, -1, -1, -1 );	// Padding 未設定の状態に初期化
		//--
		
		// メニュー・メッセージ
		addMes( menuMes );
		
		// ボタン作成
		for ( int i=0; i<butName.length; i++ ){
			addButton( i, butName[i] );
		}
		
		//	setVisibility( View.VISIBLE );
	}

	
	// make Text Mes
	public void addMes( String mesStr ){
		TextView mes = new TextView( context );
		mes.setText( mesStr );
		
		mes.setBackgroundColor(Color.argb( 128, 0, 0, 255 ));	// 背景色設定
		mes.setHeight(40);		// 高さ設定
		mes.setTextSize(20.0f);	// フォントサイズ
		mes.setGravity(Gravity.CENTER);		// センター表示
		
		addView(mes);
	}
	
	// make Button
	public void addButton( int id, String butName ){
		Button but = new Button( context );
		but.setId( id );
		but.setText( butName );

		//	mes.setBackgroundColor(Color.argb( 128, 0, 0, 255 ));	// 背景色設定
		mes.setHeight(40);		// 高さ設定
		mes.setTextSize(20.0f);	// フォントサイズ
		mes.setGravity(Gravity.CENTER);		// センター表示

		addView(but);
		but.setOnClickListener( this );	// onClick の設定
		
//	Log.d("TEST", "add but(" +id +")"+" : " +but.getId() );
	}
	
	// close : remove All Views
	public void close( ){
		removeAllViews();
	}

	// Event : click
	public void onClick( View but ){
		
		if ( chois > 0 ){
			selected = true;
			select_id = but.getId();
			
			if ( _listener != null ){
				_listener.onMenuSelected( select_id );	// イベントの通知( -> Activty )
			}
			chois--;
			//--
			
			// 選択されたボタン以外を非表示にする。
			if( chois <= 0 ){
				int child = getChildCount();
				for ( int i=1; i<child; i++ ){
					if( i != ( select_id +1 ) ){
						getChildAt( i ).setVisibility( View.INVISIBLE );
					}
				}
			}
			//--
		}
		//--
//	Log.d("TEST", "Who click? : " +but.getId() +"  select_id : " +select_id );
	}
	
	
	
	////////////////////////////////////////////////////////////////

	// イベントの通知先
	public interface onSelectListener{
		public void onMenuSelected( int select_id );
	}

	// リスナーの登録
	public void setOnSelectListener( onSelectListener listener ){
		_listener = listener;
	}
	////////////////////////////////////////////////////////////////

}

●SelectMenu のオブジェクトを生成後、表示したいViewGroup にadd すれば使用できる。

●表示位置とボタンの横幅は、setPadding で設定する。
 setPadding はLinearLayout に元々あるmethod なので、オブジェクトに対しても設定できるよ。

●init() で、メニュー・メッセージと各ボタン名の設定。
 method を実行すると、メッセージのTextViewとボタンを生成して、メニューを表示する。

●選択肢が決定されると、ボタンのIDがselect_id に保持される。
 また、リスナー登録しておくと、select_id を通知してくれる。

●close() で、メニューを非表示にする。
 すべてのメッセージとボタンをLinearLayout から削除する。
 オブジェクトは生きてるので、init() すれば新しいメニューが表示されるよ。

●ちょっとお遊びで、chois という変数をつけてみた。
 chois回数分だけ、ボタンを押せる。
 正解を選ぶとか、正しい順番を押させるとか、…そんな使い方。

課 題

・ボタンの外観
	今はデフォなので味気なし。
	カーソルと、押された時の反応も変えるべし。
・ボタン・サイズ
	文字サイズと共に、今は固定。
	文字列に合わせて変わる、指定設定できるようにする。
・Open & Close エフェクト
	パッと表示されるだけじゃ味気ない。
	なにかエフェクトをつけよう。

 それと、ソースの洗練もね。(w

Posted in メニュー, 選択肢. Tags: , , , . 選択肢メニューを作ってみた はコメントを受け付けていません。 »