อินพุตและเซ็นเซอร์

Android SDK ช่วยให้คุณเข้าถึงข้อมูลที่ป้อนและเซ็นเซอร์ต่างๆ ที่มาพร้อมกับ Glass EE2 หน้านี้แสดงภาพรวมเกี่ยวกับฟีเจอร์ รายละเอียดการใช้งาน และเคล็ดลับที่เป็นประโยชน์

ท่าทางแตะสัมผัส

คุณใช้ Android SDK เพื่อเปิดใช้การเข้าถึงข้อมูลดิบจากทัชแพดของ Glass ได้ ซึ่งทําได้โดยใช้ตัวตรวจจับท่าทางสัมผัสที่จะตรวจจับท่าทางสัมผัสทั่วไปใน Glass โดยอัตโนมัติ เช่น แตะ เลื่อน และเลื่อน

คุณสามารถใช้เครื่องมือตรวจจับท่าทางสัมผัสนี้ในแอปเพื่อดูการแตะ ปัดไปข้างหน้า ปัดกลับ และปัดลงได้ด้วย ซึ่งคล้ายกับอุปกรณ์ Glass ก่อนหน้านี้

การใช้ท่าทางสัมผัสเหล่านี้เป็นวิธีที่ดีที่สุด ดังนี้

  • แตะ: ยืนยันหรือป้อน
  • ปัดไปข้างหน้า ปัดกลับ: เลื่อนดูการ์ดและหน้าจอ
  • ปัดลง: กลับหรือออก

ดูรายละเอียดการใช้งานได้ในตัวอย่างตัวตรวจจับท่าทางสัมผัส

ตรวจจับท่าทางสัมผัสด้วยตัวตรวจจับท่าทางสัมผัสของ Android

Android GestureDetector ช่วยให้คุณตรวจหาท่าทางสัมผัสง่ายๆ และซับซ้อน เช่น ท่าทางสัมผัสที่ใช้นิ้วหลายนิ้วหรือการเลื่อน

ตรวจจับท่าทางสัมผัสระดับกิจกรรม

ตรวจจับท่าทางสัมผัสที่ระดับกิจกรรมเฉพาะเมื่อไม่สําคัญกับส่วนใดของ UI ที่สนใจ ตัวอย่างเช่น หากคุณต้องการเปิดเมนูเมื่อผู้ใช้แตะทัชแพด ไม่ว่าจะโฟกัสมุมมองใด ให้จัดการ MotionEvent ภายในกิจกรรม

ต่อไปนี้คือตัวอย่างการตรวจจับท่าทางสัมผัสระดับกิจกรรมที่ใช้ GestureDetector และใช้ GestureDetector.OnGestureListener เพื่อประมวลผลท่าทางสัมผัสที่รู้จัก ซึ่งจะมีการจัดการและแปลเป็นภาษาต่อไปนี้

  • TAP
  • SWIPE_FORWARD
  • SWIPE_BACKWARD
  • SWIPE_UP
  • SWIPE_DOWN

Kotlin

class GlassGestureDetector(context: Context, private val onGestureListener: OnGestureListener) :
    GestureDetector.OnGestureListener {

    private val gestureDetector = GestureDetector(context, this)

    enum class Gesture {
        TAP,
        SWIPE_FORWARD,
        SWIPE_BACKWARD,
        SWIPE_UP,
        SWIPE_DOWN
    }

    interface OnGestureListener {
        fun onGesture(gesture: Gesture): Boolean
    }

    fun onTouchEvent(motionEvent: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(motionEvent)
    }

    override fun onDown(e: MotionEvent): Boolean {
        return false
    }

    override fun onShowPress(e: MotionEvent) {}

    override fun onSingleTapUp(e: MotionEvent): Boolean {
        return onGestureListener.onGesture(Gesture.TAP)
    }

    override fun onScroll(
        e1: MotionEvent,
        e2: MotionEvent,
        distanceX: Float,
        distanceY: Float
    ): Boolean {
        return false
    }

    override fun onLongPress(e: MotionEvent) {}

    /**
     * Swipe detection depends on the:
     * - movement tan value,
     * - movement distance,
     * - movement velocity.
     *
     * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement
     * angle is only between 60 and 120 degrees.
     * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends
     * on deltaX value sign.
     *
     * ______________________________________________________________
     * |                     \        UP         /                    |
     * |                       \               /                      |
     * |                         60         120                       |
     * |                           \       /                          |
     * |                             \   /                            |
     * |  BACKWARD  <-------  0  ------------  180  ------>  FORWARD  |
     * |                             /   \                            |
     * |                           /       \                          |
     * |                         60         120                       |
     * |                       /               \                      |
     * |                     /       DOWN        \                    |
     * --------------------------------------------------------------
     */
    override fun onFling(
        e1: MotionEvent,
        e2: MotionEvent,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        val deltaX = e2.x - e1.x
        val deltaY = e2.y - e1.y
        val tan =
            if (deltaX != 0f) abs(deltaY / deltaX).toDouble() else java.lang.Double.MAX_VALUE

        return if (tan > TAN_60_DEGREES) {
            if (abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) {
                false
            } else if (deltaY < 0) {
                onGestureListener.onGesture(Gesture.SWIPE_UP)
            } else {
                onGestureListener.onGesture(Gesture.SWIPE_DOWN)
            }
        } else {
            if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) {
                false
            } else if (deltaX < 0) {
                onGestureListener.onGesture(Gesture.SWIPE_FORWARD)
            } else {
                onGestureListener.onGesture(Gesture.SWIPE_BACKWARD)
            }
        }
    }

    companion object {

        private const val SWIPE_DISTANCE_THRESHOLD_PX = 100
        private const val SWIPE_VELOCITY_THRESHOLD_PX = 100
        private val TAN_60_DEGREES = tan(Math.toRadians(60.0))
    }
}

