J'ai un GridView dans une application sur laquelle je travaille. J'aimerais pouvoir réorganiser les éléments dans GridView par glisser-déposer. J'ai trouvé beaucoup d'aide pour ListViews mais rien sur GridViews. Je souhaite obtenir un comportement similaire à celui de cette application de lancement http://www.youtube.com/watch?v=u5LISE8BU_E&t=5m30s . Des idées?
Si vous ne résolvez pas ce problème, je fournirai mon code. Mais cela fonctionne sur Android 3.0 et les versions ultérieures, car j'utilise Framework Android drag-n-drop
grid = (GridView) findViewById(R.id.grid);
grid.setAdapter(new DragGridAdapter(items, getActivity()));
....
grid.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
GridView parent = (GridView) v;
int x = (int) event.getX();
int y = (int) event.getY();
int position = parent.pointToPosition(x, y);
if (position > AdapterView.INVALID_POSITION) {
int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
View curr = parent.getChildAt(i);
curr.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
boolean result = true;
int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DRAG_LOCATION:
break;
case DragEvent.ACTION_DRAG_ENTERED:
v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_selected);
break;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_unselected);
break;
case DragEvent.ACTION_DROP:
if (event.getLocalState() == v) {
result = false;
} else {
View droped = (View) event.getLocalState();
GridItem dropItem = ((DragGridItemHolder) droped.getTag()).item;
GridView parent = (GridView) droped.getParent();
DragGridAdapter adapter = (DragGridAdapter) parent.getAdapter();
List<GridItem> items = adapter.getItems();
View target = v;
GridItem targetItem = ((DragGridItemHolder) target.getTag()).item;
int index = items.indexOf(targetItem);
items.remove(dropItem);
items.add(index, dropItem);
adapter.notifyDataSetChanged();
}
break;
case DragEvent.ACTION_DRAG_ENDED:
v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_unselected);
break;
default:
result = false;
break;
}
return result;
}
});
}
int relativePosition = position - parent.getFirstVisiblePosition();
View target = (View) parent.getChildAt(relativePosition);
DragGridItemHolder holder = (DragGridItemHolder) target.getTag();
GridItem currentItem = holder.item;
String text = currentItem.getFile().getAbsolutePath();
ClipData data = ClipData.newPlainText("DragData", text);
target.startDrag(data, new View.DragShadowBuilder(target), target, 0);
}
}
return false;
et DragGridAdapter
public class DragGridAdapter extends BaseAdapter{
private Context context;
private List<GridItem> items;
public DragGridAdapter(List<GridItem> items, Context context){
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
DragGridItemHolder holder;
if (convertView == null) {
holder = new DragGridItemHolder();
ImageView img = new ImageView(context);
holder.image = img;
convertView = img;
convertView.setTag(holder);
} else {
holder = (DragGridItemHolder) convertView.getTag();
}
holder.item = items.get(position);
holder.image.setImageBitmap(items.get(position).getBitmap());
return convertView;
}
public List<GridItem> getItems() {
return items;
}
J'espère que ça vous aide
Ma version pour l'affichage glisser de la grille https://github.com/askerov/DynamicGrid .
Il étend GridView original, supporte le glisser-déposer pour réorganiser les éléments, défilement automatique si glisser hors de l'écran. Il est complètement fonctionnel sur les api 3.0+, mais supporte 2.2 et 2.3 avec des limitations (pas d'animations).
Jetez un coup d'œil à DraggableGridView de thquinn, ceci a été développé pour Android 2.2 (API niveau 8) . J'espère que cela aidera quelqu'un :)
Il n’est pas facile de donner une réponse courte à ce sujet, car des centaines de lignes de code sont impliquées: vous devrez intercepter le début de l’action de glissement, généralement sur onLongClick, masquer la vue qui a initié l’action, afficher une superposition pouvant être déplacée pendant que l’utilisateur est toujours en action de toucher la terre et enfin faire les modifications à la retouche. La meilleure solution consiste à étendre le GridView standard dans Android.widget. Le résultat ressemble à ceci:
Voici une démo vidéo sur YouTube qui pourrait vous être utile: http://www.youtube.com/watch?v=m4yktX3SWSs&feature=youtu.be
J'ai également mis en place une réponse plus détaillée dans un article de mon blog. Vous trouverez peut-être cela utile car il est fourni avec un exemple complet de code source. Le lien est: http://www.pocketmagic.net/2013/11/complex-Android-gridview-with-drag-and-drop-functionality/
En utilisant le framework drag-n-drop, au lieu de cycler les enfants et de définir draglistener, j'utilise comme conteneur de disposition d'élément de grille un DragableLinearLayout qui étend LinearLayout et implémente la méthode onDragEvent (DragEvent).
Ainsi, vous pouvez remplir votre grille avec l'adaptateur comme d'habitude et l'essentiel du code de glisser-déposer se trouve sur onDragEvent de DragableLinearLayout.
public class DragableLinearLayout extends LinearLayout {
public DragableLinearLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public DragableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DragableLinearLayout(Context context) {
super(context);
}
@Override
public boolean onDragEvent(DragEvent event) {
//in wich grid item am I?
GridView parent = (GridView) getParent();
Object item = parent.getAdapter().getItem(
parent.getPositionForView(this));
//if you need the database id of your item...
Cursor cur = (Cursor) item;
long l_id = cur.getLong(cur.getColumnIndex("youritemid"));
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
return true;
case DragEvent.ACTION_DRAG_ENTERED:
setBackgroundColor(Color.GREEN);
invalidate();
return true;
case DragEvent.ACTION_DRAG_EXITED:
setBackgroundColor(Color.WHITE);
invalidate();
return false;
case DragEvent.ACTION_DROP:
ClipData cd = event.getClipData();
long l_id_start = Long.valueOf(cd.getItemAt(0).getText()
.toString());
//
Toast.makeText(getContext(), "DROP FROM " + l_id_start
+ " TO " + l_id, Toast.LENGTH_LONG);
//do your stuff
........
//the db requery will be on the onDragEvent.drop of the container
//see the listener
return false;
case DragEvent.ACTION_DRAG_ENDED:
setBackgroundColor(Color.WHITE);
invalidate();
//
return false;
}
return true;
}
}
private View.OnDragListener listenerOnDragEvent = new View.OnDragListener() {
public boolean onDrag(View v, DragEvent event) {
// Defines a variable to store the action type for the incoming
// event
final int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DROP:
// REQUERY
updateDbView();
return false;
// break;
}
return true;
}
};
J'ai récemment trouvé une solution sur laquelle son auteur a passé pas mal de temps ici http://blahti.wordpress.com/2012/03/03/improved-drag-drop-for-gridview/ Il y a 4 précédents articles de blog connexes expliquant ce qui se passe plus en détail ici.
Vous avez probablement besoin du projet PagedDragDropGrid: https://github.com/mrKlar/PagedDragDropGrid
Il fournit une ViewGroup
personnalisée (similaire à GridView) avec une fonction de réorganisation en douceur (exactement comme dans votre vidéo). Cela nécessitera probablement un peu de personnalisation, mais cela en vaut la peine.
J'espère que ça va aider.
Voici une bibliothèque library de h6ah4i qui tire parti des vues Recycler pour offrir une vue de grille par glisser-déposer avec possibilité de réorganisation.