カスタムセレクターを介したListViewアイテムの背景


98

リストセレクターを介して各リストビューアイテムにカスタム背景を適用することは可能ですか?

デフォルトのセレクター@android:color/transparentstate_focused="false"ケースを指定しますが、これを一部のカスタムドローアブルに変更しても、選択されていないアイテムには影響しません。Romain Guy はこの回答でこれが可能であると示唆ているようです。

私は現在、各ビューでカスタム背景を使用し、アイテムが選択/フォーカスされている場合にセレクターが表示されるように非表示にすることで同じ効果を達成していますが、これをすべて1か所で定義するとよりエレガントになります。

参考までに、これは私がこれを試すために使用しているセレクタです:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="false"
        android:drawable="@drawable/list_item_gradient" />

    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true" android:state_enabled="false"
        android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_disabled" />
    <item android:state_focused="true" android:state_enabled="false"
        android:drawable="@drawable/list_selector_background_disabled" />

    <item android:state_focused="true" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />
    <item android:state_focused="false" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />

    <item android:state_focused="true"
        android:drawable="@drawable/list_selector_background_focus" />

</selector>

そして、これは私がセレクターを設定している方法です:

<ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:listSelector="@drawable/list_selector_background" />    

助けてくれてありがとう!

回答:


128

私自身、これに不満を抱いて、ようやく解決しました。Romain Guyがほのめかしたように、"android:state_selected"使用しなければならない別の状態があります。リスト項目の背景には状態ドローアブルを使用し、リストには別の状態ドローアブルを使用しlistSelectorます。

list_row_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="@drawable/listitem_background"
    >
...
</LinearLayout>

listitem_background.xml:

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

ListViewを含むlayout.xml:

...
<ListView 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:listSelector="@drawable/listitem_selector"
   />
...

listitem_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/listitem_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/listitem_selected" />
</selector>

1
詳しい回答ありがとうございます。私の質問で述べたように、これはまさに私が現在行っていることでもあり、非常にうまく機能しています。
シルガピラ2010年

残念ながら、リストビューのカスタマイズにまだ問題があります。ここに私の特定の問題を投稿しました:stackoverflow.com/questions/5426385/… ; ご意見、ご感想をお寄せください。
LostNomad311 2011年

背景としてパディングを伴う9パッチのドローアブルを使用する場合は機能しません。私は私の答えを参照してください、私が思うに、究極の解決策を見つけた
のMichałK

これはポストICSで機能しますが、ジンジャーブレッドでは、リスト全体が押された、または選択されたドローアブルで色分けされます。
ガンナー2013

ICS以前のソリューションはありますか?
Lonli-Lokli 2014

78

dglmtnによるソリューションは、背景としてパディングを使用した9パッチのドローアブルがある場合は機能しません。奇妙なことが起こります、私はそれについて話したくありません、あなたがそのような問題を抱えているなら、あなたはそれらを知っています。

ここで、さまざまな状態と9パッチのドローアブルを備えたリストビューが必要な場合(すべてのドローアブルと色で動作すると思います)、次の2つのことを行う必要があります。

  1. リスト内のアイテムのセレクターを設定します。
  2. リストのデフォルトセレクターを削除します。

まず、row_selector.xmlを設定します。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_enabled="true" 
     android:state_pressed="true" android:drawable="@drawable/list_item_bg_pressed" />
    <item android:state_enabled="true"
     android:state_focused="true" android:drawable="@drawable/list_item_bg_focused" />
    <item android:state_enabled="true"
     android:state_selected="true" android:drawable="@drawable/list_item_bg_focused" />
    <item
     android:drawable="@drawable/list_item_bg_normal" />
</selector>

を忘れないでくださいandroid:state_selectedandroid:state_focusedリストと同じように機能しますが、リストアイテムに適用されます。

セレクターをアイテム(row.xml)に適用します。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/row_selector"
>
...
</RelativeLayout>

リストの透過的なセレクターを作成します。

<ListView
    android:id="@+id/android:list"
    ...
    android:listSelector="@android:color/transparent"
    />

これでうまくいくはずです。