Java

  public class GlassGestureDetector implements GestureDetector.OnGestureListener {

   enum Gesture {
     TAP,
     SWIPE_FORWARD,
     SWIPE_BACKWARD,
     SWIPE_UP,
     SWIPE_DOWN,
   }

   interface OnGestureListener {
     boolean onGesture(Gesture gesture);
   }

   private static final int SWIPE_DISTANCE_THRESHOLD_PX = 100;
   private static final int SWIPE_VELOCITY_THRESHOLD_PX = 100;
   private static final double TAN_60_DEGREES = Math.tan(Math.toRadians(60));

   private GestureDetector gestureDetector;
   private OnGestureListener onGestureListener;

   public GlassGestureDetector(Context context, OnGestureListener onGestureListener) {
     gestureDetector = new GestureDetector(context, this);
     this.onGestureListener = onGestureListener;
   }

   public boolean onTouchEvent(MotionEvent motionEvent) {
     return gestureDetector.onTouchEvent(motionEvent);
   }

   @Override
   public boolean onDown(MotionEvent e) {
     return false;
   }

   @Override
   public void onShowPress(MotionEvent e) {
   }

   @Override
   public boolean onSingleTapUp(MotionEvent e) {
     return onGestureListener.onGesture(Gesture.TAP);
   }

   @Override
   public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
     return false;
   }

   @Override
   public void onLongPress(MotionEvent e) {
   }

   /**
    * Swipe detection depends on the:
    * - movement tan value,
    * - movement distance,
    * - movement velocity.
    *
    * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement
    * angle is only between 60 and 120 degrees.
    * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends
    * on deltaX value sign.
    *
    *           ______________________________________________________________
    *          |                     \        UP         /                    |
    *          |                       \               /                      |
    *          |                         60         120                       |
    *          |                           \       /                          |
    *          |                             \   /                            |
    *          |  BACKWARD  <-------  0  ------------  180  ------>  FORWARD  |
    *          |                             /   \                            |
    *          |                           /       \                          |
    *          |                         60         120                       |
    *          |                       /               \                      |
    *          |                     /       DOWN        \                    |
    *           --------------------------------------------------------------
    */
   @Override
   public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
     final float deltaX = e2.getX() - e1.getX();
     final float deltaY = e2.getY() - e1.getY();
     final double tan = deltaX != 0 ? Math.abs(deltaY/deltaX) : Double.MAX_VALUE;

     if (tan > TAN_60_DEGREES) {
       if (Math.abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) {
         return false;
       } else if (deltaY < 0) {
         return onGestureListener.onGesture(Gesture.SWIPE_UP);
       } else {
         return onGestureListener.onGesture(Gesture.SWIPE_DOWN);
       }
     } else {
       if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) {
         return false;
       } else if (deltaX < 0) {
         return onGestureListener.onGesture(Gesture.SWIPE_FORWARD);
       } else {
         return onGestureListener.onGesture(Gesture.SWIPE_BACKWARD);
       }
     }
   }
  }

ตัวอย่างการใช้งาน

