J'essaie de gérer des événements tactiles et de cliquer sur des événements sur un bouton. Je fais ce qui suit:
button.setOnClickListener(clickListener);
button.setOnTouchListener(touchListener);
Lorsqu'un auditeur est enregistré, tout fonctionne correctement, mais lorsque j'essaie de les utiliser, seuls les événements tactiles sont déclenchés. Une solution de contournement? Qu'est-ce que je fais mal?
Il existe une différence subtile mais très importante entre ClickListener
et TouchListener
. La TouchListener
est exécutée avant que la vue puisse répondre à l'événement. La ClickListener
ne recevra son événement que lorsque la vue l'aura traité.
Ainsi, lorsque vous touchez votre écran, la TouchListener
est exécutée en premier et lorsque vous renvoyez true
pour votre événement, la ClickListener
ne l'obtiendra jamais. Mais si vous appuyez sur la boule de commande de votre appareil, la ClickListener
doit être déclenchée, car la TouchListener
ne répond pas.
C'est un peu délicat.
Si vous définissez onTouchListener
, vous devez renvoyer true
dans ACTION_DOWN
, pour indiquer au système que j'ai consommé l'événement et qu'il ne sera pas répercuté sur les autres écouteurs.
Mais alors OnClickListener
ne sera pas renvoyé.
Vous pouvez donc penser que je vais juste faire mon travail là-bas et renvoyer false
afin que je puisse aussi recevoir des clics . Si vous le faites, cela fonctionnera, mais vous ne serez pas abonné à d'autres événements tactiles à venir (ACTION_MOVE
, ACTION_UP
) Par conséquent, la seule option consiste à renvoyer true
à cet endroit, mais vous ne recevrez aucun événement de clic comme indiqué précédemment.
Vous devez donc effectuer le clic manuellement dans le ACTION_UP
avec view.performClick()
Cela fonctionnera.
Vous devriez retourner false dans votre OnTouchListener
, votre OnClickListener
sera également traitée.
Je suppose que vous retournez true
dans votre OnTouchListener
? Cela consommera l'événement, il ne sera donc pas envoyé pour un traitement ultérieur.
Sur une note de côté - quel est l'intérêt d'avoir à la fois un écouteur clic et tactile?
button.setOnTouchListener(this);
Implémentez l'interface et le code ici:
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (view.getId()) {
case R.id.send:
switch(motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
//when the user has pressed the button
//do the needful here
break;
case MotionEvent.ACTION_UP:
//when the user releases the button
//do the needful here
break;
}
break;
}
return false;
}
## Exact working solution for both click action and touch listener(dragging) ##
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private float CLICK_ACTION_THRESHOLD = 0.5f;
private float startX;
private float startY;
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (view.getId()) {
case R.id.chat_head_profile_iv:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//remember the initial position.
initialX = params.x;
initialY = params.y;
startX = event.getX();
startY = event.getY();
//get the touch location
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
return true;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float endY = event.getY();
if (shouldClickActionWork(startX, endX, startY, endY)) {
openScreen();// WE HAVE A CLICK!!
}
return true;
case MotionEvent.ACTION_MOVE:
//Calculate the X and Y coordinates of the view.
params.x = initialX + (int) (event.getRawX() - initialTouchX);
params.y = initialY + (int) (event.getRawY() - initialTouchY);
//Update the layout with new X & Y coordinate
mWindowManager.updateViewLayout(mChatHeadView, params);
return true;
}
break;
}
return true;
}
private boolean shouldClickActionWork(float startX, float endX, float startY, float endY) {
float differenceX = Math.abs(startX - endX);
float differenceY = Math.abs(startY - endY);
if ((CLICK_ACTION_THRESHOLD > differenceX) && (CLICK_ACTION_THRESHOLD > differenceY))
return true;
else
return false;
}
Pour rendre les deux événements possibles dans gridview, uniquement en rendant le retour de l'auditeur tactile "faux" comme suit, cela a fonctionné pour moi.
**GridView myView = findViewById(R.id.grid_view);
myView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// ... Respond to touch events
return false;
}
});**
de cette façon, les deux événements peuvent être atteints
Toutes les réponses ci-dessus sont dites que nous ne pouvons pas gérer à la fois setOnTouchListener
et setOnClickListener
.
Cependant, je vois que nous pouvons gérer les deux par return false
dans setOnTouchListener
Exemple
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.button)
button.setOnClickListener {
Log.i("TAG", "onClick")
}
button.setOnTouchListener { v, event ->
Log.i("TAG", "onTouch " + event.action)
false
}
}
Lorsque je clique sur Button
, logcat s’affiche comme suit:
I/TAG: onTouch 0
I/TAG: onTouch 1
I/TAG: onClick