J'ai une liste d'enregistrements dans une listview que je veux que l'utilisateur puisse trier de nouveau en utilisant une méthode de glisser-déposer. J'ai vu cela implémenté dans d'autres applications, mais je n'ai pas trouvé de tutoriel pour cela. Ce doit être quelque chose dont les autres ont également besoin. Quelqu'un peut-il m'indiquer un code pour le faire?
J'y travaille depuis un certain temps maintenant. Difficile de bien faire les choses, et je ne prétends pas le faire, mais j'en suis satisfait jusqu'à présent. Mon code et plusieurs démos peuvent être trouvés à
Son utilisation est très similaire à TouchInterceptor (sur laquelle le code est basé), bien que des modifications importantes aient été apportées à la mise en œuvre.
DragSortListView permet un défilement régulier et prévisible lors du déplacement et de la réorganisation des éléments. Les shuffles d’éléments sont beaucoup plus compatibles avec la position de l’élément glissant/flottant. Les éléments de liste à hauteur hétérogène sont pris en charge. Le défilement par défilement est personnalisable (je montre un défilement rapide dans une longue liste - ce n’est pas une application qui vous vient à l’esprit). Les en-têtes/pieds de page sont respectés. etc.?? Regarde.
Ajoute cette réponse à l'intention de ceux qui Google sur ce sujet ..
Il y avait un épisode de DevBytes ( ListView Cell Dragging and Rearranging ) récemment qui explique comment faire cela
Vous pouvez le trouver ici aussi l'exemple de code est disponible ici .
En gros, ce code crée un dynamic listview
par l’extension de listview
qui prend en charge le déplacement et l’échange de cellules. Pour que vous puissiez utiliser le DynamicListView
au lieu de votre ListView
de base, vous avez implémenté une vue liste avec glisser-déposer.
Maintenant, c'est assez facile à implémenter pour RecyclerView
avec ItemTouchHelper . Remplacez juste la méthode onMove
de ItemTouchHelper.Callback
:
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mMovieAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
Vous pouvez trouver un bon didacticiel à ce sujet sur medium.com: glisser-glisser avec RecyclerView
La bibliothèque DragListView fait cela vraiment bien avec un support très agréable pour les animations personnalisées telles que les animations d'élévation. Il est également maintenu et mis à jour régulièrement.
Voici comment vous l'utilisez:
1: Ajoute la bibliothèque à classer en premier
dependencies {
compile 'com.github.woxthebox:draglistview:1.2.1'
}
2: Ajouter une liste à partir de xml
<com.woxthebox.draglistview.DragListView
Android:id="@+id/draglistview"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
3: Définir l'auditeur glisser
mDragListView.setDragListListener(new DragListView.DragListListener() {
@Override
public void onItemDragStarted(int position) {
}
@Override
public void onItemDragEnded(int fromPosition, int toPosition) {
}
});
4: Créer un adaptateur remplacé par DragItemAdapter
public class ItemAdapter extends DragItemAdapter<Pair<Long, String>, ItemAdapter.ViewHolder>
public ItemAdapter(ArrayList<Pair<Long, String>> list, int layoutId, int grabHandleId, boolean dragOnLongPress) {
super(dragOnLongPress);
mLayoutId = layoutId;
mGrabHandleId = grabHandleId;
setHasStableIds(true);
setItemList(list);
}
5: implémenter un viewholder qui s'étend de DragItemAdapter.ViewHolder
public class ViewHolder extends DragItemAdapter.ViewHolder {
public TextView mText;
public ViewHolder(final View itemView) {
super(itemView, mGrabHandleId);
mText = (TextView) itemView.findViewById(R.id.text);
}
@Override
public void onItemClicked(View view) {
}
@Override
public boolean onItemLongClicked(View view) {
return true;
}
}
Pour des informations plus détaillées, allez à https://github.com/woxblom/DragListView
J'ai trouvé DragSortListView a bien fonctionné, bien que le démarrer aurait pu être plus facile. Voici un bref tutoriel sur son utilisation dans Android Studio avec une liste en mémoire):
Ajoutez ceci au build.gradle
dépendances pour votre application:
compile 'asia.ivity.Android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
Créez une ressource pour l'ID de la poignée de glissement en créant ou en ajoutant à values/ids.xml
:
<resources>
... possibly other resources ...
<item type="id" name="drag_handle" />
</resources>
Créez une mise en page pour un élément de liste qui inclut votre image préférée de la poignée de glissement et affectez son ID à celui que vous avez créé à l'étape 2 (par exemple, drag_handle
).
Créez une mise en page DragSortListView, à peu près comme ceci:
<com.mobeta.Android.dslv.DragSortListView
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:dslv="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
dslv:drag_handle_id="@id/drag_handle"
dslv:float_background_color="@Android:color/background_light"/>
Définissez un dérivé ArrayAdapter
avec un remplacement getView
qui restitue la vue de votre élément de liste.
final ArrayAdapter<MyItem> itemAdapter = new ArrayAdapter<MyItem>(this, R.layout.my_item, R.id.my_item_name, items) { // The third parameter works around ugly Android legacy. http://stackoverflow.com/a/18529511/145173
@Override public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
MyItem item = getItem(position);
((TextView) view.findViewById(R.id.my_item_name)).setText(item.getName());
// ... Fill in other views ...
return view;
}
};
dragSortListView.setAdapter(itemAdapter);
Définissez un écouteur de dépôt qui réorganise les éléments au fur et à mesure qu'ils sont déposés.
dragSortListView.setDropListener(new DragSortListView.DropListener() {
@Override public void drop(int from, int to) {
MyItem movedItem = items.get(from);
items.remove(from);
if (from > to) --from;
items.add(to, movedItem);
itemAdapter.notifyDataSetChanged();
}
});
Je suis récemment tombé sur ce grand Gist qui donne une implémentation fonctionnelle d’un tri par glisser ListView
, sans aucune dépendance externe.
En gros, cela consiste à créer votre adaptateur personnalisé en étendant ArrayAdapter
en tant que classe interne à l'activité contenant votre ListView
. Sur cet adaptateur, on place ensuite un onTouchListener
dans votre liste d'éléments qui signaleront le début du glissement.
Dans ce Gist, ils définissent l'auditeur sur une partie spécifique de la présentation de l'élément de liste (le "descripteur" de l'élément), de sorte que l'utilisateur ne le déplace pas accidentellement en appuyant sur une partie quelconque de celui-ci. Personnellement, j’ai préféré utiliser un onLongClickListener
à la place, mais c’est à vous de décider. Voici un extrait de cette partie:
public class MyArrayAdapter extends ArrayAdapter<String> {
private ArrayList<String> mStrings = new ArrayList<String>();
private LayoutInflater mInflater;
private int mLayout;
//constructor, clear, remove, add, insert...
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = convertView;
//inflate, etc...
final String string = mStrings.get(position);
holder.title.setText(string);
// Here the listener is set specifically to the handle of the layout
holder.handle.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
startDrag(string);
return true;
}
return false;
}
});
// change color on dragging item and other things...
return view;
}
}
Cela implique également l'ajout d'un onTouchListener
au ListView
, qui vérifie si un élément est en train d'être déplacé, gère la permutation et l'invalidation et arrête l'état de glissement. Un extrait de cette partie:
mListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (!mSortable) { return false; }
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
// get positions
int position = mListView.pointToPosition((int) event.getX(),
(int) event.getY());
if (position < 0) {
break;
}
// check if it's time to swap
if (position != mPosition) {
mPosition = position;
mAdapter.remove(mDragString);
mAdapter.insert(mDragString, mPosition);
}
return true;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE: {
//stop drag state
stopDrag();
return true;
}
}
return false;
}
});
Enfin, voici à quoi ressemblent les méthodes stopDrag
et startDrag
, qui gèrent l'activation et la désactivation du processus de glisser:
public void startDrag(String string) {
mPosition = -1;
mSortable = true;
mDragString = string;
mAdapter.notifyDataSetChanged();
}
public void stopDrag() {
mPosition = -1;
mSortable = false;
mDragString = null;
mAdapter.notifyDataSetChanged();
}