【Android】親Viewの状態に合わせて子Viewを変化させる
こんにちわ、pencoです。
またまた日本語力のないタイトルで申し訳ないです。
今回は、親のViewがチェックされたら(選択状態ならば)、子のViewも変化(画像を変えたり、文字の色を変えたり)させてみたいと思います。
今回目指すものは…
事の発端としては、カスタムのListViewで、一行選択されたら行の色を変えるという所から始まりました。
こちらを参考にさせて頂いています。
Android DrawableState でリストアイテムの背景を変える ViewGroup を作る
目指す形はこんな感じです。
リストのレイアウト
リスト一行に設定しているレイアウトファイルは以下の様になっています。
例ですので端折っていますが、説明上レイアウトの構成だけ見て頂ければ。。
<?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 の状態を取得することは出来ません。
これで、コードでレイアウトを修正する必要なく、ビューが切り替わるようになりました。
ではでは、本日はこの辺で。
コメントをどうぞ