web-dev-qa-db-fra.com

Android: comment gérer le clic sur un bouton

Ayant une solide expérience dans le domaine non-Java et non-Android, j'apprends Android.

J'ai beaucoup de confusion avec différents domaines, l'un d'entre eux est la gestion des clics sur les boutons. Il y a au moins 4 façons de faire (!!!), elles sont brièvement listées ici

par souci de cohérence, je les énumérerai:

  1. Ayez un membre de la classe View.OnClickListener dans l'activité et assignez-le à une instance qui gérera la logique onClick dans la méthode d'activité onCreate.

  2. Créez 'onClickListener' dans la méthode d'activité 'onCreate' et affectez-le au bouton à l'aide de setOnClickListener 

  3. Implémentez 'onClickListener' dans l'activité elle-même et affectez-le en tant qu'écouteur pour le bouton. Dans le cas où l'activité comporte peu de boutons, il convient d'analyser l'identifiant du bouton pour exécuter le gestionnaire 'onClick' correspondant au bouton approprié.

  4. Avoir une méthode publique sur l'activité qui implémente la logique 'onClick' et l'affecter au bouton dans la déclaration XML de l'activité

Question 1:

Sont toutes ces méthodes, y at-il une autre option? (Je n'ai besoin d'aucun autre, juste curieux)

Pour moi, le moyen le plus intuitif serait le plus récent: il faut taper le moins de code possible et est le plus lisible (du moins pour moi).

Bien que, je ne vois pas cette approche largement utilisée. Quels sont les inconvénients pour l'utiliser?

Question 2:

Quels sont les avantages/inconvénients de chacune de ces méthodes? S'il vous plaît partager soit votre expérience ou un bon lien. 

Tous les commentaires sont les bienvenus!

P.S. J'ai essayé de Google et de trouver quelque chose pour ce sujet, mais les seules choses que j'ai trouvées sont la description "comment" faire cela, pas pourquoi c'est bon ou mauvais.

78
Budda

Question 1: Malheureusement, celui dans lequel vous dites le plus intuitif est le moins utilisé sous Android. Si je comprends bien, vous devez séparer votre interface utilisateur (XML) et vos fonctionnalités de calcul (fichiers de classe Java). Cela facilite également le débogage. Il est en fait beaucoup plus facile de lire de cette façon et de penser à Android imo.

Question 2: Je crois que les deux principalement utilisés sont # 2 et # 3. Je vais utiliser un bouton clickButton comme exemple.

2

est sous la forme d'une classe anonyme.

Button clickButton = (Button) findViewById(R.id.clickButton);
clickButton.setOnClickListener( new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                ***Do what you want with the click here***
            }
        });

Ceci est mon préféré car il a la méthode onClick juste à côté de l'endroit où la variable de bouton a été définie avec le findViewById. Il semble très soigné et ordonné que tout ce qui traite de ce clickButton Button View se trouve ici.

Un inconvénient que mon collègue commente, c'est que vous imaginiez avoir plusieurs points de vue qui requièrent l'auditeur onclick. Vous pouvez voir que votre onCreate sera très long. Alors que pourquoi il aime utiliser:

3

Disons que vous avez 5 boutons de clic:

Assurez-vous que votre activité/fragment implémente OnClickListener 

// in OnCreate

Button mClickButton1 = (Button)findViewById(R.id.clickButton1);
mClickButton1.setOnClickListener(this);
Button mClickButton2 = (Button)findViewById(R.id.clickButton2);
mClickButton2.setOnClickListener(this);
Button mClickButton3 = (Button)findViewById(R.id.clickButton3);
mClickButton3.setOnClickListener(this);
Button mClickButton4 = (Button)findViewById(R.id.clickButton4);
mClickButton4.setOnClickListener(this);
Button mClickButton5 = (Button)findViewById(R.id.clickButton5);
mClickButton5.setOnClickListener(this);


// somewhere else in your code