หากต้องการใช้การตรวจจับท่าทางสัมผัสระดับกิจกรรม คุณต้องทํางานต่อไปนี้ให้เสร็จ

  1. เพิ่มการประกาศต่อไปนี้ลงในไฟล์ Manifest ภายในการประกาศแอปพลิเคชัน วิธีนี้ช่วยให้ แอปได้รับ MotionEvent ในกิจกรรม
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
    
  2. ลบล้างเมธอด dispatchTouchEvent(motionEvent) ของกิจกรรมเพื่อส่งเหตุการณ์การเคลื่อนไหวไปยังเครื่องมือตรวจจับท่าทางสัมผัส onTouchEvent(motionEvent)
  3. นํา GlassGestureDetector.OnGestureListener มาใช้ในกิจกรรม

ตัวอย่างของเครื่องมือตรวจจับท่าทางสัมผัสระดับกิจกรรมมีดังต่อไปนี้

Kotlin

class MainAcvitiy : AppCompatActivity(), GlassGestureDetector.OnGestureListener {

    private lateinit var glassGestureDetector: GlassGestureDetector

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        glassGestureDetector = GlassGestureDetector(this, this)
    }

    override fun onGesture(gesture: GlassGestureDetector.Gesture): Boolean {
        when (gesture) {
            TAP ->
                // Response for TAP gesture
                return true
            SWIPE_FORWARD ->
                // Response for SWIPE_FORWARD gesture
                return true
            SWIPE_BACKWARD ->
                // Response for SWIPE_BACKWARD gesture
                return true
            else -> return false
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        return if (glassGestureDetector.onTouchEvent(ev)) {
            true
        } else super.dispatchTouchEvent(ev)
    }
}

Java

  public class MainActivity extends AppCompatActivity implements OnGestureListener {

   private GlassGestureDetector glassGestureDetector;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);

     glassGestureDetector = new GlassGestureDetector(this, this);
   }

   @Override
   public boolean onGesture(Gesture gesture) {
     switch (gesture) {
       case TAP:
         // Response for TAP gesture
         return true;
       case SWIPE_FORWARD:
         // Response for SWIPE_FORWARD gesture
         return true;
       case SWIPE_BACKWARD:
         // Response for SWIPE_BACKWARD gesture
         return true;
       default:
         return false;
     }
   }

   @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
     if (glassGestureDetector.onTouchEvent(ev)) {
       return true;
     }
     return super.dispatchTouchEvent(ev);
   }
  }

อินพุตเสียง

Glass Enterprise Edition 2 เป็นอุปกรณ์มาตรฐาน AOSP ที่รองรับแหล่งสัญญาณเสียงพื้นฐาน

แหล่งที่มาของเสียงต่อไปนี้มีการประมวลผลสัญญาณขั้นสูง

การจดจําเสียง

Glass Enterprise Edition 2 สนับสนุนการใช้ภาษาหลักสําหรับการจดจําคําพูด วิธีนี้รองรับเฉพาะภาษาอังกฤษเท่านั้น

รูปภาพการจดจําเสียงกระจก

UI การจดจําคําพูดกําลังรอให้ผู้ใช้พูดและส่งคืนข้อความที่ถอดเสียงหลังจากพูดเสร็จ หากต้องการเริ่มต้นกิจกรรม ให้ทําตามขั้นตอนต่อไปนี้

  1. โทรหา startActivityForResult() ด้วยความตั้งใจของ ACTION_RECOGNIZE_SPEECH ระบบรองรับฟีเจอร์จุดประสงค์พิเศษต่อไปนี้เมื่อคุณเริ่มกิจกรรม
  2. ลบล้างโค้ดเรียกกลับ onActivityResult() เพื่อรับข้อความที่ถอดเสียงจากจุดประสงค์พิเศษของ EXTRA_RESULTS ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้ ระบบจะเรียกใช้โค้ดเรียกกลับนี้เมื่อผู้ใช้พูดจบ

Kotlin

private const val SPEECH_REQUEST = 109

private fun displaySpeechRecognizer() {
    val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
    startActivityForResult(intent, SPEECH_REQUEST)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
        val results: List<String>? =
            data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
        val spokenText = results?.get(0)
        // Do something with spokenText.
    }
    super.onActivityResult(requestCode, resultCode, data)
}

Java

private static final int SPEECH_REQUEST = 109;

private void displaySpeechRecognizer() {
    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    startActivityForResult(intent, SPEECH_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent data) {
    if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
        List<String> results = data.getStringArrayListExtra(
                RecognizerIntent.EXTRA_RESULTS);
        String spokenText = results.get(0);
        // Do something with spokenText.
    }
    super.onActivityResult(requestCode, resultCode, data);
}