J'ai donc une activité avec 2 widgets ListView
, lorsque vous sélectionnez une valeur dans le premier, le second est rempli avec les valeurs liées à la sélection dans la première ListView
. Ce mécanisme fonctionne sans problème, mais je souhaite maintenant que les choix des utilisateurs restent en surbrillance. J'ai lu une bonne quantité de questions liées à ce sujet et il semble qu'il existe une myriade de moyens pour y parvenir mais après avoir essayé environ 4-5 d'entre eux, je ne peux toujours pas le faire fonctionner.
Je travaille sur la seconde ListView
en utilisant l'attribut XML Android:listSelector="#CCCCCC"
, mais cela semble avoir été nettoyé une fois qu'une OnItemClickListener
est introduite dans le mélange (comme celle que j'utilise sur ma première ListView
).
Jusqu'ici voici ce que j'ai:
Personnalisé OnItemClickListener
J'ai trouvé en parcourant diverses réponses concernant ce sujet (légèrement modifié afin de pouvoir charger mes informations la deuxième liste):
private class ItemHighlighterListener implements OnItemClickListener {
private View oldSelection = null;
public void clearSelection() {
if(oldSelection != null) {
oldSelection.setBackgroundColor(Android.R.color.transparent);
}
}
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
clearSelection();
oldSelection = view;
view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.list_selector));
loadClubs(mXMLPortalOptions.getRegion(pos).getId());
mClubList.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.list_item_white, mClubs));
}
}
Voici mon fichier list_selector.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_selected="true"><shape>
<solid Android:color="#CCCCCC" />
</shape></item>
<item Android:state_selected="false"><shape>
<solid Android:color="#FFFFFF" />
</shape></item>
</selector>
La méthode (OnItemClick) est appelée et exécutée, mais l'arrière-plan de ma ListItem
reste de la même couleur: /
Je ne peux pas croire que cette tâche simple s'est avérée si compliquée.
Si j'ai omis du code qui pourrait être utile ou si ma question manque de détails, n'hésitez pas à le préciser et je ferai de mon mieux pour m'expliquer.
Mettez une variable de position pour l'élément sélectionné. Changer la position dans la méthode onItemClicked()
. Vérifiez la position sélectionnée dans List Adapter dans getView()
et définissez l'arrière-plan de l'élément sélectionné.
public class TestAdapter extends BaseAdapter
{
private Context context;
private ArrayList<TestList> testList;
private int selectedIndex;
private int selectedColor = Color.parseColor("#1b1b1b");
public TestAdapter(Context ctx, ArrayList<TestList> testList)
{
this.context = ctx;
this.testList = testList;
selectedIndex = -1;
}
public void setSelectedIndex(int ind)
{
selectedIndex = ind;
notifyDataSetChanged();
}
@Override
public int getCount()
{
return testList.size();
}
@Override
public Object getItem(int position)
{
return testList.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
private class ViewHolder
{
TextView tv;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View vi = convertView;
ViewHolder holder;
if(convertView == null)
{
vi = LayoutInflater.from(context).inflate(R.layout.test_list_item, null);
holder = new ViewHolder();
holder.tv = (TextView) vi;
vi.setTag(holder);
}
else
{
holder = (ViewHolder) vi.getTag();
}
if(selectedIndex!= -1 && position == selectedIndex)
{
holder.tv.setBackgroundColor(Color.BLACK);
}
else
{
holder.tv.setBackgroundColor(selectedColor);
}
holder.tv.setText("" + (position + 1) + " " + testList.get(position).getTestText());
return vi;
}
}
Définissez maintenant la variable selectedIndex quand un élément de la liste a cliqué.
public class TestActivity extends Activity implements OnItemClickListener
{
// Implemented onItemClickListener
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.setSelectedIndex(position);
}
}
Pour développer la bonne solution de Shaiful, vous pourriez ne pas le forcer à travailler dans votre situation.
Si vous utilisez votre code dans public void onListItemClick(ListView l, View v, int index, long id)
, si vous utilisez des fragments et devez déclarer une interface au lieu d'implémenter OnListItemClickListener, ou tout ce qui entraîne votre IDE à générer des erreurs, vous devrez peut-être accéder à des variables et des méthodes statiquement.
public static int selectedPosition = 0;
ArrayAdapter<Your_obj> adapter = null;
@Override
public void onListItemClick(ListView l, View v, int index, long id) {
super.onListItemClick(l, v, index, id);
selectedPosition = index;
Your_adapter.setSelectedIndex(selectedPosition);
adapter.notifyDataSetChanged();
}
Et dans Your_adapter:
private static int selectedIndex;
//public Your_adapter...
public static void setSelectedIndex(int ind) {
selectedIndex = ind;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
WellHolder holder = null;
if (null == convertView) {
//set up your "holder"
}
if (position == selectedIndex) {
convertView.setBackgroundColor(convertView.getResources().getColor(R.color.cyan));
}
else {
convertView.setBackgroundColor(convertView.getResources().getColor(R.color.silver));
}
return convertView;
}
Parmi les autres différences, vous ne devez initialiser aucune variable avec la valeur "0" ou "-1", et notifyDataSetChanged () est appelé dans votre activité.
Encore une fois, merci pour votre solution @Shaiful. Cela m'a certainement aidé à gagner du temps en essayant de faire fonctionner ce qui est par défaut dans iOS pour Android, tout en évitant le sélecteur/élément/focus/pressé/etc.
J'ai fait face à un problème similaire. C'est ma solution:
Commencez par ajouter un sélecteur de liste personnalisé à votre affichage de liste:
<ListView
Android:id="@+id/list"
Android:layout_width="match_parent"
Android:layout_height="fill_parent"
Android:listSelector="@drawable/listselector" />
Dans listselector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_accelerated="false"
Android:drawable="@drawable/bg" />
</selector>
Et enfin un fichier bg.xml avec la couleur de votre surbrillance:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
<solid Android:color="#33b5e6"/>
</shape>
//create a list_itemselectorin drawable folder
//you will get the list item selected background color change once you select //the item
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<!-- Focused State -->
<item Android:state_focused="true"><shape>
<solid Android:color="#66FFFFFF" />
</shape></item>
<!-- Pressed State -->
<item Android:state_pressed="true"><shape>
<solid Android:color="@color/Black" />
</shape></item>
<!-- Default State -->
<item><shape>
<solid Android:color="@color/Black" />
</shape></item>
</selector>
//create a list in layout folder
<ListView
Android:id="@+id/mySlidingList"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:choiceMode="singleChoice"
Android:divider="@color/GrayHot"
Android:dividerHeight="1dip"
Android:listSelector="@drawable/list_itemselector"
Android:scrollbars="none" />
// Et voir la sortie.
Je pense que la solution la meilleure et la plus simple est la suivante. Vous n'avez pas besoin de définir un Android:listSelector
sur le ListView lui-même ou d'apporter des modifications à l'adaptateur. Vous n'avez pas même besoin d'appeler un _setSelection(position)
dans la OnItemClickListener
car il est traité automatiquement.
Définir sur votre ListView:
Android:choiceMode="singleChoice"
Définir l'arrière-plan de l'élément de liste lui-même:
Android:background="?android:attr/activatedBackgroundIndicator"
C'est tout.
De cette façon, vous obtiendrez un comportement système par défaut. C'est comme ça que ça se passe dans la disposition par défaut Android.R.layout.simple_list_item_activated_1
.
Je le cherchais il y a deux semaines et le résultat est que ce n'est pas possible avec un sélecteur pouvant être tiré . Pour plus d'informations, lisez cet article sur le blog des développeurs Android: Touch Mode
En résumé: l'élément est sélectionné uniquement lorsque votre doigt est à l'écran.
Une autre possibilité est d’enregistrer quel élément est sélectionné dans une var et Paint différent en utilisant votre adaptateur personnalisé, comme le dit Shaiful.
Pour résumer ce post et peut-être aider quelqu'un d'autre à l'avenir, je suggère la réponse :)
Premièrement, nous devons créer un fichier res/drawable/list_item_background.xml
avec le contenu suivant:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item
Android:state_activated="true"
Android:drawable="@color/list_item_activated" />
<item
Android:drawable="@color/list_item_default" />
</selector>
Spécifiez vos ressources disponibles, bien sûr. Et vous pouvez également ajouter d'autres éléments <item>
avec différents états, tels que state_pressed
, state_focused
etc.
Ensuite, nous devrions définir le paramètre background
sur notre élément de liste personnalisé ViewGroup
élément (f.i. res/layout/list_item_layout.xml
) comme ceci:
Android:background="@drawable/list_item_background"
L'étape suivante consiste à modifier notre classe Adapter
personnalisée. Voici le fragment de code suivant:
public class CustomAdapter extends BaseAdapter {
private List<Item> items;
private LayoutInflater itemInflater;
private int selectedIndex; // add this
public CustomAdapter(Context c, List<Item> items) {
this.items = items;
this.itemInflater = LayoutInflater.from(c);
selectedIndex = -1; // add this
}
/* add this */
public void setSelectedIndex(int index) {
selectedIndex = index;
notifyDataSetChanged();
}
/* other adapter's stuff */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = itemInflater.inflate(R.layout.list_item_layout, parent, false);
}
// add this
convertView.setActivated(selectedIndex != -1 && position == selectedIndex);
/* do some stuff */
return convertView;
}
}
Enfin, nous devrions appeler la méthode de l'adaptateur setSelectedIndex(position)
dans la méthode onItemClick(...)
de AdapterView.OnItemClickListener
.
public class YourActivity extends Activity
implements AdapterView.OnItemClickListener {
private CustomAdapter mCustomAdapter;
/* activity implementation */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mCustomAdapter.setSelectedIndex(position);
}
}
Maintenant, nous pouvons être satisfaits des éléments de liste appropriés soulignant :)
P.S. Si nous voulons activer le mode à choix multiples sur notre liste, nous allons simplement placer la chaîne suivante dans notre classe d'activité où l'occurrence listView
est conservée:
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Ainsi, nous aurons les éléments multiples appropriés en surbrillance.
- J'espère que ça aide n'importe qui :)
Il existe une solution simple, entièrement XML, qui a fonctionné pour moi . Premièrement, définissez XML-dessinable avec un code de sélecteur dans lequel l'état "normal" correspondra à l'état visuel "sélectionné non exprimé" d'un élément de la liste, et state_pressed = true État visuel "pressé" . Exemple de fichier "custom_item_selector.xml", ressemblant à la sélection bleue Holo:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_pressed="true">
<shape Android:shape="rectangle">
<solid
Android:color="#643292ff">
</solid>
<stroke
Android:width="1dp"
Android:color="#c83292ff">
</stroke>
</shape>
</item>
<item>
<shape Android:shape="rectangle">
<solid
Android:color="#323292ff">
</solid>
<stroke
Android:width="1dp"
Android:color="#783292ff">
</stroke>
</shape>
</item>
</selector>
(peut également définir l'état ciblé à cet endroit) . Deuxièmement, appliquez cet élément pouvant être dessiné au xml en tant que listSelector de ListView et définissez son choix en mode souhaité:
<ListView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:id="@+id/listView"
Android:choiceMode="singleChoice"
Android:listSelector="@drawable/custom_item_selector"/>
C'est tout. Il permet de définir différents états visuels pour les éléments "simplement sélectionnés" et "sélectionnés", en rendant par exemple les éléments plus clairs sur la presse.
Pour que les éléments de la liste (sélection multiple) restent en surbrillance, suivez les étapes ci-dessous (activé).
1. Définir l'arrière-plan pour afficher la disposition des éléments comme dessinable.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="40dp"
Android:background="@drawable/list_item_selector">
<ImageView
Android:id="@+id/icon"
Android:layout_width="22px"
Android:layout_height="22px"
Android:layout_marginLeft="4px"
Android:layout_marginRight="10px"
Android:layout_marginTop="4px"
Android:src="@mipmap/ic_launcher" >
</ImageView>
<TextView
Android:id="@+id/label"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@+id/label"
Android:textSize="20px" >
</TextView>
</LinearLayout>
2. sélecteur pouvant être dessiné
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_pressed="true" Android:drawable="@Android:color/holo_red_light" />
<item Android:state_activated="true" Android:drawable="@Android:color/holo_orange_dark" />
</selector>
3. Liste de vues en mode choix multiple
getListView (). setChoiceMode (ListView.CHOICE_MODE_MULTIPLE);
L'image ci-dessous montre, lorsque l'utilisateur a sélectionné plusieurs éléments de la liste.
Si vous pouvez utiliser un dessin pour afficher listItem Highlighted, utilisez le code suivant: -
listView.setSelector(R.drawable.bg_image);
Ça marche.