web-dev-qa-db-fra.com

événement onClick ne déclenche pas | Android

J'ai fait une application de test très simple avec une activité et une mise en page. La onClick ne se déclenche pas la première fois que vous appuyez dessus, comme il se doit.

L'activité:

package com.example.mytest;

import Android.os.Bundle;
import Android.app.Activity;
import Android.view.Menu;
import Android.view.View;
import Android.widget.EditText;
import Android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText ed1 = (EditText) findViewById(R.id.editText1);

        ed1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_LONG)
                        .show();

            }

        });
    }

}

La disposition:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <EditText
        Android:id="@+id/editText1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentTop="true"
        Android:ems="10" >

        <requestFocus />
    </EditText>

    <EditText
        Android:id="@+id/editText2"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentLeft="true"
        Android:layout_below="@+id/editText1"
        Android:ems="10" />

</RelativeLayout>

Si vous exécutez cette application et cliquez sur la deuxième editText, puis sur la première, la onClick ne sera pas déclenchée. Vous pouvez continuer à sélectionner en arrière et cela ne déclenchera pas du tout la variable onClick. J'ai besoin de cette fonctionnalité de base, mais je n'ai pas été en mesure de trouver un moyen de la faire fonctionner. Des idées?

Remarquer

J'ai essayé toutes les méthodes recommandées sur mon périphérique physique API de niveau 16 et mon émulateur d'API de niveau 8, mais je rencontre le même problème.

Clarification

Lorsque editText1 est activé et que l'utilisateur clique dessus, la méthode onClick est déclenchée. Si editText2 est ciblé et que l'on clique sur editText1, il ne le fait pas est déclenché. Gros problème.

48
EGHDK

Overview, Lorsqu'un utilisateur interagit avec un composant de l'interface utilisateur, les différents écouteurs sont appelés dans un ordre descendant. Si l'un des écouteurs de priorité supérieure "consomme l'événement", les écouteurs inférieurs ne seront pas appelés .

Dans votre cas, ces trois auditeurs sont appelés dans l'ordre:

  1. OnTouchListener
  2. OnFocusChangeListener
  3. OnClickListener

La première fois que l'utilisateur touche un texte d'édition, il reçoit le focus pour qu'il puisse taper. L'action est consommée ici. Par conséquent, la priorité inférieure OnClickListener n'est pas appelée. Chaque contact successif ne change pas le focus, donc ces événements se répercutent sur OnClickListener.

Les boutons (et autres composants similaires) ne reçoivent pas le focus d'un événement tactile, c'est pourquoi OnClickListener est appelé à chaque fois.

En gros, vous avez trois choix:

  1. Implémentez un OnTouchListener par lui-même:

    ed1.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(MotionEvent.ACTION_UP == event.getAction())
                editTextClicked(); // Instead of your Toast
            return false;
        }
    });
    

    Cela s'exécutera à chaque fois que le EditText est touché. Notez que l'écouteur retourne false, cela permet à l'événement de se répercuter sur OnFocusChangeListener intégré, qui modifie le focus afin que l'utilisateur puisse taper dans EditText.

  2. Implémentez OnFocusChangeListener avec OnClickListener:

    ed1.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus)
                editTextClicked(); // Instead of your Toast
        }
    });
    

    Cet écouteur attrape le premier événement tactile lorsque le focus est modifié, tandis que votre OnClickListener intercepte tous les autres événements.

  3. (Ce n'est pas une réponse valable ici, mais c'est une bonne astuce à connaître.) Définissez l'attribut focusable sur false dans votre XML:

    Android:focusable="false"
    

    Maintenant, le OnClickListener déclenchera chaque fois sur lequel il est cliqué. Mais cela rend le EditText inutile puisque l'utilisateur ne peut plus entrer de texte ...

Remarque:

getApplicationContext() peut créer des fuites de mémoire. Une bonne habitude est d'éviter de l'utiliser sauf si cela est absolument nécessaire. Vous pouvez utiliser en toute sécurité v.getContext() à la place.

J'espère que cela pourra aider!

177
Sam

rendre le texte d'édition cliquable .. En XML Android:clickable="true" ou en code 

ed1.setClickable(true);

alors fais 

ed1.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
      Toast.makeText(getBaseContext(), "1",Toast.LENGTH_SHORT).show();
    }
  });
