2010-11-22 5 views
16

ho creato una finestra personalizzata e un layout di xml:mediante l'attributo onClick nel layout xml provoca una NoSuchMethodException nelle finestre di dialogo Android

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <Button 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Tap Me" 
     android:onClick="dialogClicked" /> 
</LinearLayout> 

Nella classe finestra ho implementato il metodo "dialogClicked (Visualizza v)" :

public class TestDialog extends Dialog { 

public TestDialog(final Context context) 
{ 
    super(context); 
} 

@Override 
protected void onCreate(final Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.dialog); 
} 

public void dialogClicked(final View view) 
{ 
    System.out.println("clicked"); 
} 

} 

Quando si tocca il tasto ho un NoSuchMethodException 'dialogClicked'. L'impostazione del gestore onClick nel layout xml funziona bene per le attività, ma non nelle finestre di dialogo. Qualche idea? Cosa sto facendo di sbagliato?

+1

Hai provato a rimuovere il modificatore "finale" da dialogClicked (vista Vista finale) a dialogClicked (Visualizza vista)? – 100rabh

+0

http://stackoverflow.com/questions/12582695/android-dialog-nosuchmethodexception-error-when-using-xml-onclick/26263507#26263507 –

risposta

25

Definire il metodo (dialogClicked) in Activity. e modificare TestDialog come il seguente codice:

public class TestDialog extends Dialog { 
Context mContext; 
public TestDialog(final Context context) 
{ 

    super(context); 
    mContext=context; 
} 

@Override 
protected void onCreate(final Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    LinearLayout ll=(LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.dialog, null); 
    setContentView(ll); 
} 
} 

penso che funziona :)

+0

Sì, questo è il punto principale: definire il metodo (dialogClicked) in Activity, se si utilizza onClick. –

+0

Thx ... ora posso prendere l'evento almeno nell'attività e avere una voce per ulteriori ottimizzazioni per spostare il metodo del gestore nell'implementazione della finestra di dialogo. – Impression

+0

@Jett Hsieh ok bene, ma come scriverò il codice per l'annullamento del pulsante e la selezione dei pulsanti in modo che possa chiudere il dialogo sto ottenendo l'errore in questa tecnica – Erum

1

finestre di dialogo hanno bisogno della firma

dialogClicked(DialogInterface dialog, int id) { ... } 
+0

Puoi farmi un esempio più concreto, perché la tua risposta non funziona - in A proposito, ho capito :) Ho provato a usare questo metodo nell'attività di chiamata e nella finestra di dialogo. Ma ottieni ancora la finestra di dialogo NoSuchMethodExcepionClicked (Visualizza). – Impression

+0

Non voglio prendere il normale evento onClick di OnClickListener, vuoi usare la funzione android: onClick. – Impression

2

ho trovato il seguente codice nel sorgente View.java:

