Non sono sicuro che si tratti di un problema di dispositivo o di un problema con il mio codice, ma ho creato un elenco ordinabile trascinabile semplice utilizzando un layout relativo e visualizzazioni di immagine. Ho ragioni molto specifiche per farlo in questo modo e questa non è la mia domanda.Android/kindle drag drop congelamento occasionalmente
Il problema che sto avendo a volte bloccherà completamente la mia app. L'oggetto si bloccherà nello stato di trascinamento. Se alzo il dito, l'ombra (trascinando) l'oggetto è ancora sullo schermo e se tocco lo schermo si sposterà in quel punto. Questo andrà avanti per circa un minuto e poi avrò un errore dicendo che l'app non è reattiva con l'opzione di ucciderlo o aspettare. L'unica parte utile nel logcat è la seguente:
12-09 14:23:13.157: W/WindowManager(16415): Drag is in progress but there is no drag window handle.
Poi, quando i tempi di app fuori ottengo questo come un errore
12-09 14:59:09.782: E/ActivityManager(16415): ANR in com.appname.appname (com.appname.appname/.MainActivity)
12-09 14:59:09.782: E/ActivityManager(16415): Reason: keyDispatchingTimedOut
Ho cercato su google questo messaggio di errore e l'unica Info E 'stato qualcuno senza trascina l'ascoltatore e un'altra persona che dice che è il sensore tattile del dispositivo a non tenere il passo.
Idealmente, mi piacerebbe risolvere questo errore e impedire che accada in primo luogo. Sembra che succeda soprattutto se trascino velocemente, ma non posso chiedere ai miei utenti di non trascinarsi velocemente ... giusto?
In alternativa, c'è un modo per rilevare che il trascinamento ha bloccato l'app e interrotto il trascinamento. Come impostare un timer sull'ascoltatore touch e se non ci sono messaggi di tipo drag_location come un secondo o due interrompe il trascinamento? Le cose del timer che so come fare, ma non so come forzerei la resistenza a fermarsi mentre è congelata. Qualche idea?
Ecco il codice:
configurazione
//happens once when the app loads
RelativeLayout trackList = (RelativeLayout) findViewById(R.id.nsTrackList1);
trackList.setOnDragListener(new MyTrackDragListener(this));
//happens in a loop for each "track" (image view)
trackButton = new ImageView(this);
trackButton.setImageDrawable(nsPackages[trackId].banner[bannerSizeSelector]);
trackButton.setOnTouchListener(new MyTrackTouchListener());
sul touch
public class MyTrackTouchListener implements OnTouchListener {
boolean isDragging=false;
float prevX, prevY;
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getPointerCount() < 2 && !isDragging) return false;
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
isDragging=false;
prevX=0;
prevY=0;
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
if(isDragging) return true;
boolean wasFirst = (prevX == 0 || prevY == 0);
float theTotalDiff = Math.abs(prevX - motionEvent.getX()) + Math.abs(prevY - motionEvent.getY());
prevX=motionEvent.getX();
prevY=motionEvent.getY();
if(wasFirst) return true;
if(theTotalDiff <3) return true;
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
int thisViewId = view.getId();
//hide view
view.setVisibility(View.GONE);
isDragging=true;
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
isDragging=false;
return true;
}else {
Integer thisAction = motionEvent.getAction();
Log.d("looper","Motion action: "+thisAction.toString());
return false;
}
}
}
Al trascinamento
class MyTrackDragListener implements OnDragListener {
public static boolean isDragging=false;
private MainActivity parent;
public MyTrackDragListener(MainActivity myAct){
parent=myAct;
}
@Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
isDragging=true;
// do nothing
return true;
case DragEvent.ACTION_DROP:
View view = (View) event.getLocalState();
parent.doDropSort(view,(int) event.getY());
return true;
case DragEvent.ACTION_DRAG_ENDED:
if(isDragging && event.getResult()==false){
View view2 = (View) event.getLocalState();
parent.doDropSort(view2,(int) event.getY(),true);
return true;
}
isDragging=false;
break;
case DragEvent.ACTION_DRAG_LOCATION:
parent.doDragHover((int) event.getY());
return true;
default:
Log.d("looper","drag other... "+String.valueOf(event.getAction()));
}
return false;
}
}
Alcune cose che già provato
- Rimozione l'ascoltatore di trascinamento del tutto
- tornare sempre vero dal onDrag
- Riportare sempre falso dal onDrag
- In pratica ogni combinazione di rendimento vero/falso nella resistenza e toccare
- Rimuovere la parte 2 dita e Action_Move e attivare il trascinamento su Action_down invece
Stessi risultati. Drag and drop funziona perfettamente circa il 70% delle volte e poi improvvisamente fa il comportamento di congelamento descritto sopra. A volte è la prima volta che si trascina, dopo diversi anni. Ho notato un pattern coerente tranne possibilmente velocità di trascinamento. Sembra che in genere si verifichi quando sto trascinando velocemente, ma la direzione di trascinamento o il punto in cui trascino non sembra avere importanza.
Come un ex dipendente di Amazon Kindle e sviluppatore, mi piacerebbe vedere se si puoi ottenerlo in modo coerente con una piccola app di prova e quindi inviare una segnalazione di errore. –
@CarlAnderson Grazie, ho provato con i test manuali da alcuni giorni e non riesco a vedere alcun motivo. Hai qualche consiglio su come costruire un'app di test per questo tipo di comportamento? C'è un modo per simulare l'input touch/drag-drop? – Lenny
Nessuno di ciò che conosco e, sfortunatamente, se non riesci a riprodurlo in modo coerente, probabilmente non lo guarderanno. –