web-dev-qa-db-fra.com

L'utilisation de l'attribut onClick dans XML XML de la mise en page provoque une exception NoSuchMethodException dans les boîtes de dialogue Android

J'ai créé une boîte de dialogue personnalisée et une mise en page 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>

Dans la classe de dialogue, j'ai implémenté la méthode "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");
 }

}

Lorsque j'appuie sur le bouton, une exception «dialogueClicked» apparaît. La définition du gestionnaire onClick dans layout xml convient parfaitement aux activités, mais pas aux dialogues. Des idées? Qu'est-ce que je fais mal?

16
Impression

Définissez la méthode (dialogClicked) dans Activity. Et modifiez TestDialog comme le code suivant:

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

Je pense que ça marche :)

25
Jett Hsieh

Je pense que le problème est celui de la portée. Je ne sais pas comment vous avez réglé ce problème en XML, mais la méthode dialogueClicked de votre modèle XML ne sait pas où trouver la méthode que vous avez définie dans la classe de dialogue. 

L’approche standard que j’ai vue pour relier des boutons dans des dispositions personnalisées est la suivante.

  1. implémenter la classe OnClickListener
  2. Lier les boutons click event à la classe de dialogue
  3. Désactivez les boutons du bouton onClick en fonction de l'id. Vous devez ajouter un identifiant à votre bouton.

.

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

}

J'espère que cela pourra aider. Serait toujours intéressé de savoir s'il existe une solution pour utiliser xml onClick pour se lier à la méthode. Peut-être un argument supplémentaire dans le setContentView? quelque chose r'other.

6
Emile

J'ai trouvé le code suivant dans la source View.Java:

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

-> La vue utilise son contexte pour résoudre la méthode du gestionnaire onclick.

Noew le code suivant de la source Dialog.Java:

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

Dans le constructeur de la boîte de dialogue, une instance de ContextThemeWrapper est créée et définie en tant que contexte. Cette instance n'est ni la classe de dialogue personnalisée, ni l'activité d'appel, qui peut être le lieu d'implémentation de la méthode de gestionnaire. Par conséquent, les vues ne peuvent pas trouver la méthode du gestionnaire onclick.

Mais je dois utiliser l'attribut XML onclick. Des solutions de contournement disponibles?

2
Impression

Android:onClick="method" est assez cool, mais cela ne fonctionne pas sur Android 1.5, donc je l'évite depuis un certain temps.

Une solution de contournement facile:

Faites de votre Dialog une Activity et utilisez Android:theme="@Android:style/Theme.Dialog" en vous AndroidManifest.

1
Macarse

Les dialogues ont besoin de la signature 

dialogClicked(DialogInterface dialog, int id) { ... }
1
David Hedlund

Suite au message de Jett Hsieh, j'ai implémenté mes dialogues de manière légèrement différente en utilisant showDialog et licencierDialog, mais les principes de base pour obtenir le système Android: onClick fonctionne sont les mêmes.

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

Et le fichier de mise en page:

<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>
1
Kennifer

system recherche la méthode dans laquelle la mise en page a été gonflée ou dans la classe d'activité à laquelle le xml a été défini comme contenu.

0
noob

Essayez de définir cette méthode (dialogClicked) dans l'activité et non dans la boîte de dialogue.

Il peut utiliser la réflexion. Ainsi, si vous utilisez différentes activités, écrivez cette méthode dans chaque activité pour indiquer que

0
Pedro Loureiro

Une boîte de dialogue est toujours créée et affichée dans le cadre d’une activité. Selon les références Android:

Si vous décidez de créer une boîte de dialogue en dehors de la méthode onCreateDialog (), 
 Ne sera pas associée à une activité. Vous pouvez cependant 
 L'attacher à une activité avec setOwnerActivity (Activity).

En outre, transmettez-vous l'objet renvoyé par getApplicationContext (); au constructeur de TestDialog?

0
Raunak