android - personalizada - dialogos personalizados
El uso del atributo onClick en el xml de diseño provoca una excepción NoSuchMethodException en los diálogos de Android (9)
Creo que el tema es de alcance. No estoy seguro de cómo abordó esto en xml, pero, en esencia, 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.
- implementar la clase OnClickListener
- Enlazar los botones, haga clic en evento a la clase de diálogo.
- Cambie 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 con el método. Tal vez un argumento adicional en el setContentView? algo r''otro
He creado un diálogo personalizado y un diseño xml:
<?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 implementado el método "dialogClicked (View 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''. Configurar el controlador onClick en el xml de diseño funciona bien para las actividades, pero no en los diálogos. ¿Algunas ideas? ¿Qué estoy haciendo mal?
Define el método (dialogClicked) en Activity. Y modifique 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 :)
El sistema busca el método en el que se ha inflado el diseño o en la clase de actividad a la que se configuró el xml como contenido.
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);
...
-> Las vistas usan su contexto para resolver el método del controlador onclick.
Recuerda el siguiente código de la 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, se crea una instancia de ContextThemeWrapper y se establece como contexto. Esta instancia no es ni 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 usar el atributo XML onclick. ¿Hay soluciones disponibles?
Intente definir ese método (dialogClicked) en la actividad y no en el diálogo.
Podría usar la reflexión, así que si usa diferentes actividades, simplemente escriba ese método en cada actividad que pueda mostrar ese diálogo.
Los diálogos necesitan la firma.
dialogClicked(DialogInterface dialog, int id) { ... }
Siguiendo con la publicación de Jett Hsieh, he implementado mis diálogos de forma ligeramente diferente usando showDialog y dismissDialog, pero los fundamentos de cómo funciona el android: onClick ha sido el mismo, mi código de ejemplo se encuentra a continuación para futuras referencias.
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>
Un diálogo siempre se crea y se muestra como parte de una actividad. Según las referencias de 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).
Además, ¿está pasando el objeto devuelto por getApplicationContext (); ¿Al constructor de TestDialog?
android:onClick="method"
es bastante bueno, pero no funciona en Android 1.5, así que lo evito por algún tiempo.
Una solución fácil:
Haz de tu Dialog
una Activity
y usa android:theme="@android:style/Theme.Dialog"
en tu AndroidManifest
.