5
mainu

Je suis probablement trop tard pour la fête, mais voici un extrait de code qui résout le problème avec onClick () non appelé:

ed1.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP && !v.hasFocus()) {
            // onClick() is not called when the EditText doesn't have focus,
            // onFocusChange() is called instead, which might have a different 
            // meaning. This condition calls onClick() when click was performed
            // but wasn't reported. Condition can be extended for v.isClickable()
            // or v.isEnabled() if needed. Returning false means that everything
            // else behaves as before.
            v.performClick();
        }
        return false;
    }
});
4

Cela est dû au fait que le premier tapotement met en évidence la vue. Le robinet suivant déclenche le clic.

Si vous gonflez la vue dynamiquement, procédez comme suit:

Android:clickable="true"
Android:focusable="false"
Android:focusableInTouchMode="false"

Si cela ne fonctionne pas, essayez également de l'appliquer à la vue parent.

2
Irshu
public class TestProject extends Activity implements OnClickListener {
TextView txtmsg;
EditText ed1, ed2;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    txtmsg = (TextView) findViewById(R.id.txtmsg);
    ed1 = (EditText) findViewById(R.id.edt1);
    ed2 = (EditText) findViewById(R.id.edt2);

    ed1.setOnClickListener(this);
    ed2.setOnClickListener(this);
}

@Override
public void onClick(View v) {


    if(v==ed1){
        txtmsg.setText("1");
        Toast.makeText(this, "first",Toast.LENGTH_SHORT).show();
    }
    if(v==ed2){
        txtmsg.setText("2");
        Toast.makeText(this, "second",Toast.LENGTH_SHORT).show();
    }

}

}

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" >

    <EditText
        Android:id="@+id/edt1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentLeft="true"
        Android:layout_alignParentTop="true"
        Android:ems="10" />

    <EditText
        Android:id="@+id/edt2"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentLeft="true"
        Android:layout_below="@+id/edt1"
        Android:layout_marginTop="14dp"
        Android:ems="10" />

    <TextView
        Android:id="@+id/txtmsg"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignRight="@+id/edt2"
        Android:layout_below="@+id/edt2"
        Android:layout_marginRight="22dp"
        Android:layout_marginTop="160dp"
        Android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>
0
Yash

Évitez d’utiliser une FocusChangeListener car elle se comportera de manière erratique si vous n’en avez pas vraiment besoin (par exemple lorsque vous entrez dans une activité). Il suffit de définir une OnTouchListener avec votre OnClickListener comme ceci:

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            view.requestFocus();
            break;
    }
    return false;
}

Cela fera que votre EditText sera d'abord ciblé et que votre onClick fonctionnera correctement la première fois.

0
Andrei Lupsa

Il m'a fallu une minute pour comprendre cela une fois où cela m'est arrivé. Ma ImageButton avec setOnClickListener et onClick n'a pas semblé se déclencher, puis j'ai réalisé qu'il se trouvait en réalité sous un autre élément de ma présentation xml.

 <RelativeLayout>
     <ImageButton>
     <LinearLayout></LinearLayout>
 </RelativeLayout>

dans ceci:

 <RelativeLayout>
     <LinearLayout></LinearLayout>
     <ImageButton>
 </RelativeLayout>

et tout à coup l'imageButton n'a pas été superposée par l'autre mise en page, car elle a été ajoutée plus tard à la mise en page parent. Bonne chance, toujours amusant quand des choses de base semblent soudainement cesser de fonctionner

0
ColossalChris

C'est la manière la plus simple de travailler avec le sélecteur de dates.

private DatePickerDialog datePickerDialog;
EditText etJoiningDate;
etJoiningDate=(EditText)findViewById(R.id.etJoiningDate);

etJoiningDate.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:

                final Calendar cldr = Calendar.getInstance();
                int day = cldr.get(Calendar.DAY_OF_MONTH);
                int month = cldr.get(Calendar.MONTH);
                int year = cldr.get(Calendar.YEAR);
                // date picker dialog
                datePickerDialog = new DatePickerDialog(TestActivity.this,
                        new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                                etJoiningDate.setText(dayOfMonth + "/" + (monthOfYear + 1) + "/" + year);
                            }
                        }, year, month, day);
                datePickerDialog.show();

                break;
        }


        return false;
    }


});
0
Hasan Masud