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>
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é
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>
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>
@ 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>