お使いのブラウザは、バージョンが古すぎます。

このサイトは、Internet Explore8・Internet Explore9には対応しておりません。
恐れ入りますが、お使いのブラウザをバージョンアップしていただきますよう宜しくお願いいたします。

【Android】親Viewの状態に合わせて子Viewを変化させる

こんにちわ、pencoです。
またまた日本語力のないタイトルで申し訳ないです。
 
今回は、親のViewがチェックされたら(選択状態ならば)、子のViewも変化(画像を変えたり、文字の色を変えたり)させてみたいと思います。

今回目指すものは…

 
事の発端としては、カスタムのListViewで、一行選択されたら行の色を変えるという所から始まりました。
 
こちらを参考にさせて頂いています。
Android DrawableState でリストアイテムの背景を変える ViewGroup を作る
 
目指す形はこんな感じです。
list01

リストのレイアウト

 
リスト一行に設定しているレイアウトファイルは以下の様になっています。
例ですので端折っていますが、説明上レイアウトの構成だけ見て頂ければ。。

<?xml version="1.0" encoding="utf-8"?>
<jp.co.nihonvtr.sample.CheckedRelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/list_item">

  <RelativeLayout
    android:id="@+id/iconLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#1c1b1b" >

      <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/noimage" />
  </RelativeLayout>

  <TextView
    android:id="@+id/titleText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_toRightOf="@id/iconLayout"
    android:text="@string/text_notitle"
    android:textColor="#ffffff" />

  <TextView
    android:id="@+id/timeStamp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_marginLeft="10dp"
    android:layout_toRightOf="@id/iconLayout"
    android:text="@string/text_default_date"
    android:textColor="#b0b0b0" />
</jp.co.nihonvtr.sample.CheckedRelativeLayout>

 
このままだと、CheckedRelativeLayout の背景色は変わりますが、文字色も画像も固定のままです。
 
これを行がクリックされたら、TextView の文字色を変更し、ImageView は違う画像に切り替わるようにしていきたいと思います。
 

切り替え用のselector作成

  
コードで行がクリックされるイベントを拾って、setTextColor()などで修正する方法もありますが、もっと勝手に切り替わって欲しいので、レイアウトのルートであるCheckedRelativeLayout のステータス checked を子Viewの TextView や ImageView に引き継ぎ、その値を利用して selector を作ることにしました。

ImageViewの切り替えselector

 
まずは、ImageView の画像を切り替える為の selector を作ります。

res/xml/list_tap.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 選択されたとき -->
  <item
    android:state_checked="true"
    android:drawable="@drawable/list_tap_on" />
   
<!-- 通常の状態 -->
  <item
    android:state_selected="false"
    android:state_pressed="false"
    android:state_enabled="true"
    android:drawable="@drawable/list_tap_off" />
</selector>

TextViewの切り替えselector

  
次に TextView の文字色を変更するための selector を作ります。

res/color/list_text_title.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 選択されたとき -->
  <item
    android:state_checked="true"
    android:color="#000000" />
   
<!-- 通常の状態 -->
  <item
    android:state_selected="false"
    android:state_pressed="false"
    android:state_enabled="true"
    android:color="#ffffff" />
   
  <item
    android:state_pressed="true"
    android:color="#ffffff" />
</selector>

 
それぞれ、android:state_checked=”true” の時に選択中の色や画像になるように設定します。TextView の場合、android:state_pressed=”true” の状態がないと、文字が消えてしまうことがあったため、リストが押された時の文字色を指定しています。
 

xmlをレイアウトに反映

  
最後に作成した xml をレイアウトに反映させます。

<?xml version="1.0" encoding="utf-8"?>
<jp.co.nihonvtr.sample.CheckedRelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/list_item">

  <RelativeLayout
    android:id="@+id/iconLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#1c1b1b"
    android:duplicateParentState="true" >

      <ImageView
        android:id="@+id/imageView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@xml/list_tap"
        android:duplicateParentState="true" />
  </RelativeLayout>

  <TextView
    android:id="@+id/titleText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_toRightOf="@id/iconLayout"
    android:text="@string/text_notitle"
    android:textColor="@color/list_text_title"
    android:duplicateParentState="true" />

  <TextView
    android:id="@+id/timeStamp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_marginLeft="10dp"
    android:layout_toRightOf="@id/iconLayout"
    android:text="@string/text_default_date"
    android:textColor="@color/list_text_timestamp"
    android:duplicateParentState="true" />
</jp.co.nihonvtr.sample.CheckedRelativeLayout>

 
ここで重要なのが android:duplicateParentState=”true” の部分です。
このプロパティは true を指定することで、親の状態を子が共有することが出来ます。つまり先に書いた、親View(CheckedRelativeLayout) のステータス checked を子View に引き継ぐ、ということになります。
 
これで、親の CheckedRelativeLayout が checked=”true” になった時に、子も checked=”true” となるため、作成した xml の設定が有効になります。
 
1つ注意したいのは ImageView です。
このビューの直接の親は id が iconLayout の RelativeLayout です。そのため、この RelativeLayout にも android:duplicateParentState=”true” を指定しなければ CheckedRelativeLayout の状態を取得することは出来ません。
 
これで、コードでレイアウトを修正する必要なく、ビューが切り替わるようになりました。
 
 
ではでは、本日はこの辺で。

コメントをどうぞ

メールアドレスは公開されません。* が付いている欄は必須項目です。


お気軽にお問い合わせください。

日本VTR実験室では、お仕事のご依頼、ブログ・コラムのご感想などを受け付けております。
アプリ開発・コンテンツ制作でお困りでしたら、お気軽にご相談ください。
ご連絡お待ちしております。

お問い合わせはこちらから

03-3541-1230

info@nvtrlab.jp

電話受付対応時間:平日AM9:30〜PM6:00