รากฐาน UX สําหรับเฟรมเวิร์กการสัมผัส

การปรับปรุงเฟรมเวิร์ก Android ทั้งหมดที่สร้างขึ้นเพื่อตอบสนองต่อการสัมผัสนั้นขับเคลื่อนโดยชุดหลักการ UX ที่พัฒนาไปพร้อมๆ กัน หลักการปัจจุบันเกี่ยวข้องกับการเปลี่ยนการสั่นที่ทำให้เกิดเสียงดังด้วยการโต้ตอบการสัมผัสที่ชัดเจน และการสำรวจการโต้ตอบการสัมผัสที่หลากหลาย

หลักการ UX

รูปที่ 1 หลักการปัจจุบัน

ตารางต่อไปนี้แสดงรายการ API การสัมผัสทั้งหมดที่ใช้ได้

API วิธีการและค่าคงที่ ปีเพิ่ม
android.view.HapticFeedbackConstants
  • CONTEXT_CLICK
  • CLOCK_TICK
  • VIRTUAL_KEY
  • KEYBOARD_TAP
  • LONG_PRESS
ก่อนปี 2016
  • KEYBOARD_PRESS
  • KEYBOARD_RELEASE
  • TEXT_HANDLE_MOVE
  • VIRTUAL_KEY_RELEASE
2017 (Android 8)
  • CONFIRM
  • REJECT
  • GESTURE_START
  • GESTURE_END
2020 (Android 11)
android.View
  • performHapticFeedback()
ก่อนปี 2016
android.os.Vibrator
  • vibrate()
  • hasVibrator()
ก่อนปี 2016
  • hasAmplitudeControl()
2017 (Android 8)
  • areAllEffectsSupported()
  • areAllPrimitivesSupported()
  • areEffectsSupported()
  • arePrimitivesSupported()
2020 (Android 11)
android.os.VibrationEffect
  • createOneShot()
  • createWaveform()
2017 (Android 8)
  • EFFECT_TICK
  • EFFECT_CLICK
  • EFFECT_HEAVY_CLICK
  • EFFECT_DOUBLE_CLICK
  • createPredefined()
2019 (Android 10)
android.os.VibrationEffect.Composition
  • PRIMITIVE_TICK
  • PRIMITIVE_CLICK
  • addPrimitive()
  • compose()
2020 (Android 11)
android.media.AudioAttributes.Builder
  • setHapticChannelsMuted()
2019 (Android 10)

การสั่นแบบสั่น

ตั้งแต่สมัยเพจเจอร์และฟีเจอร์โฟน เราได้ใช้การสั่นของมวลหมุนเยื้องศูนย์ (ERM) คุณภาพต่ำแต่ประหยัดพลังงานแบบใช้กริ่งแทนเสียงกริ่งในโหมดเงียบ องค์ประกอบฮาร์ดแวร์เดิมที่ทำให้เกิดเสียงดังและไม่พึงประสงค์อาจส่งผลเสียต่อ UX ของการสัมผัสด้วยการให้การแสดงผลคุณภาพต่ำ (เช่น โทรศัพท์ราคาถูกที่เสีย)

สัมผัสที่ชัดเจน

การสัมผัสที่ชัดเจนรองรับความรู้สึกของการเปลี่ยนแปลงสถานะแบบแยกต่างหาก (เช่น การเปลี่ยนแปลงแบบไบนารีระหว่างกระบวนการเปิดและปิด) ลักษณะของสิ่งกระตุ้นที่แยกต่างหากจะสร้างการสัมผัสที่ชัดเจนเป็นเอนทิตีเดียว (เช่น เอฟเฟกต์การสัมผัส 1 รายการต่อเหตุการณ์อินพุต 1 รายการ)

Android มุ่งมั่นที่จะมอบการสัมผัสที่ชัดเจนพร้อมความรู้สึกที่ชัดเจนแต่คมชัดแทนความรู้สึกที่ดังกึกก้องหรือคลุมเครือ

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

ใน HapticFeedbackConstants:

  • CLOCK_TICK
  • CONFIRM
  • CONTEXT_CLICK
  • GESTURE_END
  • GESTURE_START
  • KEYBOARD_PRESS
  • KEYBOARD_RELEASE
  • KEYBOARD_TAP
  • LONG_PRESS
  • REJECT
  • TEXT_HANDLE_MOVE
  • VIRTUAL_KEY
  • VIRTUAL_KEY_RELEASE

ใน VibrationEffect:

  • EFFECT_CLICK
  • EFFECT_DOUBLE_CLICK
  • EFFECT_HEAVY_CLICK
  • EFFECT_TICK

