◆AndroidのSpinnerのカスタマイズ:メモ
Androidのspinnerのカスタマイズ
Spinnerは3つの表示部品から成り立っています。
これらをカスタマイズします。この記事では実際のアプリ GooglePlay:しなやかメトロノーム のコードを例として説明します。
設定ファイルは複数あり、参照関連は次の様になっています。
java/MainActivity.java | +-- res/layout/my_spinner_item(ボタントップテキスト設定) | +-- res/layout/my_spinner_dropdown_item(ドロップダウンテキスト設定) res/layout/activity_main.xml-beat_and_sway.xml | +-- res/drawable/my_spinner.xml(セレクター) | +-- res/drawable/my_spinner_normal.xml(レイヤーリスト) | | | +-- res/drawable/my_spinner_base.xml(シェイプ) | | | +-- res/drawable/my_spinner_mark_dark.png(イメージ) | +-- res/drawable/my_spinner_pressed.xml(レイヤーリスト) | +-- res/drawable/my_spinner_base.xml(シェイプ) | +-- res/drawable/my_spinner_mark_bright.png(イメージ)
ボタン上のテキストitem
選択リストの要素はArrayAdapter<T>の構築子で指定されます。 このとき、その要素がボタン上に現れる時のスタイル定義を与えます。
通常MainActivityのOnCreate()で次の様に指定します。
for(int _n=0;_n<A_definition.spinners_items.length;++_n ){ ArrayAdapter<String> _adapter=new ArrayAdapter<String>( this ,android.R.layout.simple_spinner_item ,A_definition.spinners_items[_n] ); _adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item ); Spinner _spinner= (Spinner)findViewById(A_definition.spinner_ids[_n]); _spinner.setAdapter(_adapter); _spinner.setOnItemSelectedListener(this); }
ここで
android.R.layout.simple_spinner_item
が標準のテキストitemの定義です。
これを自分の定義したものに置き換えることにより、ボタントップのテキストのスタイル変更ができます。
res/layout下にファイルmy_spinner_itemを作成し、標準のitem定義の代わりに参照します。
<?xml version="1.0" encoding="UTF-8"?>
<TextView
xmlns:android ="http://schemas.android.com/apk/res/android"
style ="?android:attr/spinnerItemStyle"
android:singleLine ="true"
android:layout_width ="fill_parent"
android:layout_height="wrap_content"
android:textColor ="@color/panel_text"
android:gravity ="left"
android:textSize ="@dimen/panel_text_size"
android:ellipsize ="marquee"
/>
ボタンに乗せるテキスト(TextView)の定義になっています。基本となるスタイルとして"?android:attr/spinnerItemStyle"を指定しています。 ("?"の意味は未調査)。
ここではテキストの色とサイズを指定しています。
for(int _n=0;_n<A_definition.spinners_items.length;++_n ){ ArrayAdapter<String> _adapter=new ArrayAdapter<String>( this ,R.layout.my_spinner_item ,A_definition.spinners_items[_n] ); _adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item ); Spinner _spinner= (Spinner)findViewById(A_definition.spinner_ids[_n]); _spinner.setAdapter(_adapter); _spinner.setOnItemSelectedListener(this); }
ドロップダウンitem
スピナーを押した時に表示されるドロップダウンの定義は、ArrayAdapter<T> インスタンスにsetDropDownViewResource()で与えます。
通常MainActivityのOnCreate()で次の様に指定します。
for(int _n=0;_n<A_definition.spinners_items.length;++_n ){ ArrayAdapter<String> _adapter=new ArrayAdapter<String>( this ,android.R.layout.simple_spinner_item ,A_definition.spinners_items[_n] ); _adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item ); Spinner _spinner= (Spinner)findViewById(A_definition.spinner_ids[_n]); _spinner.setAdapter(_adapter); _spinner.setOnItemSelectedListener(this); }
ここで
android.R.layout.simple_spinner_dropdown_item
が標準のドロップダウンitemの定義です。
これを自分の定義したものに置き換えることにより、ドロップダウンitemのスタイル変更ができます。
res/layout下にファイルmy_spinner_dropdown_itemを作成し、標準のitem定義の代わりに参照します。
<TextView
xmlns:android ="http://schemas.android.com/apk/res/android"
style ="?android:attr/spinnerItemStyle"
android:singleLine ="true"
android:layout_width ="fill_parent"
android:layout_height ="wrap_content"
android:textColor ="@color/item_text"
android:gravity ="left"
android:textSize ="@dimen/item_text_size"
android:ellipsize ="marquee"
/>
リストに載せるテキスト(TextView)の定義になっています。基本的にはボタンに乗せるテキストitemの定義と同じ形です。 ここでは色とサイズが異なっているので別定義にしてあります。 同じでよければテキストitemで用いた定義が使えます。
MainActivityのOnCreate()のコードはこの定義を参照する形になります。
for(int _n=0;_n<A_definition.spinners_items.length;++_n ){ ArrayAdapter<String> _adapter=new ArrayAdapter<String>( this ,R.layout.my_spinner_item ,A_definition.spinners_items[_n] ); _adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item ); Spinner _spinner= (Spinner)findViewById(A_definition.spinner_ids[_n]); _spinner.setAdapter(_adapter); _spinner.setOnItemSelectedListener(this); }
ボタンの絵柄のdrawable
Spinnerボタンの絵柄はdrawableとして定義します。
drawableとしてはイメージファイルだけでなく、xml記述による
- セレクター(条件による表示切り替え)
- レイヤーリスト(drawableを組み合わせる)
- シェイプ(図形、グラディエーション)
このアプリでは
- 押された状態と押されていない状態のセレクター:my_spinner.xml
- 通常状態のレイヤーリスト:my_spinner_normal.xml
- 押下状態のレイヤーリスト:my_spinner_pressed.xml
- 土台となるシェイプ:my_spinner_base.xml
- 通常状態の3角マークイメージ:my_spinner_mark_dark.png
- 押下状態の3角マークイメージ:my_spinner_mark_bright.png
###レイアウトからの参照
Spinerの絵柄を置き換えるにはレイアウト指定xml上のSpinerで
android:background
として、定義したdrawable(ここではmy_spinner.xml)を参照します。
<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<!-- ============================ 縦向きレイアウト ========== -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation ="vertical"
android:background ="@color/panel_color"
android:layout_width ="match_parent"
android:layout_height="match_parent">
<include layout="@layout/beat_and_sway"/>
<!-- ================= METRONOME GRAPHICS ================= -->
<SurfaceView
android:id ="@+id/image"
android:layout_width ="fill_parent"
android:layout_height="0dp"
android:layout_weight="5"/>
<!-- ====================================================== -->
<include layout="@layout/general_settings"/>
<include layout="@layout/volume_of_beat"/>
<include layout="@layout/speed_and_volume"/>
</LinearLayout>
<!-- beat_and_sway.xml -->
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width ="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="@+id/spinner1"
android:background="@drawable/my_spinner"
android:layout_width ="0dp"
android:layout_weight="1"
android:layout_height="@dimen/spinner_height"/>
...
###セレクター
状態により表示するdrawbleを指定することができます。
状態には
・android:state_pressed
・android:state_focused
・android:state_selected
・android:state_active
・android:state_checkable
・android:state_checked
・android:state_enabled
・android:state_window_focused
があります。それぞれ"true"と"false"状態があります。
ここでは、android:state_pressedで切り替えています。
条件は複数並べることができます。and結合となります。
<!-- my_spinner.xml -->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 通常時 -->
<item
android:state_pressed="false"
android:drawable="@drawable/my_spinner_normal"
/>
<!-- 押下時 -->
<item
android:state_pressed="true"
android:drawable="@drawable/my_spinner_pressed"
/>
</selector>
###通常状態のレイヤーリスト
複数のdrawableを組み合わせることができます。
ここでは、図形とイメージを組み合わせています。
&let;!-- my_spinner_normal -->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/my_spinner_base" />
<item>
<bitmap android:src="@drawable/my_spinner_mark_dark"
android:gravity="right" />
</item>
/>
</layer-list>
###押下状態のレイヤーリスト
通常状態との違いは参照しているbitmapがmy_spinner_mark_bright.pngである点です。
<!-- my_spinner_pressed.xml -->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/my_spinner_base" />
<item>
<bitmap android:src="@drawable/my_spinner_mark_bright"
android:gravity="right" />
</item>
/>
</layer-list>
###土台となるシェイプ
丸、四角、線などの簡単な図形を置くことができます。
残念ながら3角は書けません。
本アプリでは四角にグラディエーションを付け、角を少し丸めています。
<!-- my_spinner_base.xml -->
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1px"
android:color="#555555"
/>
<gradient
android:startColor="#444444"
android:endColor="#111111"
android:angle="270"
/>
<corners
android:radius="5px"
/>
</shape>
###状態を表すイメージ2つ
通常状態の灰色の3角と押下状態の緑の3角のイメージを置いてあります。
my_spinner_mark_dark.png
my_spinner_mark_bright.png
困ったもんだ平板ブーム
GUIでは「表示部品」と「アクション部品」は一目で区別されるべきです。
境目のない馬鹿げたフラットデザインが「はやり」です。 しかし極めて視認性に劣るため、その内また立体デザイン、少なくとも境目が分かるデザインに流れは戻ると考えています。
iPadを使っていたのですが、フラットデザインになってから使わなくなりました。 何が何だか分からなくて。
この「しなやかメトロノーム」も当初Spinnerをフラットで境目のないデフォルトの
まま作ってみました。(冒頭の左の絵のようになる)
するとどうしても、三画が右の要素のもののように見えて、例えば「補助拍」を
変えようとして、直ぐ前の三画を押してしまうのです。すると、出てくるのは
拍子の選択。
もちろん画面全体のトーンを揃えたい、針の方を明るく目立たせたいなどの要因も あるのですが、一番はUI部品の境目が分かるようにしたかったのです。
最近のiOSになると、境目どころかボタンとラベルの区別もつかない。
| 固定リンク

