ProgramingTip

터치 누름 대 긴 누름 대 움직임 감지?

bestdevel 2020. 11. 20. 09:18
반응형

터치 누름 대 긴 누름 대 움직임 감지?


저는 현재 Android 프로그래밍을 다루고 있습니다. 터치 이벤트를 감지하는 데 작은 문제가 있습니다. 즉, 일반 터치 누르기 (화면을 바로 놓기), 누르기 (화면을 터치하고 손가락을 누르기)) 및 움직임 (화면에서 끌기).

내가하고 싶었던 것은 내 화면에 끌 수있는 (원의) 이미지가있는 것입니다. 그런 다음 한 번 숫자 (짧게 / 일반적으로 누름) 토스트에 대한 몇 가지 기본 정보가 나타납니다. 어디에 있는지 다른 이미지 (원, 또는 삼각형)를 선택할 수있는 AlertDialog가 나타납니다.

이벤트를 감지하고 onDraw에서 이미지를 그리기 위해 자체 OnTouchListener로 사용자 정의보기를 만들었습니다. OnTouchListener.onTouch는 다음과 달라집니다.

// has a touch press started?
private boolean touchStarted = false;
// co-ordinates of image
private int x, y;

public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    if (action == MotionEvent.ACTION_DOWN) {
        touchStarted = true;
    }
    else if (action == MotionEvent.ACTION_MOVE) {
        // movement: cancel the touch press
        touchStarted = false;

        x = event.getX();
        y = event.getY();

        invalidate(); // request draw
    }
    else if (action == MotionEvent.ACTION_UP) {
        if (touchStarted) {
            // touch press complete, show toast
            Toast.makeText(v.getContext(), "Coords: " + x + ", " + y, 1000).show();
        }
    }

    return true;
}

문제는 프레스가 예상대로 작동하지 않습니다. 왜냐하면 제가 아무렇게나 화면을 터치하면 약간의 움직임도 감지하고 터치 프레스를 취소하고 대신 이미지 주위를 움직이기 때문입니다.

나는 ACTION_DOWN에서 0으로 설정하고 MOVE를 새로운 증가 MOVE에서> = 3이면 내 "move"코드를 실행하는 변수 "mTouchDelay"를 도입하여 약간 "해킹"했습니다. 그러나 나는 아버지가 갈 길이 아니라고 느낍니다.

검색 누르는 것을 감지하는 방법도 찾지 못합니다. 범인은 실제로 트리거하는 것처럼 보이는 MOVE입니다.

내가 원하는 것의 예를 보려면 Android 애플리케이션 "DailyStrip"을 참조하십시오. 이 만화의 이미지를 보여줍니다. 화면에 비해 너무 큰 경우 드래그 할 수 있습니다. 한 번 탭하면 일부 컨트롤이 팝업되고 옵션 메뉴가 표시됩니다.

추신. 내 전화는 1.5에서만 실행되기 때문에 Android 1.5에서 작동하도록 노력하고 있습니다.


이 코드는 클릭과 이동 (끌기, 스크롤)을 구분할 수 있습니다. onTouchEvent에서 플래그 isOnClick을 설정하고 초기 X, Y 좌표는 ACTION_DOWN에 있습니다. ACTION_MOVE의 플래그를 지) (의도하지 않은 움직임이 종종 감지 됨 THRESHOLD const로 사용할 수 있음).

private float mDownX;
private float mDownY;
private final float SCROLL_THRESHOLD = 10;
private boolean isOnClick;

@Override
public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            mDownX = ev.getX();
            mDownY = ev.getY();
            isOnClick = true;
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            if (isOnClick) {
                Log.i(LOG_TAG, "onClick ");
                //TODO onClick code
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (isOnClick && (Math.abs(mDownX - ev.getX()) > SCROLL_THRESHOLD || Math.abs(mDownY - ev.getY()) > SCROLL_THRESHOLD)) {
                Log.i(LOG_TAG, "movement detected");
                isOnClick = false;
            }
            break;
        default:
            break;
    }
    return true;
}

위에서 제안한 LongPress의 경우 GestureDetector를 사용하면됩니다. 이 Q & A 확인 :

Android에서 누르기 감지


Android 문서에서-

onLongClick ()

View.OnLongClickListener에서. 이것은 사용자가 항목을 터치하고있을 때 (터치 모드에있을 때) 또는 탐색 키 또는 트랙볼로 항목에 초점을 맞추고 적절한 "엔터"키를 길게 누르거나 트랙볼을 누르고있을 때 호출됩니다 ( 1 초 동안).

onTouch ()

View.OnTouchListener에서. 이것은 사용자가 누르기, 놓기 또는 화면의 모든 이동 제스처 (항목 범위 내)를 포함하여 터치 이벤트로 한정된 작업을 수행 할 때 호출됩니다.

