68 votes

Meilleure pratique pour définir les événements liés aux boutons dans Android

J'ai un Layout défini en XML, qui se compose de plusieurs Button s.

Actuellement, je fais cela dans le OnCreate pour définir les gestionnaires d'événements pour les boutons :

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

    Button newPicButton = (Button)findViewById(R.id.new_button);
    newPicButton.setOnClickListener(btnListener);
    ..... similarly for other buttons too
    .....
}

L'intérieur de la Button 's onClick je lance une caméra Intent pour obtenir une photo et à l'intérieur de la onActivityResult je configure à nouveau les gestionnaires d'événements ainsi que le paramètre View comme ça :

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    setContentView(R.layout.main);
    Button newPicButton = (Button)findViewById(R.id.new_button);
    newPicButton.setOnClickListener(btnListener);
    ...similarly for other buttons too
}

Je suis nouveau sur Android et cette approche consistant à redéfinir un événement à chaque fois me semble assez sale. J'aimerais savoir quelle est la meilleure pratique en termes de définition de gestionnaires d'événements de boutons dans des scénarios comme celui-ci.

Edit : collage de ma classe complète

public class CameraAppActivity extends Activity 
{
    /** Called when the activity is first created. */

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

        Button newPicButton = (Button)findViewById(R.id.new_button);
        newPicButton.setOnClickListener(btnListener);
    }

    //---create an anonymous class to act as a button click listener---
    private OnClickListener btnListener = new OnClickListener()
    {

        public void onClick(View v)
        {   
             //Intent newPicIntent = new Intent(v.getContext(), NewPictureActivity.class);
             //startActivityForResult(newPicIntent, 0);
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, 999);
        } 

    };  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {  

        setContentView(R.layout.main);
        Button newPicButton = (Button)findViewById(R.id.new_button);
        newPicButton.setOnClickListener(btnListener);

       //if I comment last two lines nothing happens when I click on button

    }  

La question principale est

setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);

Réenregistrement des événements à l'intérieur onActivityResult est-ce la bonne approche ? Ou est-ce que je fais quelque chose de mal ? Parce que si je ne réenregistre pas l'événement, rien ne se passe lorsque je clique sur le bouton.

2 votes

Vous ne devriez pas avoir à les configurer à nouveau en onActivityResult() s'ils sont déjà configurés dans onCreate()

0 votes

:S si je ne le fais pas en revenant à la vue principale après l'intention, rien ne se produit si je clique sur le bouton

64voto

marqss Points 4946

Pourquoi ne pas enregistrer l'événement onClick dans le layout XML et le gérer ensuite dans le code ? Voici comment je procéderais :

<Button
android:id="@+id/my_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"
android:onClick="onBtnClicked">
</Button>

et maintenant créer une méthode qui traiterait les clics

public void onBtnClicked(View v){
    if(v.getId() == R.id.my_btn){
        //handle the click here
    }
}

Vous pouvez également définir le OnClickListener individuellement pour chaque élément du code. Utilisez ensuite les instructions if/else ou switch pour déterminer l'origine.

De cette façon, vous pouvez avoir une méthode qui gère tous les boutons d'une même disposition.

UPDATE:
Bien que cette approche soit valable, je recommande fortement la deuxième option. Elle est plus propre et plus facile à maintenir, surtout lorsque vous travaillez avec des fragments.

0 votes

Cela fonctionne mais vous savez pourquoi ? v.getId() is not same as R.id.takepic_button ". takepic_button est le bouton contre lequel je mets l'événement dans XML

0 votes

Désolé, c'était mon erreur, ça marche très bien, c'était exactement ce que je cherchais.

10 votes

L'inclusion de "onClick" dans la mise en page ne fonctionne pas bien avec les fragments. Jetez un coup d'œil à ce post SO : stackoverflow.com/questions/6091194/

39voto

DArkO Points 5974

Voici la meilleure approche avec un code :

  public class MyTest extends Activity implements OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     //... some other code here to init the layout
        Button btn1 = (Button)findViewById(R.id.button1);
        Button btn2 = (Button)findViewById(R.id.button2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.button1:
                break;
            case R.id.button2:
                break;
        }
    }
}

La nouvelle classe avec une interface n'est bonne que si vous voulez découpler l'implémentation (quand vous voulez utiliser le même code de classe ailleurs, le déplacer dans un autre fichier de classe séparé etc ) mais en général si vous faites des choses liées à l'activité courante sur laquelle vous êtes et que les implémentations onClick dépendent de l'exécution en référence aux objets définis ici vous devriez définitivement utiliser la méthode que j'ai suggérée.

La création d'interfaces de classe n'est bonne que si vous voulez établir une communication entre des classes ou des activités distinctes et garder les choses séparées. Sinon, c'est une mauvaise pratique de créer des sous-classes pour cela.

11voto

Nguyen Minh Binh Points 6438

C'est la meilleure approche

@Override
public void onCreate(Bundle savedInstanceState) {
        button1.setOnClickListener(onClickListener);
        button2.setOnClickListener(onClickListener);
        button3.setOnClickListener(onClickListener);
}

private OnClickListener onClickListener = new OnClickListener() {
     @Override
     public void onClick(final View v) {
         switch(v.getId()){
             case R.id.button1:
                  //DO something
             break;
             case R.id.button2:
                  //DO something
             break;
             case R.id.button3:
                  //DO something
             break;
         }

   }
};

8voto

Octavian Damiean Points 20620

Il n'y a pas de meilleure pratique définie. Cela dépend fortement du cas d'utilisation. Vous pouvez les définir dans votre mise en page XML à l'aide de l'élément onClick attribut.

Exemple XML :

<!-- Stuff -->
<Button android:id="@+id/my_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me!"
    android:onClick="myClickMethod" />

Exemple de Java :

// stuff
public void myClickMethod(View v) {
    // more stuff
}

De cette façon, vous n'avez pas à mettre en œuvre l'option OnClickListener vous-même. Vous pouvez attribuer à chaque bouton le même onClick et décider simplement de l'action à déclencher pour chaque vue. Vous pouvez aussi avoir une méthode distincte pour chaque bouton.

En général, je déconseille l'utilisation d'un OnClickListener pour plus d'un bouton. Il est plus facile de comprendre ce que chaque écouteur est censé faire si vous utilisez des noms descriptifs, ce que vous devriez faire de toute façon.

2 votes

Cela fonctionne mais vous savez pourquoi ? v.getId() is not same as R.id.takepic_button ". takepic_button est le bouton contre lequel je mets l'événement dans XML

0 votes

Je ne peux pas le dire. C'est quelque chose que vous devrez découvrir vous-même.

0 votes

Désolé, c'était mon erreur, ça marche très bien, c'était exactement ce que je cherchais.

2voto

Nitin Points 920

@Hasan C'est la meilleure approche que j'ai trouvée et qui fonctionne pour moi à chaque fois de manière irréprochable.

  • Dans Layout.xml, définissez l'élément onClick pour le bouton

    <Button android:id="@+id/Button01"           
       android:onClick="@string/method" 
       android:focusable="true"
       android:clickable="true"
    >
    </Button>
  • Dans le fichier R.string, ajoutez la ligne suivante

    string name="method">buttonFunction</string
  • Dans le fichier sample.java, la fonction définie en R.string sera appelé lors du clic sur le bouton et devrait ressembler à quelque chose comme

    public void buttonFunction(View view) {
        // do nething u like on the click of the button
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X