1
+1、あなたの答えを以前に見なかった、私は自分でそれをしている同じ結果に出くわしました。しかし、9パッチのドローアブルについて言及してくれてありがとう。私はそれが将来の実装で役立つ可能性があると確信しています。この方法はよりクリーンで保守可能であるため、これが最良の答えになるはずです。
IsaacCisneros 2012

28
申し訳ありませんが、これは、これらのいまいましいUI APIが非常に無茶苦茶でなければならない理由を時々考えさせるようなものです。Androidにはまだやるべきことがたくさんあります。そのような基本的なものは、そのようなPITAであってはなりません。
Gubatron 2012

2
+1ありがとうございます、ありがとうございます、ありがとうございます。これらすべてのフープを飛び越えて、非常に基本的な何かを達成します。これらすべての状態は非常に混乱しています。
モリッツ

3
android:listSelector = "@ drawable / list_selector"の代わりに、android:listSelector = "@ android:color / transparent"と記述します。追加のlist_selector.xmlは必要ありません。
Sofi Software LLC

1
正解です。破壊しないリストセレクターは、独自のxmlセレクターの代わりに@android:color / transparentにすることができます。試してみただけです。機能しないのは@ nullです。これは、「リストセレクターなし」と表示され、リストセレクターがアイテムの後ろに描画されるため、何も描画されないため、驚きます。しかし、それは機能しません、デフォルトのセレクターはその当時です...
Zordid

17

リストビューの行に「背景色」を使用しないでください...

これはすべてのセレクターアクションをブロックします(私の問題でした!)

幸運を!


3
本当じゃない。単にバックグラウンドではなく、静的な色や描画可能としてセレクタを使用する
のMichałK

これは「背景色」を意味することを意図していた。あなたの言葉を完全に受け入れます。
cV2 2014

setBackgroundColor「色」で使用したセレクターが必要になったので、ここに来ました。ため息... setBackgroundまたはsetBackgroundDrawableセレクターを使用してAPIバージョンに応じて。
EpicPandaForce 2015年

5