"터치해도 이동이 일어난다"는 델타를 설정하고 이동 코드를 킥하기 전에 뷰가 적어도 델타만큼 이동되었는지 확인합니다. 그렇지 않은 경우 터치 코드를 시작하십시오.


많은 실험 끝에 이것을 발견했습니다.

활동 초기화에서 :

setOnLongClickListener(new View.OnLongClickListener() {
  public boolean onLongClick(View view) {
    activity.openContextMenu(view);  
    return true;  // avoid extra click events
  }
});
setOnTouch(new View.OnTouchListener(){
  public boolean onTouch(View v, MotionEvent e){
    switch(e.getAction & MotionEvent.ACTION_MASK){
      // do drag/gesture processing. 
    }
    // you MUST return false for ACTION_DOWN and ACTION_UP, for long click to work
    // you can return true for ACTION_MOVEs that you consume. 
    // DOWN/UP are needed by the long click timer.
    // if you want, you can consume the UP if you have made a drag - so that after 
    // a long drag, no long-click is generated.
    return false;
  }
});
setLongClickable(true);

나는 비슷한 해결책을 찾고 있었고 이것이 내가 제안하는 것입니다. OnTouch 방식에서 MotionEvent.ACTION_DOWN 이벤트에 대한 시간을 기록한 다음 MotionEvent.ACTION_UP에 대해 시간을 다시 기록합니다. 이렇게하면 자신의 임계 값을 설정할 수도 있습니다. 몇 번의 실험을 마치면 최대 시간 (밀리 초)을 알 수 있습니다. 간단한 터치를 기록해야하며 원하는대로 이동 또는 다른 방법으로 사용할 수 있습니다.

이것이 도움이 되었기를 바랍니다. 다른 방법을 사용하고 문제를 해결했다면 의견을 보내주십시오.


클릭, 길게 누르기 및 스크롤 사이를 구분해야하는 경우 GestureDetector를 사용하세요.

활동 구현 GestureDetector.OnGestureListener

예를 들어 onCreate에서 감지기를 만듭니다.

mDetector = new GestureDetectorCompat(getActivity().getApplicationContext(),this);

그런 다음보기 (예 : webview)에서 선택적으로 setOnTouchListener를 설정합니다.

onTouch(View v, MotionEvent event) {
return mDetector.onTouchEvent(event);
}

이제 Override onScroll, onFling, showPress (긴 누름 감지) 또는 onSingleTapUp (클릭 감지)을 사용할 수 있습니다.


에 설명 된대로 난 당신이 GestureDetector.OnGestureListener을 구현해야한다고 생각 롱 터치, 더블 탭, 스크롤 또는 안드로이드에서 다른 터치 이벤트 감지 GestureDetector를 사용 하고 androidsnippets을 다음 onScroll 이벤트에 onSingleTapUp에서 탭 로직과 이동 로직을 구현


나는 longclick이 클릭 이벤트로 끝나지 않기를 바라 면서이 혼란을 처리하고있었습니다.

내가 한 일입니다.

public boolean onLongClick(View arg0) {
    Toast.makeText(getContext(), "long click", Toast.LENGTH_SHORT).show();
    longClicked = true;
    return false;
}

public void onClick(View arg0) {
    if(!longClicked){
        Toast.makeText(getContext(), "click", Toast.LENGTH_SHORT).show();
    }
    longClick = false; // sets the clickability enabled
}

boolean longClicked = false;

약간의 해킹이지만 작동합니다.


오버레이 클래스에 ontouch 이벤트가 필요했습니다. 이것을 확인하십시오.

http://mirnauman.wordpress.com/2012/04/16/android-google-maps-tutorial-part-6-getting-the-location-that-is-touched/


GestureDetector.SimpleOnGestureListener에는 다음 세 가지 경우에 도움이되는 메서드가 있습니다.

   GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {

        //for single click event.
        @Override
        public boolean onSingleTapUp(MotionEvent motionEvent) {
            return true;
        }

        //for detecting a press event. Code for drag can be added here.
        @Override
        public void onShowPress(MotionEvent e) {
            View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
            ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            ClipData clipData = ClipData.newPlainText("..", "...");
            clipboardManager.setPrimaryClip(clipData);

            ConceptDragShadowBuilder dragShadowBuilder = new CustomDragShadowBuilder(child);
            // drag child view.
            child.startDrag(clipData, dragShadowBuilder, child, 0);
        }

        //for detecting longpress event
        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
        }
    });

참고 URL : https://stackoverflow.com/questions/4324362/detect-touch-press-vs-long-press-vs-movement

반응형