web-dev-qa-db-fra.com

L'élément ListView sélectionné ne fonctionne pas

Donc, j'ai un ListView et je veux changer la couleur de chaque élément de fond et le texte. Ce ListView est à l'intérieur d'un ListFragment. Mon code gonfle la présentation dans la onCreateView et gonfle la disposition de chaque élément dans la newView

Le Android:state_pressed="true" fonctionne bien, chaque fois que j'appuie sur un élément, l'arrière-plan change pour cette couleur. Mais lors de la sélection d'un élément, ni la couleur bg ni la couleur du texte ne changent, même si j'ai défini un élément avec Android:state_selected="true" dans le sélecteur.

Edit: J'utilise le SDK de niveau 11 (Android 3.0) et un Motorola Xoom.

La mise en page fragment de liste:

<?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="fill_parent"
    Android:orientation="vertical">
    <ListView
        Android:id="@Android:id/list"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"/>
</LinearLayout>

La disposition des éléments de la liste:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:orientation="vertical"
    Android:padding="25dp"
    Android:background="@drawable/list_item_bg_selector">
    <TextView Android:id="@+id/form_title"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:textSize="@dimen/text_size_xlarge"
        Android:textStyle="bold"
        Android:textColor="@drawable/list_item_text_selector" />
    <TextView Android:id="@+id/form_subtitle"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:textSize="@dimen/text_size_medium"
        Android:textStyle="normal"
        Android:layout_marginTop="5dp"
        Android:textColor="@drawable/list_item_text_selector" />
</LinearLayout>

Le sélecteur de fond:

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

Le sélecteur de texte:

<?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/white" />
    <item 
        Android:drawable="@color/list_text_blue" />
</selector>
21
aromero

La réponse consiste à utiliser l'état Android:state_activated="true" au lieu de l'état "sélectionné". Plus sur ceci ici: ListFragment Item Background sélectionné

46
aromero

La meilleure solution avec la prise en charge de tous les niveaux d'API consiste à implémenter la fonctionnalité Checkable pour l'élément de liste View, ce qui signifie que la vue de dessus de la présentation de votre élément de liste doit implémenter l'interface Checkable (dans mon cas, il s'agissait de TextView, mais la même chose peut s'appliquer à ViewGroup. classes comme LinearLayout). Lorsque vous cliquez sur un élément de la liste, la méthode ListView call setChecked et nous y modifions l'état de View pour utiliser le sélecteur Android:state_checked="true". Avec l'affichage de la liste Android:choiceMode="singleChoice", il ne sélectionnera qu'un seul élément. 

L'astuce consiste à remplacer la méthode onCreateDrawableState et à définir ici l'état coché pour drawables. Voir l'exemple de SelectableTextView ci-dessous. Une fois que setChecked est appelé, l’état coché est enregistré et appelé refreshDrawableState

Exemple de SelectableTextView:

package com.example.widget.SelectableTextView;

import Android.annotation.TargetApi;
import Android.content.Context;
import Android.os.Build;
import Android.util.AttributeSet;
import Android.widget.Checkable;
import Android.widget.TextView;

public class SelectableTextView extends TextView implements Checkable {
    private static final int[] CHECKED_STATE_SET = {
                    Android.R.attr.state_checked
    };

    private boolean mChecked;

    public SelectableTextView(Context context) {
        super(context);
    }

    public SelectableTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.Lollipop)
    public SelectableTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mChecked = checked;
            refreshDrawableState();
        }
    }

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void toggle() {
        setSelected(!mChecked);
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        }
        return drawableState;
    }
}

Exemple de structure selectable_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<com.example.widget.SelectableTextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
          xmlns:tools="http://schemas.Android.com/tools"
          Android:id="@Android:id/text1"
          Android:layout_width="match_parent"
          Android:layout_height="match_parent"
          Android:textColor="@color/list_item_selector_foreground"
          Android:background="@drawable/list_item_selector_background"
          tools:text="Item 1"/>

Exemple de list_item_selector_foreground.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <!-- checked -->
    <item Android:color="@color/list_item_text_active" Android:state_checked="true"/>

    <item Android:color="@color/list_item_text"/>
</selector>

Exemple de list_item_selector_background.xml:

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

    <item Android:drawable="@color/list_item_background"/>
</selector>
2
Arcao

N'oubliez pas de définir clickable="true" pour la mise en page. Cela a résolu mon problème.

Elément de liste:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:background="@drawable/list_item_bg_selector"
        Android:clickable="true" >

        <TextView
            Android:id="@+id/tvNewsPreviewTitle"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:maxLines="3"
            Android:ellipsize="end"
            Android:textSize="@dimen/news_preview_title_textsize"
            Android:textStyle="bold" />
    </RelativeLayout>

Sélecteur de fond:

 <selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <item Android:state_pressed="true" >
            <shape Android:shape="rectangle">
                <stroke Android:width="1dp" Android:color="@color/black" />
                <gradient Android:startColor="@color/white" Android:endColor="@color/white" />
            </shape>
        </item>
        <item>
            <shape Android:shape="rectangle">
                <stroke Android:width="1dp" Android:color="@color/holo_gray_darker" />
                <gradient Android:startColor="@color/holo_gray_bright" Android:endColor="@color/holo_gray_bright" />
            </shape>
        </item>
    </selector>
1
Yunus Emre INCE

@ Andrew S: Outre l'utilisation de l'état activé dans le sélecteur, l'état activé doit être défini sur false pour le cas par défaut, comme indiqué dans le code de sélecteur ci-dessous.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item Android:state_pressed="false"
        Android:state_activated="false"
        Android:color="@color/dark_text_blue"/>
  <item Android:state_pressed="true"
        Android:color="@color/red"/>
  <item Android:state_activated="true"
        Android:color="@color/red"/>
</selector>
0
user2089800