2013-04-22 6 views
9

Sto sviluppando per api> 14 e ho implementato la funzionalità di trascinamento/rilascio su un GridView.Scorri il gridview mentre trascini l'oggetto (come ombra)

Tuttavia, mentre si trascina gli elementi nella parte superiore o inferiore dello schermo, lo GridView non scorre.

Mi piacerebbe farlo scorrere nella direzione in cui si trascina un elemento più veloce mentre ci si sposta verso il bordo e lento mentre si sposta l'oggetto indietro verso il centro verticale dello schermo.

Sicuramente questo tipo di funzionalità dovrebbe essere standard in qualsiasi drag-n-drop?

In ogni caso, qualcuno sa qual è il modo migliore per avvicinarsi a questo?

UPDATE: non può effettivamente trovare un solo esempio su internet che tenta anche di scorrere con un elemento di griglia trascinato figuriamoci risolvere il mio problema (mi manca qualcosa qui?).

Come si ottiene l'elemento trascinabile (che appare come un'ombra) per scorrere il gridview? Sto assegnando la resistenza come segue:

int gridChildPosition = position - mGridView.getFirstVisiblePosition();      
ViewFlipper gridItem = (ViewFlipper) mGridView.getChildAt(gridChildPosition); 

ClipData data = ClipData.newPlainText("", ""); 
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(gridItem); 

if (mGridView.startDrag(data, shadowBuilder, gridItem, 0)) { 

    int lastVisiblePosition = mGridView.getLastVisiblePosition() - mGridView.getFirstVisiblePosition(); 
    for (int i=0; i<=lastVisiblePosition; i++) { 
     if (i == gridChildPosition) { 
      continue; 
     } 
     mGridView.getChildAt(i).setOnDragListener(new GridItemDragListener(position)); 
     mGridView.getChildAt(i).setAlpha(0.4f); 
    } 
} 

Sopra codice crea l'ombra trascinabile e tutti gli altri elementi attualmente ottenere in grigio. Ma non sono sicuro di come ottenere l'ombra per scorrere la griglia.

+0

Controllare la risposta qui: http://stackoverflow.com/questions/12236035/android -how-to-auto-scroll-a-gridview-vertical-on-dragging-an-item-to-the-edg? rq = 1 – dennisdrew

+0

@dennisdrew Grazie, già visto questo. Nessuna spiegazione per il trascinamento della selezione. – HGPB

+0

Puoi controllare il tutorial di DragDrop http: //blahti.wordpress.it/2011/10/03/drag-drop-per-android-gridview/che può aiutarti. – GrIsHu

risposta

1

Penso che sia necessario utilizzare i metodi smoothScrollToPosition(int position) o smoothScrollByOffset(int offset) di GridView. Prendi due rettangoli nella parte superiore e inferiore dello schermo. Se l'evento tattile viene ricevuto su questi rettangoli durante il trascinamento, scorrere lo GridView. È possibile ottenere l'ultima posizione visibile in qualsiasi momento utilizzando il metodo getLastVisiblePosition().

7

La cosa interessante di Eventi di trascinamento è che è possibile ascoltarli nel genitore ViewGroup. Estendere GridView e ignorare onDragEvent per monitorare DragEvent.ACTION_DRAG_LOCATION. In là, ottieni le coordinate Y (event.getY()) del trascinamento. Assicurati di restituire true da ACTION_DRAG_STARTED oppure non riceverai l'evento in ACTION_DRAG_LOCATION.

Determina le tue "hit box", magari utilizzando la tecnica jaibatrik suggests o semplicemente utilizzando una percentuale dell'altezza misurata di GridView.

Probabilmente sarebbe più logico utilizzare smoothScrollByOffset(int offset), in questo modo è possibile implementare lo scorrimento a gradini/esponenziale. Significa che più a lungo l'utente mantiene l'elemento trascinato nella casella di riscontro, maggiore è l'offset.

Sembra un'idea interessante per una libreria/componente open source. ;-)

EDIT:

Ecco un esempio di come si possa fare ciò:

import android.app.Activity; 
import android.content.ClipData; 
import android.content.ClipData.Item; 
import android.content.Context; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.DragEvent; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemLongClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.GridView; 

public class GridDragActivity extends Activity implements OnItemLongClickListener { 

    private static final String TAG = "GridDragActivity"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     MyGridView gridView = new MyGridView(this); 
     gridView.setNumColumns(3); 
     gridView.setOnItemLongClickListener(this); 
     gridView.setAdapter(new ArrayAdapter<String>(
       this, 
       android.R.layout.simple_list_item_1, 
       COUNTRIES)); 

     setContentView(gridView); 
    } 

    @Override 
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, 
      long id) { 

     ClipData data = ClipData.newPlainText((String) view.getTag(), 
       String.valueOf(position)); 
     View.DragShadowBuilder shadow = new View.DragShadowBuilder(view); 
     view.startDrag(data, shadow, null, 0); 

     return true; 
    } 

    class MyGridView extends GridView { 

     private static final int THRESHHOLD = 200; 
     private static final int OFFSET = 10; 

     public MyGridView(Context context) { 
      super(context); 
     } 

     @Override 
     public boolean onDragEvent(DragEvent event) { 

      int height = getMeasuredHeight(); 

      switch (event.getAction()) { 
       case DragEvent.ACTION_DRAG_STARTED: 
        return true; 

       case DragEvent.ACTION_DRAG_LOCATION: 

        float y = event.getY(); 
        if (height - y < THRESHHOLD) { 
         smoothScrollByOffset(OFFSET); 
        } else if (height - y > height - THRESHHOLD) { 
         smoothScrollByOffset(-OFFSET); 
        } 

        return true; 

       case DragEvent.ACTION_DROP: 

        ClipData data = event.getClipData(); 
        Item item = data.getItemAt(0); 
        int start = Integer.valueOf((String) item.getText()); 
        int end = pointToPosition((int) event.getX(), (int) event.getY()); 

        Log.i(TAG, "DROP started at = " + start + ", ended at = " + end); 

        return true; 
      } 

      return super.onDragEvent(event); 
     } 
    } 

    static final String[] COUNTRIES = new String[] { 
     "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", 
     "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", 
     "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", 
     "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", 
     "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", 
     "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", 
     "British Indian Ocean Territory", 
     "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burundi", 
     "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde", 
     "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", 
     "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", 
     "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", 
     "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", 
     "Dominican Republic", 
     "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", 
     "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland", 
     "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia", 
     "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar", 
     "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", 
     "Guinea-Bissau", 
     "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", 
     "Hungary" 
    }; 
} 
+0

Avrò gioco con quello che suggerisci. – HGPB

+0

@Haraldo Si prega di consultare il codice di esempio nella risposta aggiornata. :-) –

+0

Grazie, avrò bisogno di un po 'di tempo per vedere come sono stato deviato. Tuttavia, onorerò ancora la taglia se questa soluzione è utile. – HGPB