การสร้างความรู้ร่วมกันระหว่างผู้ผลิตอุปกรณ์และนักพัฒนาแอปเป็นกุญแจสำคัญในการยกระดับคุณภาพโดยรวมของการสัมผัสในระบบนิเวศ Android ใช้รายการตรวจสอบพื้นฐาน การประเมินฮาร์ดแวร์ และ CDD เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้งานการสัมผัส

กดแล้วปล่อย

รูปที่ 2 การกดและปล่อย

การโต้ตอบการสัมผัสที่หลากหลาย

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

การโต้ตอบการสัมผัสที่หลากหลาย

รูปที่ 3 ระบบสัมผัสที่สมจริงพร้อมพื้นผิวแบบเลื่อน

การลากและการปัด

รูปที่ 4 การลากและการปัด

กรณีการใช้งาน 1: พื้นผิวแบบเลื่อน

หากระบบแสดงผลสัมผัสซ้ำขณะที่นิ้วเลื่อนไปบนพื้นผิวการสัมผัส (เช่น การลาก การปัด การสำรวจพื้นผิวด้วยพื้นผิวสัมผัสจำลอง) เอฟเฟกต์สัมผัสที่แสดงซ้ำควรมีความคมชัดและละเอียด

หากเอฟเฟกต์แต่ละรายการมีเสียงอู้อี้แทนที่จะคมชัด ระยะห่างระหว่างการทำซ้ำก็อาจถูกลบออก ผลลัพธ์ที่ได้คือเสียงกริ่งยาวๆ แทนที่จะเป็นสัญญาณแบบแยกหลายรายการ

หากความกว้างของคลื่นไม่ละเอียดพอ พลังงานสัมผัสที่รับรู้จะเพิ่มขึ้นเรื่อยๆ จากการซ้ำกัน ส่งผลให้เกิดความรู้สึกสัมผัสที่รุนแรงมากเมื่อสิ้นสุดการซ้ำ

ใช้พื้นผิวสัมผัสของอุปกรณ์สำหรับท่าทางสัมผัสการปัดและการลาก

ใช้ CLOCK_TICK และ TEXT_HANDLE_MOVE ใน HapticFeedbackConstants ค่าคงที่เหล่านี้จะกำหนดลักษณะของการซ้ำและระดับความสูงไว้ล่วงหน้า

สร้างเอฟเฟกต์ของคุณเอง

หากต้องการสร้างเอฟเฟกต์ของคุณเอง ให้เขียนการออกแบบโดยต่อเรียงPRIMITIVE_CLICKและPRIMITIVE_TICKใน VibrationEffect.Composition คุณปรับลักษณะของการทำซ้ำและมาตราส่วนแอมพลิจูดได้โดยใช้ addPrimitive(int primitiveID, float scale, int delay) การรองรับจะขึ้นอยู่กับความสามารถของ CAP_COMPOSE_EFFECTS ของอินเทอร์เฟซ HAL ของมอเตอร์สั่น

กรณีการใช้งานที่ 2: การสั่นนานที่มีเอฟเฟกต์เบาลง

การสั่นเป็นเวลานานคือการสั่นด้วยความถี่ที่ราบรื่นซึ่งเปลี่ยนจาก 0 เป็นความถี่เป้าหมาย การสั่นเป็นเวลานานสามารถสร้างการสัมผัสที่รับรู้ได้ อย่างไรก็ตาม การสั่นนานๆ อย่างฉับพลันอาจทำให้ผู้ใช้ตกใจเมื่ออยู่ในสภาพแวดล้อมที่เงียบ และมักจะทำให้เกิดเสียงสั่นที่ได้ยินได้ หากต้องการให้การสั่นเป็นเวลานานน่าพอใจยิ่งขึ้น ให้ใช้เอฟเฟกต์การค่อยๆ เพิ่มขึ้นในช่วงเริ่มต้นของการสั่นเป็นเวลานาน วิธีนี้จะทำให้ความกว้างของพัลส์เปลี่ยนอย่างราบรื่นเพื่อเพิ่มความกว้างของพัลส์เป้าหมาย

ใช้เอฟเฟกต์การค่อยๆ เพิ่มระดับ

  1. ตรวจสอบความสามารถของฮาร์ดแวร์ในการควบคุมแอมพลิจูดด้วย android.os.Vibrator.hasAmplitudeControl()

    • ผลลัพธ์ต้องเป็น true เพื่อให้เกิดเอฟเฟกต์ค่อยๆ ดังขึ้นพร้อมด้วยระดับความดังที่เปลี่ยนแปลง
  2. ใช้ VibrationEffectcreateWaveform(timings[], amplitudes[], int repeat)

  3. ปรับชุด timings[] และ amplitudes[] เพื่อสร้างเส้นโค้งการเริ่มต้นอย่างช้าๆ ดังที่แสดงในรูปที่ 5

