2016-11-27 7 views
2

Ich habe eine ListView, deren untergeordnete Ansichten Long-Click-Listener festgelegt haben. Wenn auf eine untergeordnete Ansicht geklickt wird, wird ein Dialogfeld angezeigt.Warum werden Ereignisse nicht berührt, wenn ein Dialog angezeigt wird?

Das Problem ist, dass, wenn der Benutzer den Finger gedrückt hält, nachdem der Dialog angezeigt wird, sie immer noch die ListView scrollen können, obwohl die ListView jetzt hinter dem Dialog ist. Durch das Debugging habe ich festgestellt, dass alle Berührungsereignisse (z. B. ACTION_MOVE und ACTION_UP) immer noch im ursprünglichen Fenster empfangen werden, bis der Benutzer schließlich den Finger hebt.

Hier ein kurzes reproduzierbares Beispiel:

package foo; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.Context; 
import android.os.Bundle; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.BaseAdapter; 
import android.widget.ListView; 
import android.widget.TextView; 

public class MainActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     ListView listView = new ListView(this); 
     listView.setAdapter(new FooAdapter()); 
     setContentView(listView); 
    } 
} 

class FooAdapter extends BaseAdapter { 
    @Override 
    public int getCount() { 
     return 100; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     final Context context = parent.getContext(); 

     TextView textView = new TextView(context); 
     textView.setText("Text"); 
     textView.setOnLongClickListener(new View.OnLongClickListener() { 
      @Override 
      public boolean onLongClick(View view) { 
       new AlertDialog.Builder(context) 
        .setMessage("Hi") 
        .show(); 
       return true; 
      } 
     }); 

     return textView; 
    } 

    @Override 
    public Object getItem(int position) { 
     return null; 
    } 

    @Override 
    public long getItemId(int position) { 
     return 0; 
    } 
} 

auf Android 6.0, 7.0 und 7.1, die Listview weiter scrollbaren zu sein, selbst nachdem der Dialog konzentrieren nimmt, wenn der Benutzer nie geht die Ansicht Kind läßt. Dies scheint nur beim ersten Aufruf des Dialogs zu passieren (bis die Aktivität erneut erstellt wird).

Ich habe zwei Fragen:

  1. Ist das ein Android-Bug? Was passiert, ist, dass die Berührungsgeste bis zum Abschluss ausgeführt wird (von ACTION_DOWN bis ACTION_UP), obwohl das Fenster den Fokus vor ACTION_UP verliert. Ich kann mir nicht vorstellen, dass dies jemals ein wünschenswertes Verhalten ist.

  2. Was ist die beste Lösung hier? Die folgende Lösung (ohne Berücksichtigung aller Berührungsereignisse, nachdem das Fenster den Fokus verliert) funktioniert, aber ich frage mich, ob es etwas besser:

    public class MainActivity extends Activity { 
        ... 
    
        @Override 
        public void dispatchTouchEvent(MotionEvent event) { 
         if (hasWindowFocus()) { 
          return super.dispatchTouchEvent(event); 
         } else { 
          return true; // suppress 
         } 
        } 
    } 
    

    Bitte beachte, dass ich nicht AbsListView.setOnItemLongClickListener verwenden können, die dieses Problem löst, indem sie alle Touch-Ereignisse zu ignorieren nach Ein langer Klick wurde erkannt, weil er zu unflexibel ist.

+0

Versuchen Aufruf 'setCancelable (false)' auf die 'Alertdialog .Builder' Beispiel. – Emmanuel

+0

@Emmanuel Das gleiche Problem bei der Verwendung von 'setCancelable (false)'. –

+0

Haben Sie die Lösung gefunden? –

Antwort

0

Ich bin nicht sicher, dass die Art und Weise Ereignisse auf Android arbeiten. In meinen Gedanken, wenn Sie auf den Bildschirm klicken, basierend auf Ihren Koordinaten, Android wird den Ansichtsprozess dieses Ereignis angeben. Da der Benutzer das Bildlaufereignis immer noch nicht freigibt, wird diese Ansicht immer noch verstanden, die dieses Ereignis verarbeitet.

Umgehen Sie einfach listView.setEnable (true), bevor Sie das Dialogfeld anzeigen.

Best Practice, Erstellen von benutzerdefinierten Dialog oder util Dialog mit den Hörern zu erstellen:

vor show -> disable Listview vor entlassen -> aktivieren Listview

Verwandte Themen