J'ai une ListActivity
qui implémente onListItemClick()
et appelle une fonction doSomething()
de la classe. Ce dernier contient l.setSelection(position)
où l
est l'objet ListView
.
Il existe maintenant un onClickListener()
à l'écoute d'un clic de bouton qui exécute certaines actions et qui appelle aussi doSomething()
.
Dans le premier cas, l'élément sélectionné est correctement positionné, mais dans le second, rien ne se passe.
Des indices sur ce comportement étrange et comment je pourrais le faire fonctionner?
vous avez peut-être besoin d'utiliser la fonction:
ListView.setItemChecked(int position, boolean checked);
utiliser requestFocusFromTouch()
avant d'appeler la méthode setSelection()
Je sais que c'est une vieille question mais je viens d'avoir un problème similaire que j'ai résolu de cette manière:
mListView.clearFocus();
mListView.post(new Runnable() {
@Override
public void run() {
mListView.setSelection(index);
}
});
Vous devrez peut-être insérer setSelection()
dans une post
ed Runnable
( reference ).
setSelection()
n'a pas nécessairement d'impact visuel. La barre de sélection ne s'affiche que si vous utilisez le D-pad/la boule de commande pour parcourir la liste. Si vous appuyez sur l'écran pour cliquer sur quelque chose, la barre de sélection apparaît brièvement et disparaît.
Par conséquent, setSelection()
n'aura un impact visuel que si l'activité n'est pas en mode tactile (c'est-à-dire, la dernière chose que l'utilisateur a faite a été d'utiliser le D-pad/le trackball).
Je ne suis pas sûr à 100% que cela explique votre phénomène au vu de la description que vous avez fournie, mais je me suis dit que ça en valait la peine ...
Si vous utilisez un adaptateur pour votre liste, ajoutez ce code à votre adaptateur:
public class MyAdapter extends
ArrayAdapter<MyClass> {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflator = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflator.inflate(R.layout.my_adapter, null);
} else {
rowView = (View) convertView;
}
//...
// set selected item
LinearLayout ActiveItem = (LinearLayout) rowView;
if (position == selectedItem)
{
ActiveItem
.setBackgroundResource(R.drawable.background_dark_blue);
// for focus on it
int top = (ActiveItem == null) ? 0 : ActiveItem.getTop();
((ListView) parent).setSelectionFromTop(position, top);
}
else
{
ActiveItem
.setBackgroundResource(R.drawable.border02);
}
}
private int selectedItem;
public void setSelectedItem(int position) {
selectedItem = position;
}
}
Dans votre activité:
myAdapter.setSelectedItem(1);
J'ai une très grande demande avec Webcontent. Lorsque j'ai utilisé le code dans onCreateView, Listview n'était même pas fini de charger .. .. Je l'ai mis dans onPostExecute de mon AsyncTask.
//Get last position in listview
if (listView != null && scrollPosition != 0) {
listView.clearFocus();
listView.requestFocusFromTouch();
listView.post(new Runnable() {
@Override
public void run() {
listView.setItemChecked(scrollPosition, true);
listView.setSelection(scrollPosition);
}
});
}
N'oubliez pas de définir l'élément enregistré sur Click;)
Pour moi appeler
listView.notifyDataSetChanged();
listView.requestFocusFromTouch();
et alors
listView.setSelection(position);
résolu le problème.
si vous faites cela dans un exécutable, cela fonctionne sans appeler requestFocusFromTouch (), mais l'ancienne position de ListView est affichée pendant un sekound.
Peut-être devriez-vous utiliser la méthode smoothScrollToPosition (int position) de ListView
Lorsqu’on utilise post to setSelection()
, la ListView
sera affichée en premier, puis fera défiler jusqu’à la position, grâce à " layout ", puis layout agira en réalité sur le setSelection()
, car setSelection()
appelle le setSelectionFromTop(int position, int y)
.
listView.setAdapter(listView.getAdapter());
listView.setSelection(123);
Essayez simplement ce code
listView.setAdapter(adapter);
listView.setSelection(position);
adapter.notifyDataSetChanged();
J'ai constaté que parfois setSelection ne fonctionnait pas car je définissais l'attribut "Android: height" de listView sur "wrap_content".
Et les fois où mon application ne fonctionne pas, c’est lorsque listView devient défilable de non-scrollable.
Par exemple, si mon application est "Application de navigateur de fichiers". Lorsque ma liste est inférieure à, disons 6, elle ne peut pas défiler. Maintenant, je reviens au répertoire parent qui contient 11 objets. Je souhaite définir la sélection sur une position et cela ne fonctionnera pas ici.
to\from | Scrollable | non-Scrollable
Scrollable | O | O (bien sûr)
non-scrollable | X | O (bien sûr)
Je ne veux pas utiliser post (Runnable), car il y aura un délai.
==================================
Réponse:
Vous pouvez essayer de définir "Android: height" sur "match_parent"
Mon dieu, ça passe trois jours.
Dans mon cas, smoothScrollToPosition (int position) a fonctionné. Pouvez-vous également me dire comment définir cette position de défilement au centre de la liste? Il est apparu au bas des éléments visibles.
Pour moi, cela a aidé à définirListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
ou ListView.CHOICE_MODE_MULTIPLE
puisListView.setSelection(position)
ou ListView.setItemChecked(position, true);
.__ fonctionne bien
Vous pouvez essayer 2 façons comme celles-ci:
Solution A:
mListView.post(new Runnable() {
@Override
public void run() {
if (null != mListView) {
mListView.clearFocus();
mListView.requestFocusFromTouch();
mListView.setSelection(0);
}
}
});
Dans certaines situations compliquées, cette solution apportera de nouveaux problèmes dans Android 8.x.
En outre, cela pourrait provoquer une inFocusChange () inattendue.
Solution B: Définir une vue personnalisée étend ListView. Remplacez la méthode handleDataChanged (). Puis setSelection (0). Dans CustomListView:
@Override
protected void handleDataChanged() {
super.handleDataChanged();
if (null != mHandleDataChangedListener){
mHandleDataChangedListener.onChanged();
}
}
HandleDataChangedListener mHandleDataChangedListener;
public void setHandleDataChangedListener(HandleDataChangedListener handleDataChangedListener) {
this.mHandleDataChangedListener = handleDataChangedListener;
}
public interface HandleDataChangedListener{
void onChanged();
}
En activité:
mListView.setHandleDataChangedListener(new CustomListView.HandleDataChangedListener() {
@Override
public void onChanged() {
mListView.setHandleDataChangedListener(null);
mListView.setSelection(0);
}
});
mAdapter.notifyDataSetChanged();
Ok, c'est fini.
J'ai trouvé une solution dans mon cas. Je n'utilise pas Runnable car ma classe étend ListFragment. Ce que je devais faire est de rendre mon index final; Final index = 5; MListView.setSelection (index);