การสั่นเป็นเวลานาน

รูปที่ 5 เส้นโค้งการเริ่มการสั่นแบบยาว

กรณีการใช้งาน 3: การโต้ตอบการสัมผัสที่เชื่อมโยงกับเสียง

การสัมผัสที่เชื่อมโยงกับเสียงคือรูปแบบการสัมผัสที่เชื่อมโยงกับจังหวะของเสียงเพื่อดึงดูดความสนใจของผู้ใช้

ประโยชน์ของการสัมผัสที่เชื่อมโยงกับเสียง

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

คุณควรพิจารณารูปแบบจังหวะของความรู้สึก หากไม่มีความรู้สึกถึงจังหวะ ผู้ใช้จะรับรู้ถึงความรู้สึกสัมผัสเป็นการสั่นแบบสุ่ม และมักจะไม่สนใจ

คู่เสียง

รูปที่ 6 ตัวอย่างการสัมผัสที่จับคู่กับเสียง

การโต้ตอบการสัมผัสที่เชื่อมโยงกับเสียง: เคล็ดลับในการใช้งาน

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

  • ใช้คลาส MediaPlayer หรือ SoundPool

    • เนื้อหาในรูปแบบ OGG ที่มีคีย์ข้อมูลเมตาพิเศษ (ANDROID_HAPTIC ตามด้วยจำนวนช่องสัมผัส) จะบ่งบอกถึงการมีข้อมูลการสัมผัสและการเล่นด้วย MediaPlayer และ SoundPool
  • ระบุการรองรับการสัมผัสและการสตรีมเสียงใน audio_policy_configuration.xml

    • ใช้โปรไฟล์เอาต์พุตกับแชแนลการโต้ตอบการสัมผัส AUDIO_CHANNEL_OUT_HAPTIC_A|B
    • สำหรับสตรีมเอาต์พุตที่มีแชแนลการสัมผัส โปรดทราบว่าแชแนลการสัมผัสจะแสดงเป็นแชแนลเพิ่มเติมในข้อมูล

    ตัวอย่าง

    หากมาสก์ช่องสำหรับสตรีมเอาต์พุตมีลักษณะดังนี้

    AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A

    จากนั้นตัวอย่างเพลงทั้งหมดควรมีลักษณะดังนี้

    AUDIO_LEFT_CHANNEL,AUDIO_RIGHT_CHANNEL,HAPTIC_CHANNEL_A

  • เปลี่ยน AudioAttributes.Builder( ).setHapticChannelsMuted(boolean muted) เป็น false เพื่อเล่นแชแนลการสัมผัส

    • โดยค่าเริ่มต้น ช่องการสัมผัสจะปิดเสียง (true)
    • กรณีการใช้งาน ได้แก่ เสียงเรียกเข้าและเสียง UI ที่มีรีแอ็กชันการสัมผัสและการตอบกลับแบบซิงค์
  • HAL ของมอเตอร์สั่นต้องรองรับการควบคุมภายนอก

การโต้ตอบการสัมผัสที่เชื่อมโยงกับเสียง

รูปที่ 7 การใช้การสัมผัสที่จับคู่กับเสียง

การโต้ตอบการสัมผัสที่เชื่อมโยงกับเสียง: HapticGenerator

HapticGenerator เป็นเอฟเฟกต์เสียงที่เปิดตัวใน Android 12 ซึ่งสามารถสร้างข้อมูลการสัมผัสได้จากแชแนลเสียงและเล่นแบบเรียลไทม์เป็นการสัมผัสที่เชื่อมโยงกับเสียง ระบบจะใช้เอฟเฟกต์กับ AudioTrack ดังที่แสดงในรูปที่ 8

สถาปัตยกรรมของ Haptic Generator

รูปที่ 8 สถาปัตยกรรมของ Haptic Generator