Android開発者ブログの「なぜリストが黒くなるのか?Androidの最適化」の記事では、スクロール時にリストの背景が黒くなる理由について詳しく説明しています。簡単な答え:リストのcacheColorHintを透過(#00000000)に設定します。


1
単純な例ですが、非常にうまく機能します。Romain Guyに感謝します... <ListView ... android:cacheColorHint = "#00000000"> </ ListView>すべてです!
EricJOYÉ14年

Romain Guyに感謝しないでください。彼は問題の一部です。このようなOSには、それほど多くの「隠されたトリック」やその他のハッキングがあってはなりません。私はAndroidを愛していますが、他のSDK(さらに新しい/成熟度の低いSDK!)と比較した場合、それはドッグクレイプの大きな山です。
StackOverflowed

5

あなたが入れればそれで十分ですlist_row_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="@drawable/listitem_background">... </LinearLayout>

listitem_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/dark" android:state_pressed="true" />
    <item android:drawable="@color/dark" android:state_focused="true" />
    <item android:drawable="@android:color/white" />
</selector>

2
素晴らしい...最も簡単な例
Shihab Uddin 2015年

1
また、リストビューセレクターを透明にします
Sayka

4

の代わりに:

android:drawable="@color/transparent" 

書く

android:drawable="@android:color/transparent"

4

テーマを書くことができます:

<pre>

    android:name=".List10" android:theme="@style/Theme"

theme.xml

<style name="Theme" parent="android:Theme">
        <item name="android:listViewStyle">@style/MyListView</item>
</style>

styles.xml

 <style name="MyListView" parent="@android:style/Widget.ListView">
<item name="android:listSelector">@drawable/my_selector</item>

my_selectorはカスタムセレクターにしたいので、コードの記述方法がわかりません。


ヘルプに感謝しますが、これはセレクターを介してデフォルトのリストアイテムの背景を設定するのに直接役立ちません。
シルガピラ2010

2

セレクター自体を使用して目的の効果を実現する方法がわかりません。結局のところ、リスト全体に対してセレクターが1つあります。

ただし、選択の変更を制御して、必要なものを描画できます。ではこのサンプルプロジェクトで、私はセレクタを透明にし、選択した項目のバーを描きます。


実際、セレクタが1つだけであることは完全に理にかなっています。<item android:state_focused="false" android:drawable="@android:color/transparent" />デフォルトセレクターの句の存在に少し混乱している(または混乱していた)と思います。
シルガピラ2010

マーク、遊んで(ギルと同じ問題があります)私はあなたの解決策を試しました、それはトラックボールのみの部分的なものであり、タッチのみを使用してアイテムにタッチし、onItemClickedが呼び出されると、その種の何かが必要な場合は、何も呼ばれませんListView内の選択された位置と押された位置を追跡し、Item自体(カスタムビューにする)とListViewのdispatchDrawに必要なものを描画する必要があります。
codeScriber '19年

@codeScriber:「タッチのみを使用してアイテムにタッチし、onItemClickedが呼び出されると、nothingSeelectedが呼び出されます」-タッチは選択とは関係がないため、これは完全に正常な動作です。
CommonsWare、2011年

2

私は常に同じ方法を使用し、それはいつでもどこでも機能します:このようなセレクターを使用するだけです

<item android:state_activated="true"  android:color="@color/your_selected_color" />
<item android:state_pressed="true" android:color="@color/your_pressed_color" />
<item android:color="@color/your_normal_color"></item>

リストビューに設定します(これは機能させるために非常に重要です)属性

android:choiceMode="singleChoice"

textColorの場合、カラーフォルダー(重要、ドローアブルフォルダーではない!)に次のようなセレクターを配置します。

<item android:state_activated="true"  android:color="@color/your_selected_textColor" />
<item android:state_pressed="true" android:color="@color/your_pressed_textColor" />
<item android:color="@color/your_normal_textColor"></item>

これはサンプル行テンプレートです

<ImageView
    android:id="@+skinMenu/lblIcon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:src="@drawable/menu_catalog" />

<TextView
    android:id="@+skinMenu/lblTitle"
    style="@style/superlabelStyle"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginLeft="20dp"
    android:gravity="center_vertical"
    android:text="test menu testo"
    android:textColor="@color/menu_textcolor_selector"
    android:textSize="20dp"
    android:textStyle="bold" />

すべてが退屈な回避策なしで動作します。この助けを願っています


-3

FrostWireチームはこちらです。

すべてのセレクターのがらくたAPIが期待どおりに機能しません。このスレッドで提示されたすべてのソリューションをうまくいかなかった後、ListViewアイテムを拡張する瞬間の問題を解決しました。

  1. アイテムが状態を保持していることを確認します。これは、MenuItemのメンバー変数として実行しました(ブール値が選択されています)

  2. インフレートするときに、基になるアイテムが選択されているかどうかを確認します。選択されている場合は、必要なドローアブルリソースを背景として設定します(9patchなど)。アダプターがこれを認識し、何かが選択されたときにnotifyDataChanged()を呼び出すことを確認してください。

        @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        if (rowView == null) {
            LayoutInflater inflater = act.getLayoutInflater();
            rowView = inflater.inflate(R.layout.slidemenu_listitem, null);
            MenuItemHolder viewHolder = new MenuItemHolder();
            viewHolder.label = (TextView) rowView.findViewById(R.id.slidemenu_item_label);
            viewHolder.icon = (ImageView) rowView.findViewById(R.id.slidemenu_item_icon);
            rowView.setTag(viewHolder);
        }
    
        MenuItemHolder holder = (MenuItemHolder) rowView.getTag();
        String s = items[position].label;
        holder.label.setText(s);
        holder.icon.setImageDrawable(items[position].icon);
    
        //Here comes the magic
        rowView.setSelected(items[position].selected);
    
        rowView.setBackgroundResource((rowView.isSelected()) ? R.drawable.slidemenu_item_background_selected : R.drawable.slidemenu_item_background);
    
        return rowView;
    }

セレクターが実際に機能するのであれば、それは本当に素晴らしいことです。理論的には、これは素晴らしいエレガントなソリューションですが、壊れているようです。接吻。


この解決策を試したいのですが、詳しい説明や完全な解決策を教えていただけますか?ありがとう
Andrew Lam
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.