2013-02-10 7 views
7

Ho un AlertDialog con solo un po 'di testo, un NumberPicker, un OK e un Annulla.Tastiera di cattura 'Fatto' per NumberPicker

package org.dyndns.schep.example; 
import android.os.Bundler; 
import android.view.View; 
import android.widget.NumberPicker; 
import android.app.Activity; 
import android.app.AlertDialog; 
import android.app.Dialog; 
import android.app.DialogFragment; 
import android.content.DialogInterface; 

public class FooFragment extends DialogFragment { 
    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     mParent = (MainActivity) activity; 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
     builder.setPositiveButton(android.R.string.ok, 
       new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int id) { 
       mParent.setFoo(foo()); 
      } 
     }) 
     .setNegativeButton(android.R.string.cancel, null); 

     View view = getActivity().getLayoutInflater.inflate(
       R.layout.dialog_foo, null); 
     mPicker = (NumberPicker) view.findViewById(R.id.numberPicker1); 
     mPicker.setValue(mParent.getFoo()); 
     builder.setView(view); 
     return builder.create(); 
    } 

    public int foo() { 
     return mPicker.getValue(); 
    } 

    private MainActivity mParent; 
    private NumberPicker mPicker; 
} 

(Questa finestra di dialogo ancora non fare le cose che deve preservare lo stato in pausa e riprendere, lo so.)

vorrei l'azione "Fatto" sulla tastiera virtuale o altro IME per chiudere la finestra di dialogo come se fosse stato premuto "OK", poiché c'è solo un widget da modificare.

Sembra che il modo migliore per gestire un IME "Fatto" di solito è setOnEditorActionListener su un TextView. Ma non ho alcuna variabile TextView e NumberPicker non espone ovviamente alcun TextView o callback di editor simili. (Forse NumberPicker contiene un TextView con un ID costante potrei cercare usando findViewById?)

NumberPicker.setOnValueChangedListener venga attivato l'azione "Fatto", ma spara anche quando si tocca o sfogliando l'elenco dei numeri, che sicuramente non dovrebbe chiudere la finestra di dialogo.

In base alla domanda this, ho provato a verificare setOnKeyListener, ma quell'interfaccia non si attivava affatto quando si utilizzava la tastiera virtuale. Non è una sorpresa totale, dal momento che la documentazione di KeyEvent suggerisce che è pensata più per gli eventi hardware, e nelle recenti API la tastiera virtuale non le invierà affatto.

Come posso collegare l'IME "Fatto" all'azione "OK" della mia finestra di dialogo?

Edit: Dagli sguardi della sorgente, un layout NumberPicker contiene una EditText, ma la sua identificazione è id/numberpicker_input nella confezione com.android.internal. Usarlo non sarebbe facile, ed è ovviamente scoraggiato. Ma sembra che ci potrebbero essere solo modi di hacking per ottenere il comportamento che voglio.

+0

Hai provato un selettore di numeri personalizzato compatibile con le versioni precedenti di Android. Sono sicuro che avrai accesso al loro id 'EditText'. Puoi controllare questo: https://github.com/SimonVT/android-numberpicker – Naveen

risposta

8

Come posso collegare l'IME "Fatto" all'azione "OK" della mia finestra di dialogo?

Il problema è che non è possibile passare gli eventi della IME se non si dispone di un ascoltatore impostato sul widget TextView che attualmente funziona con l'IME. Un modo per fare ciò che vuoi è collegare la nostra logica al figlio di NumberPicker che funziona con l'IME (come hai già parlato nell'ultima parte della tua domanda). Per evitare di utilizzare determinati ID o altri trucchi del layout (che possono essere problematici) per ottenere una sospensione di tale widget, è possibile utilizzare una tattica avida, impostando l'ascoltatore su qualsiasi widget da NumberPicker che potrebbe attivare l'evento desiderato (TextViews o qualsiasi sottoclasse di TextView).Qualcosa di simile a questo:

private AlertDialog mCurrentDialog; 
    private List<TextView> mTargets = new ArrayList<TextView>(); 
    private OnEditorActionListener mListener = new OnEditorActionListener() { 

     @Override 
     public boolean onEditorAction(TextView v, int actionId, 
       KeyEvent event) { 
      if (actionId == EditorInfo.IME_ACTION_DONE) { 
       // if a child of NumberPicker triggers the DONE editor event 
       // get a reference to the positive button(which you use in your 
       // code) and click it 
       mCurrentDialog.getButton(Dialog.BUTTON_POSITIVE).performClick(); 
      } 
      return false; 
     } 
    }; 

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 
    // ... 
    mPicker = (NumberPicker) view.findViewById(R.id.numberPicker1); 
     mPicker.setValue(mParent.getFoo()); 
     // clear any previous targets 
     mTargets.clear(); 
     // find possible targets in the NumberPicker 
     findTextViews(mPicker); 
     // setup those possible targets with our own logic 
     setupEditorListener();   
     builder.setView(view); 
     // get a reference to the current showed dialog 
     mCurrentDialog = builder.create();   
     return mCurrentDialog; 
    } 

Dove i metodi sono:

private void findTextViews(ViewGroup parent) { 
     final int count = parent.getChildCount(); 
     for (int i = 0; i < count; i++) { 
      final View child = parent.getChildAt(i); 
      if (child instanceof ViewGroup) { 
       findTextViews((ViewGroup) child); 
      } else if (child instanceof TextView) { 
       mTargets.add((TextView) child); 
      } 
     } 
    } 

    private void setupEditorListener() { 
     final int count = mTargets.size(); 
     for (int i = 0; i < count; i++) { 
      final TextView target = mTargets.get(i); 
      target.setOnEditorActionListener(mListener); 
     } 
    } 

L'altra soluzione possibile (e ragionevole) (come Naveen già menzionato nel suo commento) è quello di utilizzare una delle porte della NumberPicker class (o modifica quello dell'SDK) là fuori e inserisci i tuoi id di widget (che renderanno un riferimento al widget un compito semplice). Questo sarebbe più facile da implementare ora ma scomodo da mantenere a lungo termine.

+0

Pensi che valga la pena di usare un elenco di TextViews piuttosto che interrompere il ciclo di ricerca quando ne viene trovato uno? – aschepler

+0

@aschepler Ne vale la pena (per sicurezza). Non sono sicuro che ciò sia consentito (dall'alleanza di Android) ma un produttore di dispositivi potrebbe fare il proprio widget 'NumberPicker' con uno o più' TextViews/EditTexts '(perché non un'intestazione ?, ad esempio) oltre al normale inserisci 'EditText'. Inoltre, avere questo elenco non riduce le prestazioni (che il metodo ricorsivo analizzerà una gerarchia di vista di piccole dimensioni) o il consumo di memoria (poiché i widget sono già nel layout, stai semplicemente memorizzando i riferimenti ad essi). – Luksprog

+0

Non è meglio creare 'NumberPicker 'personalizzati e fare lo stesso? Il codice sarà molto più pulito – Jin35

0

La mia ricerca e sperimentazione è risultata anche a mani vuote. Detto questo non vorrei incoraggiare questo tipo di comportamento in quanto non ha molto senso.

Se avete bisogno di un NumberPicker è perché volete che la funzionalità scorra fino al valore di cui avete bisogno, non inserendolo (anche se è possibile). Se vuoi inserire il valore userai un EditText e sarai in grado di implementare ciò di cui hai bisogno senza problemi.

In alternativa è necessario copiare l'implementazione di NumberPicker dall'origine e quindi modificarla in base alle proprie esigenze (fx aggiungendo opzioni ime).

Problemi correlati