ภาพแสดงสถาปัตยกรรมนี้แสดงตําแหน่งที่ตัวสร้างการสัมผัสใช้กับสตรีมเสียงที่ผู้ใช้ส่งเข้ามาก่อนที่จะส่งไปยัง Audio HAL ระบบจะใช้เครื่องกำเนิดหลังจาก AudioMixer แยกข้อมูลเสียงและข้อมูลการสัมผัส และก่อนใช้เอฟเฟกต์เสียงอื่นๆ และเอาต์พุตของเครื่องกำเนิดจะลบล้างข้อมูลการสัมผัสก่อนหน้าในสตรีม

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

  • ความถี่เรโซแนนซ์ของตัวกรองย่านความถี่กลาง

    ความถี่เรโซแนนซ์ของไวเบรเตอร์คือความถี่ที่ตัวกระตุ้นการสัมผัสมีเอาต์พุตสูงสุด พารามิเตอร์นี้จะปรับตัวต้านการตอบกลับเพื่อทำให้ฟังก์ชันการโอนการตอบสนองแบนลงบางส่วนเพื่อให้ได้แบนด์วิดท์ที่กว้างขึ้น เฟรมเวิร์ก Android จะลิงก์ค่านี้กับเอาต์พุตของวิธี HAL ของ IVibrator.getResonantFrequency ตัวสั่นโดยอัตโนมัติ

    ค่าเริ่มต้นของพารามิเตอร์นี้คือ 150 Hz คุณสามารถแก้ไขค่านี้ได้ในโค้ด

  • กำลังการทำให้เป็นไปตามมาตรฐานสำหรับโหมดช้า

    พารามิเตอร์นี้กำหนดตัวคูณในการทำให้เป็นมาตรฐานบางส่วน (การควบคุมอัตราขยายอัตโนมัติ) ค่าเริ่มต้นคือ -0.8 ซึ่งหมายความว่าขั้นตอนการควบคุมอัตราขยายนี้จะนำความแปรปรวนของช่วงไดนามิกออก 80% คุณแก้ไขข้อมูลนี้ได้ในโค้ด

  • ปัจจัย Q สำหรับตัวกรองย่านความถี่

    ปัจจัยคุณภาพของไวเบรเตอร์ (Q factor) กำหนดโดยพารามิเตอร์ 2 รายการ ได้แก่

    • Q ของศูนย์ ซึ่งเป็นปัจจัยคุณภาพของศูนย์ในตัวกรองย่านความถี่ที่ตัดที่ยกเลิกการสั่นพ้องบางส่วน

    • Q ของขั้ว ซึ่งเป็นปัจจัยคุณภาพของขั้วในตัวกรองย่านความถี่ที่หยุด

    อัตราส่วนของค่า 2 ค่าดังกล่าวจะจำกัดการลดการสะท้อนเพื่อเพิ่มย่านความถี่ต่ำและขยายการตอบสนองของอัลกอริทึม ตัวอย่างเช่น ค่าเริ่มต้น 8 สำหรับ Q ของศูนย์และ 4 สำหรับ Q ของขั้วจะให้อัตราส่วน 2 ซึ่งจำกัดการลดการสะท้อนด้วยปัจจัย 2 (6 dB) เฟรมเวิร์ก Android จะลิงก์ทั้ง 2 ค่ากับเอาต์พุตของเมธอด HAL ของ Vibrator IVibrator.getQFactor

    หากค่าเริ่มต้นไม่ได้คำนึงถึงกำลังของมอเตอร์ที่ลดลงในอุปกรณ์ เราขอแนะนำให้แก้ไขทั้ง 2 ค่าพร้อมกัน โดยเพิ่มหรือลดทั้ง 2 ค่า อัตราส่วนของ Q ที่จุด 0 กับ Q ที่จุดยอดควรมากกว่า 1 คุณแก้ไขข้อมูลนี้ได้ในโค้ด

  • ความถี่มุมสำหรับการบิดเบือน

    ความถี่มุมจะใช้กับตัวกรอง Low Pass ที่ช่วยลดการสั่นในระดับต่ำและเพิ่มระดับที่สูงขึ้นโดยใช้การบิดเบือนแบบลูกบาศก์ โดยค่าเริ่มต้นจะเป็น 300 Hz คุณสามารถแก้ไขค่านี้ได้ในโค้ด

  • อัตราขยายอินพุตและเกณฑ์คิวบ์สำหรับความผิดเพี้ยน

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

    • ค่าเริ่มต้นของปัจจัยการขยายสัญญาณอินพุตคือ 0.3
    • ค่าเริ่มต้นของเกณฑ์คิวบ์คือ 0.1

    เราขอแนะนําให้แก้ไขทั้ง 2 ค่าพร้อมกัน โดยสามารถดูได้ในโค้ด

    ดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันที่ใช้โดยตัวกรองนี้ได้ที่การใช้งานในโค้ด

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

  • อัตราขยายเอาต์พุตสำหรับความผิดเพี้ยน

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

    หากการสั่นเบาเกินไป ให้เพิ่มค่า หากได้ยินเสียงฮัดแดดของฮาร์ดแวร์ตัวกระตุ้น ให้ลดค่า