ProgramingTip

MotionEvent.ACTION_UP이 호출되지 않을 것입니다.

bestdevel 2020. 12. 2. 21:41
반응형

MotionEvent.ACTION_UP이 호출되지 않을 것입니다.


내 문제를 더 잘 이해하기 위해 아래의 계획을 고려하십시오. 여기에 이미지 설명 입력

보시다시피 패딩으로 목록 목록보기를 고려하고 있습니다. 이제 사용자가 목록 항목을 참조 작업으로 밝은 파란색 배경색을 제공했습니다. 이제 내 응용 프로그램은 onTouch 이벤트 자체를 처리하여 다음과 같은 작업을 결정합니다.

  • 딸깍하는 소리
  • 왼쪽에서 오른쪽으로 스 와이프
  • 오른쪽에서 왼쪽으로 스 와이프

다음은 내 코드입니다.

public boolean onTouch(View v, MotionEvent event) {
        if(v == null)
        {
            mSwipeDetected = Action.None;
            return false;
        }
        switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN: {
            downX = event.getRawX();
            downY = event.getRawY();
            mSwipeDetected = Action.Start;

         // Find the child view that was touched (perform a hit test)
            Rect rect = new Rect();
            int childCount = listView.getChildCount();
            int[] listViewCoords = new int[2];
            listView.getLocationOnScreen(listViewCoords);
            int x = (int) event.getRawX() - listViewCoords[0];
            int y = (int) event.getRawY() - listViewCoords[1];
            View child;
            for (int i = 0; i < childCount; i++) {
                child = listView.getChildAt(i);
                child.getHitRect(rect);
                if (rect.contains(x, y)) {
                    mDownView = child;
                    break;
                }
            }


            return false; // allow other events like Click to be processed
        }
        case MotionEvent.ACTION_MOVE: {
            upX = event.getRawX();
            upY = event.getRawY();
            float deltaX=0,deltaY=0;
             deltaX = downX - upX;
             deltaY = downY - upY;

                if(deltaY < VERTICAL_MIN_DISTANCE)
                {
                            setTranslationX(mDownView, -(deltaX));
                            setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / listView.getWidth())));
                            return false;
                }
                else
                {
                    forceBringBack(v);
                }

                          return false;              

        }
        case MotionEvent.ACTION_UP:
        {

             stopX = event.getX();
             float stopValueY = event.getRawY() - downY;             
             float stopValue = stopX - downX;

             if(!mDownView.isPressed())
             {
                 forceBringBack(mDownView);
                 return false;
             }             

             boolean dismiss = false;
             boolean dismissRight = false;


             if(Math.abs(stopValue)<10)
             {
                 mSwipeDetected = Action.Start;
             }
             else
             {
                 mSwipeDetected = Action.None;

             }
             String log = "";
             Log.d(log, "Here is Y" + Math.abs(stopValueY));
             Log.d(log, "First Comparison of Stop Value > with/4" + (Math.abs(stopValue) > (listView.getWidth() /4)));
             Log.d(log, "Second Comparison " + (Math.abs(stopValueY)<VERTICAL_MIN_DISTANCE));
             Log.d(log, "Action Detected is " + mSwipeDetected + " with Stop Value  " + stopValue);

             if((Math.abs(stopValue) > (listView.getWidth() /4))&&(Math.abs(stopValueY)<VERTICAL_MIN_DISTANCE))
             {
                 dismiss = true;
                 dismissRight = stopValue > 0;

                 if(stopValue>0)
                 {
                 mSwipeDetected = Action.LR;

                 }
                 else
                     mSwipeDetected = Action.RL;
             }
             Log.d(log, "Action Detected is " + mSwipeDetected + " with Stop Value after dissmiss" + stopValue);

             if(dismiss)
             {
                 if(dismissRight)
                     mSwipeDetected = Action.LR;
                 else
                     mSwipeDetected = Action.RL;
                 animate(mDownView)
                 .translationX(dismissRight ? listView.getWidth() : - listView.getWidth())
                 .alpha(0)
                 .setDuration(mAnimationTime)
                 .setListener(new AnimatorListenerAdapter() {
                     public void onAnimationEnd(Animator animation)
                     {

                     }
                });
             }
             else
             {
                 animate(mDownView)
                 .translationX(0)
                 .alpha(1)
                 .setDuration(mAnimationTime)
                 .setListener(null);
             }


             break;           

        }
        }
        return false;
    }

