« ◆星の近接効果と銀河の回転 | トップページ | ◆Xampp6.5.11、日本語とmySQL:メモ »

◆AndroidのSpinnerのカスタマイズ:メモ

忘れない内にメモ!

 Androidのspinnerのカスタマイズ

Spinnerは3つの表示部品から成り立っています。

  1. ボタン上のテキストitem
  2. ドロップダウンitem
  3. ボタンの絵柄のdrawable
これらをカスタマイズします。

この記事では実際のアプリ 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"を指定しています。 ("?"の意味は未調査)。
ここではテキストの色とサイズを指定しています。

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);
    }

スピナーを押した時に表示されるドロップダウンの定義は、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を組み合わせる)
  • シェイプ(図形、グラディエーション)
が置けます。

このアプリでは

でスピナー画像を組み上げています。

###レイアウトからの参照

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になると、境目どころかボタンとラベルの区別もつかない。

|

« ◆星の近接効果と銀河の回転 | トップページ | ◆Xampp6.5.11、日本語とmySQL:メモ »

トラックバック


この記事へのトラックバック一覧です: ◆AndroidのSpinnerのカスタマイズ:メモ:

« ◆星の近接効果と銀河の回転 | トップページ | ◆Xampp6.5.11、日本語とmySQL:メモ »