public void onClick(View v) {
    switch (v.getId()) {
        case  R.id.clickButton1: {
            // do something for button 1 click
            break;
        }

        case R.id.clickButton2: {
            // do something for button 2 click
            break;
        }

        //.... etc
    }
}

Ainsi, comme l'explique mon collègue, c'est plus net à ses yeux, car tous les calculs onClick sont gérés à un endroit et ne surchargent pas la méthode onCreate. Mais l’inconvénient que je vois est que: 

  1. se voit, 
  2. et tout autre objet susceptible d'être situé dans onCreate utilisé par la méthode onClick devra être transformé en champ.

Faites-moi savoir si vous souhaitez plus d'informations. Je n'ai pas répondu complètement à votre question parce que c'est une question assez longue. Et si je trouve des sites, je vais élargir ma réponse, je ne fais que donner une expérience.

126
D. Tran

# 1 J'utilise fréquemment le dernier en présence de boutons sur la disposition qui ne sont pas générés (mais statiques évidemment).

Si vous l'utilisez dans la pratique et dans une application métier, faites très attention, car lorsque vous utilisez source obfuscater comme ProGuard, vous devez indiquer ces méthodes dans votre activité pour ne pas être masquées.

Pour archiver une sorte de sécurité au moment de la compilation avec cette approche, consultez Android Lint ( exemple ).


# 2 Avantages et inconvénients pour toutes les méthodes sont presque les mêmes et la leçon devrait être:

Utilisez ce qui est le plus approprié ou qui vous semble le plus intuitif.

Si vous devez affecter la même variable OnClickListener à plusieurs instances de bouton, enregistrez-la dans la classe (# 1). Si vous avez besoin d'un simple écouteur pour un bouton, effectuez une implémentation anonyme:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Take action.
    }
});

J'ai tendance à ne pas implémenter la OnClickListener dans l'activité, cela crée parfois un peu de confusion (surtout lorsque vous implémentez plusieurs autres gestionnaires d'événements et que personne ne sait ce que this fait tout).

10
Lukas Knuth

Je préfère l'option 4, mais cela me semble intuitif, car je travaille beaucoup trop dans Grails, Groovy et JavaFX. Les connexions "magiques" entre la vue et le contrôleur sont courantes. Il est important de bien nommer la méthode:

Dans la vue, ajoutez la méthode onClick au bouton ou à un autre widget:

    Android:clickable="true"
    Android:onClick="onButtonClickCancel"

Puis dans la classe, manipulez la méthode:

public void onButtonClickCancel(View view) {
    Toast.makeText(this, "Cancel pressed", Toast.LENGTH_LONG).show();
}

Encore une fois, nommez la méthode clairement, quelque chose que vous devriez faire quand même, et la maintenance devient une seconde nature.

Un gros avantage est que vous pouvez maintenant écrire des tests unitaires pour la méthode. L'option 1 peut le faire, mais les options 2 et 3 sont plus difficiles.

8
Steve Gelman

Le moyen le plus utilisé est la déclaration anonyme

    Button send = (Button) findViewById(R.id.buttonSend);
    send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // handle click
        }
    });

Vous pouvez également créer un objet View.OnClickListener et le définir sur le bouton ultérieurement, mais vous devez toujours remplacer la méthode onClick, par exemple.

View.OnClickListener listener = new View.OnClickListener(){
     @Override
        public void onClick(View v) {
            // handle click
        }
}   
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(listener);

Lorsque votre activité implémente l'interface OnClickListener, vous devez écraser la méthode onClick (View v) au niveau de l'activité. Ensuite, vous pouvez associer cette activité à l’écoute du bouton, car elle implémente déjà l’interface et remplace la méthode onClick ().

public class MyActivity extends Activity implements View.OnClickListener{


    @Override
    public void onClick(View v) {
        // handle click
    }


    @Override
    public void onCreate(Bundle b) {
        Button send = (Button) findViewById(R.id.buttonSend);
        send.setOnClickListener(this);
    }

}

