2010-11-22 11 views
16

He creado un diálogo personalizado y un diseño xml:atributo onClick en xml diseño provoca un NoSuchMethodException en los diálogos de 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> 

En la clase de diálogo He aplicado el método "dialogClicked (Ver 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"); 
} 

} 

Cuando toco el botón obtengo una NoSuchMethodException 'dialogClicked'. Establecer el controlador onClick en el diseño xml funciona bien para las actividades, pero no en los cuadros de diálogo. ¿Algunas ideas? ¿Qué estoy haciendo mal?

+1

¿Intentó eliminar el modificador "final" del cuadro de diálogo Habilitado (vista de vista final) en el cuadro de diálogo Habilitado (Ver vista)? – 100rabh

+0

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

Respuesta

25

Defina el método (diálogoClicked) en la Actividad. y modificar TestDialog como el siguiente código:

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); 
} 
} 

creo que funciona :)

+0

Sí, ese es el punto principal: defina el método (dialogClicked) en Activity, si usa onClick. –

+0

Thx ... ahora puedo ver el evento al menos en la actividad y tener una entrada para una mayor optimización para mover el método del controlador a la implementación del diálogo. – Impression

+0

@Jett Hsieh bien, pero ¿cómo voy a escribir el código para cancelar el botón y seleccionar el botón para que pueda descartar el diálogo que estoy recibiendo un error en esta técnica – Erum

1

Diálogos necesitan la firma

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

¿Puede darme un ejemplo más concreto, porque su respuesta no funciona? En el camino, lo he entendido :) He intentado utilizar este método en la actividad de llamada y el diálogo. Pero aún así obtener el diálogo NoSuchMethodExceptionClicked (Ver). – Impression

+0

No quiero atrapar el evento OnClick normal mediante OnClickListener, quiero usar la funcionalidad android: onClick. – Impression

2

que he encontrado el siguiente código en la fuente View.java:

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

-> Los puntos de vista utiliza su contexto para resolver el método onclick.

Noew el siguiente código de fuente Dialog.java:

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

En el constructor del diálogo de una instancia de ContextThemeWrapper se crea y se establece como contexto. Esta instancia no es la clase de diálogo personalizada, ni la actividad de llamada, que puede ser el lugar para implementar el método del controlador. Por lo tanto, las vistas no pueden encontrar el método del controlador onclick.

Pero tengo que utilizar el attribut XML de onclick. ¿Alguna solución alternativa disponible?

+0

Dado que esto no es una respuesta, prefiero mover esto como una investigación más a su pregunta. –

0

Trate de definir ese método (dialogClicked) en la actividad y no en el cuadro de diálogo.

Podría utilizar la reflexión por lo que si utiliza diferentes actividades acaba de escribir ese método en cada actividad que pudiera mostrar que el diálogo

+0

Ya lo intenté antes de hacer mi pregunta en stackoverflow: no funciona. En este momento, creo que este problema no se puede solucionar debido al mecanismo de reflexión dentro de la implementación de vista predeterminada. – Impression

0

Un diálogo es siempre crea y se muestra como parte de una actividad. Según Android Referencias:

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).

Además, ¿está pasando el objeto devuelto por getApplicationContext(); al constructor de TestDialog?

+0

No funciona (lo probé). De acuerdo con el código, he publicado una respuesta, se puede ver que la implementación del constructor de diálogo de Android crea una instancia propia y privada del contexto (ContextThemeWrapper). La llamada a la reflexión, que es utilizada por el evento onclick para determinar el método del manejador, está en contra de este contexto interno creado. – Impression

6

Creo que el problema es de alcance. No estoy seguro de cómo abordar esto en xml, pero esencialmente el método dialogueClicked en su diseño xml no sabe dónde encontrar el método que ha definido en la clase de diálogo.

El enfoque estándar que he visto para enlazar botones en diseños personalizados es el siguiente.

  1. implementar la clase OnClickListener
  2. Enlazar los botones de eventos de clic a la clase de diálogo
  3. Interruptor cabo los botones en el botón onClick basado en ID. Necesitarías agregar una identificación a tu botón.

.

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; 
    } 
} 

}

Espero que ayude. Todavía estaría interesado en saber si había una solución para usar xml onClick para enlazar al método. Tal vez un argumento adicional en el setContentView? algo entre ellos.

1

android:onClick="method" es genial, pero no funciona en Android 1.5, así que lo estoy evitando por un tiempo.

Una solución fácil:

Haga su Dialog un Activity y utilizar android:theme="@android:style/Theme.Dialog" en que AndroidManifest.

1

Siguiendo con el post de Jett Hsieh, he aplicado mis diálogos de forma ligeramente diferente utilizando showDialog y dismissDialog, pero los fundamentos de la obtener el android: el uso de onClick ha sido el mismo, mi código de ejemplo está a continuación para referencia futura.

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; 
     } 
    } 
} 

Y el archivo de diseño:

<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 busca el método en el que el diseño ha sido inflado de, o en la clase de actividad a la que el xml se establece como contenido.

Cuestiones relacionadas