2013-06-19 12 views
7

La sfida di associare un GestureDetector ad un ListPreference è 2 volte:Come allegare GestureDetector ad un ListPreference?

  1. Ottenere una maniglia per una ListPreference che è definito solo in un preferences.xml (cioè non un'istanza in codice Java).
  2. ListPreference non è una sottoclasse Visualizza o Attività.

È possibile associare un GestureDetector a un ListPreference?

Se sì, come si dovrebbe fare questo? Dove dovrei scrivere il codice per creare un'istanza di GestureDetector e implementare l'ascoltatore?

+2

Potrebbe dirmi qual è l'obiettivo principale di questa implementazione: qual è il risultato atteso e per che cosa verrà utilizzato "GestureDetector"? – g00dy

+0

@ g00dy Tutto ciò che voglio a questo punto è rilevare una pressione prolungata su qualsiasi elemento nell'elenco (e naturalmente restituire l'indice dell'elemento premuto a lungo). – scatmoi

risposta

4

A meno che non abbia risposto correttamente alla domanda, la risposta è probabilmente più semplice di quanto si possa pensare. Il codice sorgente per ListPreferece indica che è poco più di un wrapper attorno a uno AlertDialog che visualizza le sue varie opzioni in un ListView. Ora, AlertDialog consente effettivamente di ottenere un handle sul pacchetto ListView, che probabilmente è tutto ciò che serve.

In uno dei commenti hai indicato che, in questa fase, tutto ciò che ti interessa è il rilevamento di una pressione prolungata su qualsiasi elemento nell'elenco. Quindi piuttosto che rispondere allegando un GestureDetector, userò semplicemente un OnItemLongClickListener.

public class ListPreferenceActivity extends PreferenceActivity implements OnPreferenceClickListener { 

    private ListPreference mListPreference; 

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

     addPreferencesFromResource(R.xml.list_prefs); 

     mListPreference = (ListPreference) findPreference("pref_list"); 
     mListPreference.setOnPreferenceClickListener(this); 
    } 

    @Override 
    public boolean onPreferenceClick(Preference preference) { 
     AlertDialog dialog = (AlertDialog) mListPreference.getDialog(); 
     dialog.getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
      @Override public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) { 
       Toast.makeText(getApplicationContext(), "Long click on index " + position + ": " 
         + parent.getItemAtPosition(position).toString(), Toast.LENGTH_SHORT).show(); 
       return false; 
      } 
     }); 
     return false; 
    } 

} 

Il risultato (che il brindisi nel lungo click visualizzazione):

enter image description here

Con un riferimento al ListView, si potrebbe anche allegare un OnTouchListener, GestureDetector ecc Fino a voi per andare da qui.

+0

Sì, hai preso la domanda correttamente. :-) +1, accettando e premiando il bonus. Ora ... c'è qualche possibilità che il cast di '(AlertDialog)' non ** funzionerà in alcune versioni di Android/flavor/distro/customization? – scatmoi

+0

@scatmoi: Il cast dovrebbe essere sicuro per tutto ciò che si estende da 'DialogPreference', perché questo impone le sue classi di estensione per costruire il' Dialog' usando 'onPrepareDialogBuilder (AlertDialog.Builder builder)'. Ho avuto una rapida occhiata, e 'ListPreference' lo ha annullato per contratto almeno fino ad Android 1.5 (Cupcake). In effetti, 'ListPreference' non è cambiato nel corso degli anni ... Comunque, solo per la sanità mentale, non sarebbe male aggiungere un controllo' instanceof' prima del cast. :) –

0

Ho impostato un GestrueDetector su ScrollView utilizzando setOnTouchListener in precedenza e ho cercato un metodo simile per ListPreference, tuttavia dal momento che ListPreference non contiene un tale metodo, non credo che ciò sia possibile.

+2

Il punto cruciale della sfida è che 'ListPreference' ** è ** una vista, ma non è definito in un XML di layout e quindi non è possibile accedervi tramite [findViewById()] (http: // stackoverflow. com/q/17192066/1088,88 mille). O può? Sto iniziando a pensare che l'unico modo per aggirare questo problema è definire e utilizzare una sottoclasse di ListPreference, quindi nel suo 'onCreate()', [setOnTouchListener()] (http://developer.android.com/reference/android/ view/View.html # setOnTouchListener (android.view.View.OnTouchListener)). – scatmoi

+0

Potrebbe essere possibile eseguire un 'getView(). SetOnTouchListener()'. Non sono sicuro di come esattamente. – TronicZomB

1

Come suggerito da @TronicZomB, questo non è direttamente possibile.

È possibile aggirare questo creando la propria classe derivata ListPreference, ottenendo la sua visualizzazione nel inhered onBindDialogView().

Ricordare tuttavia che quest'ultimo è difficile perché onBindDialogView() viene chiamato solo se onCreateDialogView() non restituisce null e ciò può accadere solo se si crea la propria visualizzazione personalizzata per YourListPreference.

Il metodo consigliato per eseguire questa operazione è build a custom Preference.

Una volta fatto, si ha un riferimento alla vista di YourListPreference, che è obbligatoria per il collegamento di GestureDetector perché uno dei passaggi richiede setOnTouchListener() sulla vista.

+0

Il tuo metodo potrebbe funzionare ma è troppo macchinoso. L'approccio di @ MH. È più elegante (ma non so se è garantito che sia compatibile con le future versioni di Android). – scatmoi