터치 동작

Android 터치 스크린을 사용하면 Glass 터치패드에서 원시 데이터에 액세스할 수 있습니다.

하지만 GDK는 탭, 스와이프, 스크롤 등 Glass에서 일반적인 동작을 자동으로 감지하는 동작 동작을 제공합니다.

또한 간단한 동작은 동작 감지기를 사용하지 않고도 쉽게 처리할 수 있도록 기본적으로 D패드 이벤트로 변환됩니다.

동작을 D패드 키 이벤트로 감지

기본적으로 Glass 시스템은 간단한 동작을 D패드 키 이벤트로 변환합니다. 이렇게 하면 활동 또는 뷰의 onKeyDown()onKeyUp() 이벤트를 수신 대기하여 다음 동작을 D패드 키로 처리할 수 있습니다.

다음 스니펫은 사용자가 터치패드를 탭할 때 이를 감지합니다.

public class MyActivity extends Activity {
    ...
    @Override
    public boolean onKeyDown(int keycode, KeyEvent event) {
        if (keycode == KeyEvent.KEYCODE_DPAD_CENTER) {
            // user tapped touchpad, do something
            return true;
        }
        ...
        return super.onKeyDown(keycode, event);
    }
}

개별 뷰에서 탭을 감지하는 메서드는 뷰에 OnClickListener를 구현하는 것입니다. 사용자가 뷰에 포커스가 있는 터치패드 (D패드 중앙 버튼 클릭으로 변환됨)를 탭하면 뷰에서 OnClickListener를 사용하여 이벤트를 처리할 수 있습니다.

public final class MyActivity extends Activity implements OnClickListener {

    View cardView;

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        cardView = new Card(this).setText("Tap to carry out an action").getView();
        // To receive touch events from the touchpad, the view should be focusable.
        cardView.setOnClickListener(this);
        cardView.setFocusable(true);
        cardView.setFocusableInTouchMode(true);
        setContentView(cardView);
    }

    @Override
    protected void onResume() {
        // To receive touch events from the touchpad, the view should have focus.
        cardView.requestFocus();
        super.onResume();
    }

    @Override
    public void onClick(View v) {
        // perform desired action
    }
}

동작 감지기로 동작 감지

동작 감지기를 사용하면 간단한 동작뿐 아니라 여러 손가락이나 스크롤을 사용하는 동작과 같은 좀 더 복잡한 동작을 감지할 수 있습니다. 복잡한 동작에는 해당하는 D패드 키가 없습니다.

GestureDetector동작에 대한 알림을 받도록 구현할 수 있는 리스너 인터페이스를 제공합니다.

활동 수준 동작 감지

UI의 어느 부분에 포커스가 있는지 중요하지 않은 경우 활동 수준에서 동작을 감지하는 것이 적절합니다. 예를 들어 사용자가 터치패드를 탭할 때 어떤 뷰에 포커스가 있는지와 상관없이 메뉴를 불러오려면 활동 내에서 MotionEvent를 처리합니다.

예를 들면 다음과 같습니다.

  1. 인식된 동작을 처리하기 위해 리스너를 구현하는 GestureDetector를 만듭니다.
  2. 활동의 onGenericMotionEvent() 메서드를 재정의하여 모션 이벤트를 동작 감지기의 onMotionEvent() 메서드에 전달합니다.

모션 이벤트가 발생하면 시스템이 이를 모션 감지기에 전달합니다. 동작 감지기가 인식되면 적절한 리스너에게 이벤트를 처리하도록 알립니다.

public class MainActivity extends Activity {
    private GestureDetector mGestureDetector;
    // ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        mGestureDetector = createGestureDetector(this);
    }

    private GestureDetector createGestureDetector(Context context) {
    GestureDetector gestureDetector = new GestureDetector(context);
        //Create a base listener for generic gestures
        gestureDetector.setBaseListener( new GestureDetector.BaseListener() {
            @Override
            public boolean onGesture(Gesture gesture) {
                if (gesture == Gesture.TAP) {
                    // do something on tap
                    return true;
                } else if (gesture == Gesture.TWO_TAP) {
                    // do something on two finger tap
                    return true;
                } else if (gesture == Gesture.SWIPE_RIGHT) {
                    // do something on right (forward) swipe
                    return true;
                } else if (gesture == Gesture.SWIPE_LEFT) {
                    // do something on left (backwards) swipe
                    return true;
                }
                return false;
            }
        });
        gestureDetector.setFingerListener(new GestureDetector.FingerListener() {
            @Override
            public void onFingerCountChanged(int previousCount, int currentCount) {
              // do something on finger count changes
            }
        });
        gestureDetector.setScrollListener(new GestureDetector.ScrollListener() {
            @Override
            public boolean onScroll(float displacement, float delta, float velocity) {
                // do something on scrolling
            }
        });
        return gestureDetector;
    }

    /*
     * Send generic motion events to the gesture detector
     */
    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        if (mGestureDetector != null) {
            return mGestureDetector.onMotionEvent(event);
        }
        return false;
    }
}

뷰 수준 동작 감지

포커스가 있는 뷰에 따라 다른 작업을 하려는 경우 뷰 수준에서 동작을 감지하는 것이 적합합니다.

예를 들면 다음과 같습니다.

  1. dispatchGenericFocusedEvent() 메서드를 재정의하는 맞춤 뷰를 만듭니다. 모션 이벤트가 발생하면 이 메서드는 모션 이벤트를 동작 감지기에 전달합니다.
  2. 뷰에 포커스가 있을 때 이벤트를 감지하도록 뷰를 포커스 가능으로 선언합니다.
  3. 인식된 동작을 처리하기 위해 리스너를 구현하는 GestureDetector를 만듭니다.

뷰에 포커스가 있을 때 동작 감지기가 모션을 인식하면 동작 감지기가 적절한 리스너를 호출합니다.

/**
 * TextView that handles touchpad input (currently only TAP).
 */
public class TouchpadHandlingTextView extends TextView
        implements OnAttachStateChangeListener{

    private final GestureDetector mTouchDetector;

    public TouchpadHandlingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchDetector = createGestureDetector(context);
        // must set the view to be focusable
        setFocusable(true);
        setFocusableInTouchMode(true);
    }

    public TouchpadHandlingTextView(Context context) {
        this(context, null);
    }

    @Override
    public void onViewAttachedToWindow(View v) {
        requestFocus();
    }

    @Override
    public void onViewDetachedFromWindow(View v) {
    }

    /**
     * Pass a MotionEvent into the gesture detector
     */
    @Override
    public boolean dispatchGenericFocusedEvent(MotionEvent event) {
        if (isFocused()) {
            return mTouchDetector.onMotionEvent(event);
        }
        return super.dispatchGenericFocusedEvent(event);
    }

    /**
     * Create gesture detector that triggers onClickListener. Implement
     * onClickListener in your Activity and override
     * onClick() to handle the "tap" gesture.
     */
    private GestureDetector createGestureDetector(Context context) {
        GestureDetector gd = new GestureDetector(context);
        gd.setBaseListener(new GestureDetector.BaseListener() {

            @Override
            public boolean onGesture(Gesture gesture) {
                if (gesture == Gesture.TAP) {
                    return performClick();
                }
                return false;
            }
        });
        return gd;
    }
}