2012年11月12日月曜日

【Android】ListViewタップ時に勝手に表示される背景色を殺す


アプリケーションを個人で一人で作ってる時は
俺が仕様だとそれで済むのかもしれません.
しかし,チームで作ってるとなるとそういうわけにもいかず,
デザインチームがこうしてくれと言われたら本当に無理な場合を除いてそう実装しなければいけません.

今日はそんな感じでListViewを使ったメニューを作っていくなかで,
背景色に困った場合をスキットで紹介しましょう.

開発者を 開
デザイナを デ
と表記します.

デ「今度作ってもらうアプリのメニュー画面は拡張性や項目の表示/非表示にソフトで対応できるようにリストで作ってもらいたいです」
開「ふんふん,ListViewを使ったメニューActivityね.把握」

~1時間後~
開「こんなかんじで」
デ「いいじゃないっすか」
デ「メニューは文字だけじゃなくてボタン画像も表示します」
デ「これが通常状態で」
デ「これが押された状態です」


~30分後~
開「こうなりますね」
デ「いいですね,でも青いの邪魔ですね.なんですこれ」
開「AndroidでListViewの項目押されたら出てくるやつですね」
開「機種によって青だったり黄だったり橙だったりいろいろです」
デ「消せます?」
開「できますよ」

~数分後~
開「リストの背景白く塗りつぶすとこんなかんじです」
デ「塗りつぶし…だと…」
デ「メニューの背景…できた…」
開「背景…単色じゃないの?なんでマンデルブロ…」

~数分後~
開「そりゃこうなりますよね」
デ「ですよね」
開「マンデルブロ?」
デ「マンデルブロ」

~数分後~
開「これじゃダメ?」
デ「限りなく惜しいんだけど青いの消せません?」

さて,開発者くんはデザイナくんの要望に答えようと頑張りましたが
どうしてもListViewの選択色が邪魔でしかたありません.
背景が単色じゃないので塗りつぶしも出来なくなりました.
最初はListViewをカスタムして何とかできないかと思ったみたいですが
よのなかそんなにあまくはなかったのです.

しかし,解決法はありました.
1.ListViewのアダプタを拡張
2.各項目をバインド(getView)するときに各項目にクリックリスナをセットする
3.クリックリスナでリストの指定番目をクリックする動作を行う
これだけ.
3についてはabsListViewクラスにperformItemClickという関数があります.

まずはActivityのレイアウト.
activity_main.xml

次に通常時/タッチ時に切り替わる文字色とボタン画像
color_tapped_text.xml

list_menu.xml

そしてListViewのそれぞれの項目となるレイアウト
view_list_item.xml

最後にこのActivity自身である
MainActivity.java

これでUI上でListViewをタップした時に
view_list_itemのFrameLayoutがフックというかインターセプトして
ListView自体にタップ情報を通知しないようになりました.
そのため,選択色が表示されなくなりました.
また,MainActivityAdapterのgetViewで設定しているクリックリスナ中で
performItemClickメソッドを使い,親ListViewの指定番目をクリックしています.
遠回りをわざわざしているように見えますが,UIでクリックしているわけではないので
ListViewの選択色は表示されません.

重要なことなのですが,タップをインターセプトしたのはFrameLayoutなので,
その下の画像と文字色をタップ時に変更させたい場合は
view_list_item.xmlでしている通り,ImageViewとTextViewに
android:duplicateParentState="true"
オプションを追加する必要があります.

これで
開「こうなりました」
と言えるようになりました.

1 件のコメント:

  1. バージョンによっては出来ないのかもしれませんが、
    ListViewのlistSelectorに透明色(#00xxxxxx)を設定したselectorを渡してあげると選択時のカラーを消せますよ。
    scrollingCacheにfalseを設定する事で
    androidのバージョン2系では表示がおかしくなる問題も解決出来る筈です。

    <ListView
    android:listSelector="@drawable/list_selector"
    android:scrollingCache="false" />
    (scrollingCache=false)

    -drawable/list_selector.xml-
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/clear" />
    </selector>

    -color.xml-
    <resources>
    <color name="clear">#00000000</color>
    </resources>

    返信削除