(à mon humble avis) la quatrième approche utilisée lorsque plusieurs boutons ont le même gestionnaire, et vous pouvez déclarer une méthode dans la classe d'activité et affecter cette méthode à plusieurs boutons dans une présentation XML. Vous pouvez également créer une méthode pour un bouton. préférez pour déclarer les gestionnaires dans la classe d’activité.

4
Georgy Gobozov

Les options 1 et 2 impliquent l’utilisation de la classe interne qui rendra le code encombré. L'option 2 est en quelque sorte en désordre car il y aura un écouteur pour chaque bouton. Si vous avez un petit nombre de boutons, c’est correct ... pour l’option 4, je pense que ce sera plus difficile à déboguer car vous devrez revenir en arrière et mettre en quatrième le code xml et Java . Personnellement, j’utilise l’option 3 quand Je dois gérer plusieurs clics de bouton.

1
CChi

Mon échantillon, testé dans le studio Android 2.1

Bouton Définir dans la mise en page XML

<Button
    Android:id="@+id/btn1"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content" />

Détection de pulsation Java

Button clickButton = (Button) findViewById(R.id.btn1);
if (clickButton != null) {
    clickButton.setOnClickListener( new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            /***Do what you want with the click here***/
        }
    });
}
1
Webserveis

Pour simplifier les choses, a déclaré la question 2, vous pouvez utiliser la méthode lambda pour enregistrer la mémoire variable et éviter de naviguer dans la classe de vue.

//method 1
findViewById(R.id.buttonSend).setOnClickListener(v -> {
          // handle click
});

mais si vous souhaitez appliquer click event à votre bouton immédiatement dans une méthode.

vous pouvez utiliser la question 3 de @D. Réponse Tran. Mais n'oubliez pas d'implémenter votre classe d'affichage avec View.OnClickListener

En autre, utiliser correctement la question 3 

1
Michael

Étape 1: Créer un fichier XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <Button
        Android:id="@+id/btnClickEvent"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="Click Me" />
</LinearLayout>

Étape 2: Créer MainActivity:

package com.scancode.acutesoft.telephonymanagerapp;

import Android.app.Activity;
import Android.os.Bundle;
import Android.view.View;
import Android.widget.Button;

public class MainActivity extends Activity implements View.OnClickListener {

    Button btnClickEvent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnClickEvent = (Button) findViewById(R.id.btnClickEvent);
        btnClickEvent.setOnClickListener(MainActivity.this);

    }

    @Override
    public void onClick(View v) {
        //Your Logic
    }
}

HappyCoding!

0
Manikanta Reddy

Question n ° 1 - C’est le seul moyen de gérer les clics sur les vues. 

Question 2 -
Option n ° 1/option n ° 4 - Il n'y a pas beaucoup de différence entre l'option n ° 1 et l'option n ° 4. La seule différence que je vois est que dans un cas l'activité implémente OnClickListener, alors que dans l'autre cas, il y aurait une implémentation anonyme.

Option n ° 2 - Dans cette méthode, une classe anonyme sera générée. Cette méthode est un peu fastidieuse, car vous devrez le faire plusieurs fois si vous avez plusieurs boutons. Pour les classes anonymes, vous devez faire attention à la gestion des fuites de mémoire.

Option n ° 3 - Bien que ce soit un moyen facile. Habituellement, les programmeurs essaient de ne pas utiliser de méthode avant de l'écrire. Cette méthode n'est donc pas largement utilisée. Vous verriez que la plupart des gens utilisent l'option n ° 4. Parce que c'est plus propre en terme de code. 

0
Gaurav Arora

Il existe également des options disponibles sous la forme de diverses bibliothèques qui peuvent rendre ce processus très familier aux personnes ayant utilisé d'autres frameworks MVVM.

https://developer.Android.com/topic/libraries/data-binding/

Montre un exemple de bibliothèque officielle, qui vous permet de relier des boutons comme ceci:

<Button
    Android:text="Start second activity"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:onClick="@{() -> presenter.showList()}"
/>
0
Ryan The Leach