web-dev-qa-db-fra.com

Détecter un événement tactile sur une vue lorsqu'il est déplacé depuis une autre vue

Comment détecter l'événement tactile si l'utilisateur touche la vue A et glisse jusqu'en bas de la vue B. Je souhaite détecter l'événement tactile dans la vue B.

J'ai ajouté un écouteur tactile dans la vue B, mais je ne recevais pas les événements si l'utilisateur avait initialement touché A et fait glisser le B.

enter image description here

18
dcanh121

Vous pouvez utiliser le code ci-dessous pour répondre à votre demande:

Méthode de test des limites de la vue (utilisée dans le code ci-dessous)

    Rect outRect = new Rect();
    int[] location = new int[2];

    private boolean isViewInBounds(View view, int x, int y){
        view.getDrawingRect(outRect);
        view.getLocationOnScreen(location);
        outRect.offset(location[0], location[1]);
        return outRect.contains(x, y);
    }

Test avec deux TextView

    final TextView viewA = (TextView)  findViewById(R.id.textView);
    final TextView viewB = (TextView)  findViewById(R.id.textView2);

Vue de configurationA

La OnClickListener vide est nécessaire pour garder OnTouchListener active jusqu'au ACTION_UP

    viewA.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {}
    });

    viewA.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int x = (int)event.getRawX();
            int y = (int)event.getRawY();
            if(event.getAction() == MotionEvent.ACTION_UP){
                if(isViewInBounds(viewB, x, y))
                    viewB.dispatchTouchEvent(event);
                else if(isViewInBounds(viewA, x, y)){
                    Log.d(TAG, "onTouch ViewA");
                    //Here goes code to execute on onTouch ViewA
                }
            }
            // Further touch is not handled
            return false;
        }
    });

Vue de configurationB

Cela n’est nécessaire que si vous souhaitez également appuyer sur viewB et faire glisser pour afficherA

    viewB.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {}
    });

    viewB.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int x = (int)event.getRawX();
            int y = (int)event.getRawY();
            if(event.getAction() == MotionEvent.ACTION_UP){
                if(isViewInBounds(viewA, x, y))
                    viewA.dispatchTouchEvent(event);
                else if(isViewInBounds(viewB, x, y)){
                    Log.d(TAG, "onTouch ViewB");
                    //Here goes code to execute on onTouch ViewB
                }
            }
            // Further touch is not handled
            return false;
        }
    });

Cordialement.

58
Luis

Dans ViewA, écrasez onTouchEvent comme suit:

@Override
public boolean onTouchEvent(MotionEvent event) 
{

    float x = event.getRawX();
    float y = event.getRawY();
    if ( (B.getLeft() <= x <= B.getRight()) &&
         (B.getTop() <= y <= B.getBottom())
       )
    {
        Log.i("A", "Motion Event is currently above B");
        B.dispatchTouchEvent(event);
    }

    return true;
}

Dans ViewB, remplacez la même méthode, en vous assurant que vous retournez false:

@Override
public boolean onTouchEvent(MotionEvent event) 
{
    //TODO handle touch event
    return false;//this will allow A to continue using the event
}
1
Phil

Si vous renvoyez true de l'événement onTouchEvent de la vue A, l'événement n'est pas propagé. Dans ce cas particulier, lorsque A est inférieur à B, retourne false à partir du onTouch of view A. 

Cela aiderait aussi si vous pouvez poster du code.

1
Abhishek Nandi

Je suis certain que vous devez utiliser la méthode ViewGroup.dispatchTouchEvent(MotionEvent ev) de substitution dans votre groupe de vues, qui contient les vues A et B. L'implémentation d'origine définit la vue cible lorsque le conteneur reçoit MotionEvent.getAction() == MotionEvent.ACTION_DOWN, puis distribue tous les événements tactiles suivants dans la vue cible jusqu'à ce qu'elle reçoive MotionEvent.getAction() == MotionEvent.ACTION_UP ou MotionEvent.ACTION_CANCEL.

Dans votre cas, la vue cible est A ou le conteneur lui-même (dépend de l’implémentation de votre méthode conteneur onInterceptTouchEvent(MotionEvent ev)). Vous devez donc redéfinir ce comportement et répartir les événements tactiles non seulement vers la vue cible, mais également vers toutes les vues situées sous la zone touchée (par exemple, pour afficher B).

Si vous êtes intéressé, vous pouvez partager un exemple de code et je vais essayer de vous aider davantage.

1
rus1f1kat0R

Lorsque vous avez terminé la vue B, appelez la onTouch manuellement.

if (viewBRect.contains(x, y)) {
    viewBsonTouch(view, motionEvent);
}
0
Ronnie

Essayez d’utiliser le framework drag and drop.

0
Joe Malin