보시다시피 MotionEvent.ACTION_UP에서 수행 된 작업을 결정하고 그에 따라 Enum Action의 값을 설정합니다. 이 논리는 사용자가 목록보기 경계를 넘지 않는 경우 매력처럼 작동합니다.

이제 사용자가 슬라이딩 (또는 구체적으로)하는 동안 목록 항목을 따라 손가락을 움직일 때 파란색에서 주황색으로 이동하면 MotionEvent.ACTION_UP이 listview에 제공되지 않아 내 코드가 결정을 내리지 못하고 translationX로 인해 () 메서드와 setAlpha (),이 경우 어떤 액션도 결정되지 않았으므로 해당 특정 목록 항목은 비어 있습니다.

매번 뷰를 팽창시키지 않기 때문에 문제는 여기서 멈추지 않습니다. 매번 동일한 translateX () 행이 팽창되어 공백 / 화이트 목록 항목이 여러 번 발생하기 때문입니다.

MotionEvent.ACTION_UP이 발생하지 않더라도 여전히 결정을 내릴 수 있도록 할 수있는 일이 있습니까?


당신이해야 return true;case MotionEvent.ACTION_DOWN:, 그래서이 MotionEvent.ACTION_UP처리됩니다.


View.OnTouchListener에 설명 된 대로 :

반환 :

리스너가 이벤트를 소비 한 경우 true, 그렇지 않으면 false입니다.

MotionEvent.ACTION_UPMotionEvent.ACTION_DOWN발생할 때까지 호출되지 않습니다. 이에 대한 논리적 설명은 이전에 ACTION_UPACTION_DOWN번도 발생하지 않은 경우 발생할 수 없다는 것입니다.

이 로직을 통해 개발자는 ACTION_DOWN.


또한 특정 상황 (예 : 화면 회전)에서 제스처가 취소 될 수 있으며이 경우 a MotionEvent.ACTION_UP가 전송되지 않습니다. 대신 a MotionEvent.ACTION_CANCEL가 대신 전송됩니다. 따라서 정상적인 동작 switch 문은 다음과 같아야합니다.

switch (event.getActionMasked()) {
    case MotionEvent.ACTION_DOWN:
        // check if we want to handle touch events, return true
        // else don't handle further touch events, return false
    break;

    // ... handle other cases

    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_CANCEL:
        // finish handling touch events
        // note that these methods won't be called if 'false' was returned
        // from any previous events related to the gesture
    break;
}

return true;케이스에 추가 하면 MotionEvent.ACTION_DOWN:결국 문제가 해결 될 것이라고 생각하지 않습니다 . return false매력처럼 일을 할 수 있었던 상황을 복잡하게 만들었습니다.

통지에 무엇 : MotionEvent.ACTION_DOWN: /*something*/ return true;제대로 동안, 심지어 onClickListenerm,에 사용할 다른 뷰 리스너 콜백을 차단 return false에서이 MotionEvent.ACTION_UP:MotionEvent이 올바른 목적지로 전파 될 수 있습니다.

그의 원본 코드 소스 참조 : https://github.com/romannurik/android-swipetodismiss


으로 Danpe 그의 간결한 대답에 설명 -나는 ACTION_UP 인식이하기 위해 ACTION_DOWN 코드를 추가했다.

            case MotionEvent.ACTION_DOWN:

                return true;

            case MotionEvent.ACTION_UP:

                XyPos xyPos = new XyPos();
                xyPos.x = last_x;
                xyPos.y = last_y;
                handleViewElementPositionUpdate(xyPos);

                break;

어쨌든 전체 onTouch (..) 메소드가 참을 반환하기 때문에 그게 충분하지 않은 이유는 모르겠지만 ...이 빠른 솔루션을위한 것이 좋습니다 .. (감사합니다!)

참고 URL : https://stackoverflow.com/questions/15799839/motionevent-action-up-not-called

반응형