J'ai un Layout
défini en XML qui consiste en plusieurs Button
s.
Actuellement, je le fais dans la méthode OnCreate
pour définir les gestionnaires d'événements par rapport aux 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 l'événement Button
's onClick
, je lance une caméra Intent
pour obtenir une image et à l'intérieur du rappel onActivityResult
, je configure à nouveau les gestionnaires d'événements en même temps que View
:
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 de redéfinir un événement à chaque fois me semble assez sale. J'aimerais savoir quelle est la meilleure pratique pour définir des gestionnaires d'événements de boutons dans des scénarios comme celui-ci.
Edit: coller 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é-enregistrer des événements dans 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.
Pourquoi ne pas enregistrer l'événement onClick dans la présentation XML et le gérer ensuite dans le code. Voici comment je le ferais:
<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 permettrait de gérer les clics
public void onBtnClicked(View v){
if(v.getId() == R.id.my_btn){
//handle the click here
}
}
Vous pouvez également définir 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.
METTRE À JOUR:
Bien que ce soit une approche valable, je recommanderais fortement la deuxième option. C'est plus propre et plus facile à maintenir, surtout lorsque vous travaillez avec des fragments.
Voici la meilleure approche avec le 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 utile que si vous souhaitez découpler l’implémentation (lorsque vous souhaitez utiliser le même code de classe ailleurs, déplacez-le dans un autre fichier de classe séparé, etc.), mais en général si vous effectuez des opérations connexes. L'activité en cours et les implémentations onClick dépendent de son exécution en référence aux objets définis. Vous devez absolument utiliser la méthode que j'ai proposée.
La création d’interfaces de classes n’est utile que si vous souhaitez établir une communication entre des classes ou des activités distinctes tout en gardant les choses à part. à part cela, c’est une mauvaise pratique de créer des sous-classes pour cela.
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;
}
}
};
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'attribut onClick
du bouton.
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 Java:
// stuff
public void myClickMethod(View v) {
// more stuff
}
De cette façon, vous n’aurez pas à implémenter vous-même la OnClickListener
. Vous pouvez attribuer à chaque bouton la même méthode onClick
et ensuite simplement décider par action quelle action déclencher ou vous pouvez avoir une méthode séparée pour chaque bouton.
En général, je déconseille d'utiliser une OnClickListener
pour plus d'un bouton. Il est plus facile de comprendre ce que chaque auditeur est censé faire si vous utilisez des noms descriptifs, ce que vous devriez faire de toute façon.
J'aime la méthode "moderne" de DI en utilisant Butter Knife :
@InjectView(R.id.buttonAlert)
Button buttonAlert;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
}
@OnClick(R.id.buttonAlert)
public void alertClicked(View v){
// your logic
}
@ Hasan C'est la meilleure approche que j'ai trouvée et qui me convient parfaitement à chaque fois.
Dans Layout.xml, définissez 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
Dans le fichier sample.Java, la fonction définie dans R.string sera appelée par un clic sur le bouton et devrait ressembler à quelque chose comme:
public void buttonFunction (View View) { // ne rien faire comme sur le clic du bouton }
Voici comment je l'ai fait:
@Passer outre
public void onClick(View view) {
Intent intent;
switch(view.getId()){
case R.id.home_button:
//DO something
intent = new Intent(HashTagActivity.this,MainActivity.class);
startActivity(intent);
break;
case R.id.back_button:
//DO something
intent = new Intent(HashTagActivity.this,ClassActivity.class);
startActivity(intent);
break;
case R.id.favorite_button:
//DO something
break;
case R.id.copy_button:
//DO something
break;
}
}
Cela fonctionne très bien.
Je sais que c'est vieux, mais si quelqu'un se demande pourquoi vous ne pouvez pas ajouter onClickListener
à partir de onActivityResult
, c'est parce que le bouton est nul. Si vous l'initialisez une nouvelle fois (comme vous l'avez fait dans onCreate
), vous pouvez ajouter le programme d'écoute. Soyez prudent, cependant, tout le reste sera également nul, donc si vous prenez des données à partir d'une EditText
, par exemple, vous devez l'initialiser également (un simple contrôle si l'objet est null dans la liste fera l'affaire ).
Votre activité doit implémenter OnClickListener et vous devez écrire toute votre gestion des événements pour tous les boutons de la seule méthode OnCLick ().
Le problème est que l'objet pour le bouton newPicButton est créé en tant qu'objet local qui est valide uniquement dans l'étendue de la fonction onCreate et dès que le code quitte cette fonction, le collecteur garabage libère l'objet pour le bouton. Ce que vous devez faire est de déclarer l'objet newPicButton en dehors de toute méthode, puis dans la méthode onCreate, affectez-lui un écouteur. Cela résoudra votre problème et j'espère avoir expliqué pourquoi rien ne se passe lorsque vous supprimez le code du newPicButton dans la méthode onActivityResult :)