触摸手势

借助 Android SDK,可以通过 Glass 触控板访问原始数据。

不过,GDK 提供了一个手势检测器,可以自动检测 Glass 上的常用手势,包括点按、滑动和滚动。

此外,默认情况下,简单的手势会转换为方向键事件,以便在不使用手势检测器的情况下轻松处理。

将手势检测为方向键按键事件

默认情况下,Glass 系统会将简单的手势转换为方向键按键事件。这样,您就可以监听 activity 或视图上的 onKeyDown()onKeyUp() 事件,以将以下手势作为方向键处理:

以下代码段可检测用户何时点按触控板:

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。如果用户在视图获得焦点的情况下点按触控板(转换为方向键中间的按钮点击操作),视图可以通过 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
    }
}

使用手势检测器检测手势

借助手势检测器,您可以检测简单的手势以及更复杂的手势,例如需要使用多根手指或滚动的手势。复杂的手势没有对应的方向键。

GestureDetector 提供了监听器接口,您可以实现该接口来接收手势通知。

检测 activity 级手势

如果您并不在意界面的哪个部分具有焦点,可以在 activity 级别检测手势。例如,如果您希望在用户点按触控板时弹出菜单(无论焦点为哪个视图),则应处理 activity 内的 MotionEvent

下面的示例:

  1. 创建 GestureDetector,用于实现监听器来处理识别出的手势。
  2. 替换 activity 的 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;
    }
}