public void onClick(View v) { 
          if (mHandler == null) { 
           try { 
            mHandler = getContext().getClass().getMethod(handlerName, 
              View.class); 
    ... 

-> I punti di vista utilizza il suo contesto per risolvere il metodo del gestore onclick.

Noew il seguente codice sorgente di Dialog.java:

public Dialog(Context context, int theme) { 
    mContext = new ContextThemeWrapper(context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme); 
    ... 

Nel costruttore della finestra di un'istanza di ContextThemeWrapper viene creato e impostato come contesto. Questa istanza non è né la classe di dialogo personalizzata né l'attività di chiamata, che può essere il luogo in cui implementare il metodo del gestore. Pertanto, le viste non sono in grado di trovare il metodo del gestore onclick.

Ma devo usare l'attributo XML onclick. Sono disponibili soluzioni alternative?

+0

Poiché questa non è una risposta, preferirei spostare questo come ulteriore indagine sulla tua domanda. –

0

Provare a definire tale metodo (dialogClicked) nell'attività e non nella finestra di dialogo.

Potrebbe utilizzare la riflessione quindi se si utilizza diverse attività basta scrivere che il metodo in ogni attività che potrebbe mostrare che il dialogo

+0

Ho già provato prima di porre la mia domanda a StackOverflow - non funziona. Al momento penso che questo problema non possa essere risolto a causa del meccanismo di riflessione all'interno dell'implementazione della vista predefinita. – Impression

0

Una finestra di dialogo è sempre creato e visualizzato come parte di un'attività. Secondo riferimenti Android:

If you decide to create a dialog outside of the onCreateDialog() method, 
it will not be attached to an Activity. You can, however, 
attach it to an Activity with setOwnerActivity(Activity).

Inoltre, si passa l'oggetto restituito da getApplicationContext(); al costruttore di TestDialog?

+0

Non funziona (testato). Secondo il codice, ho postato una risposta, è possibile vedere che l'implementazione del costruttore di finestre di dialogo di Android crea una propria istanza privata del contesto (ContextThemeWrapper). La chiamata di riflessione, che viene utilizzata dall'evento onclick per determinare il metodo del gestore, è contro questo contesto interno creato. – Impression

6

Penso che il problema sia di portata. Non sono sicuro di come lo hai indirizzato in xml, ma in sostanza il metodo dialogkedClick nel tuo layout xml non sa dove trovare il metodo che hai definito nella classe di dialogo.

L'approccio standard che ho visto per associare i pulsanti nei layout personalizzati è il seguente.

  1. implementare la classe OnClickListener
  2. Bind i pulsanti evento Click per la classe finestra
  3. Passare i pulsanti nel pulsante onClick sulla base di id. Dovresti aggiungere un ID al tuo pulsante.

.

public class TestDialog extends Dialog implements android.view.View.OnClickListener 
{ 
    protected void onCreate(final Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.dialog); 
     ((Button)findViewById(R.id.dialog_btn_mybutton)).setOnClickListener(this); 
    } 



public void onClick(View view) 
{ 
    switch (view.getId()) 
    { 
     case R.id.dialog_btn_mybutton: 
      //do stuff 
      // dismiss(); 
      // cancel etc. 
     break; 
    } 
} 

}

Speranza che aiuta. Sarei comunque interessato a sapere se ci fosse una soluzione per usare xml onClick per legarsi al metodo. Forse un argomento aggiuntivo in setContentView? qualcosa d'altro

1

android:onClick="method" è abbastanza bello, ma non funziona su Android 1.5, quindi sto evitando per qualche tempo.

una soluzione semplice:

Fai la tua Dialog un Activity e utilizzare android:theme="@android:style/Theme.Dialog" in voi AndroidManifest.

1

seguito al post di Jett Hsieh, ho implementato le mie finestre di dialogo in modo leggermente diverso utilizzando showDialog e dismissDialog, ma i fondamenti della ottenere l'androide: il funzionamento di onClick è stato lo stesso, il mio codice di esempio è sotto per riferimento futuro.

public class ExampleActivity extends Activity { 
    static final int DIALOG_DISCLAIMER = 0; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     showDialog(DIALOG_DISCLAIMER); 
    } 

    protected Dialog onCreateDialog(int id) 
    { 
     Dialog dialog; 
     switch(id) 
     { 
      case DIALOG_DISCLAIMER: 
       dialog = new Dialog(this); 
       dialog.setContentView(R.layout.main_disclaimer); 

       LinearLayout ll = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.main_disclaimer, null); 
       dialog.setContentView(ll); 

       break; 
      default: 
       dialog = null; 
     }  
     return dialog; 
    } 

    public void onClick(View v) 
    { 
     switch(v.getId()) 
     { 
      case R.id.maindisclaimer_button_accept: 
       dismissDialog(DIALOG_DISCLAIMER); 
       break; 
     } 
    } 
} 

E il file di layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:id="@+id/linearLayout1" 
       android:padding="10dp" 
       android:orientation="vertical" 
       android:background="@drawable/roundedcorners"> 
    <Button 
      android:id="@+id/maindisclaimer_button_accept" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="center" 
      android:text="@string/string_accept" 
      android:onClick="onClick" > 
     </Button> 
</LinearLayout> 
0

sistema cerca il metodo nel quale il layout è stato gonfiato da, o nella classe di attività a cui l'XML è stato impostato come contenuti.

Problemi correlati