ภาพรวมของเหตุการณ์อินพุต

ลองใช้วิธีการเขียน
Jetpack Compose เป็นชุดเครื่องมือ UI ที่แนะนำสำหรับ Android ดูวิธีใช้การแตะและการป้อนข้อมูลในการเขียน

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

ภายในคลาส View ต่างๆ ที่คุณจะใช้ในการเขียนเลย์เอาต์ คุณอาจสังเกตเห็นการเรียกกลับแบบสาธารณะหลายรายการ ที่ดูมีประโยชน์สำหรับเหตุการณ์ UI เฟรมเวิร์กของ Android จะเรียกวิธีการเหล่านี้เมื่อ การดำเนินการที่เกี่ยวข้องจะเกิดขึ้นกับออบเจ็กต์นั้น ตัวอย่างเช่น เมื่อแตะมุมมอง (เช่น ปุ่ม) มีการเรียกใช้เมธอด onTouchEvent() ในออบเจ็กต์นั้น อย่างไรก็ตาม หากต้องการขัดขวางปัญหานี้ คุณต้องขยายระยะเวลาต่อไปนี้ คลาสและลบล้างเมธอด อย่างไรก็ตาม การขยายออบเจ็กต์ View ทั้งหมด ในการรับมือกับเหตุการณ์แบบนั้น จะไม่สามารถดำเนินการได้ และนี่คือเหตุผลที่คลาส View มี คอลเล็กชันของอินเทอร์เฟซที่ซ้อนกันที่มี Callback ซึ่งคุณสามารถกำหนดได้ง่ายขึ้น อินเทอร์เฟซเหล่านี้ ที่เรียกว่า Listener เหตุการณ์ เป็นตั๋วของคุณในการบันทึกการโต้ตอบของผู้ใช้กับ UI ของคุณ

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

Listener เหตุการณ์

Listener เหตุการณ์เป็นอินเทอร์เฟซในชั้นเรียน View ที่มีแท็กเดียว Callback Method เฟรมเวิร์กของ Android จะเรียกวิธีการเหล่านี้เมื่อ "มุมมอง" ที่ผู้ฟังเห็น ได้รับการลงทะเบียนเมื่อการโต้ตอบของผู้ใช้กับรายการใน UI

วิธีการเรียกกลับที่รวมอยู่ในอินเทอร์เฟซ Listener เหตุการณ์มีดังนี้

onClick()
จาก View.OnClickListener โดยจะมีการเรียกเมื่อผู้ใช้แตะรายการ (เมื่ออยู่ในโหมดสัมผัส) หรือโฟกัสที่รายการด้วยแป้นนำทางหรือแทร็กบอล และ กด "Enter" ที่เหมาะสม หรือกดแทร็กบอลลง
onLongClick()
จาก View.OnLongClickListener ระบบจะเรียกตัวเลือกนี้เมื่อผู้ใช้แตะและค้างไว้ (เมื่ออยู่ในโหมดสัมผัส) หรือ โฟกัสที่รายการโดยใช้แป้นนำทางหรือแทร็กบอล และ ให้กด "Enter" ที่เหมาะสมค้างไว้ หรือกดแทร็กบอลค้างไว้ (เป็นเวลา 1 วินาที)
onFocusChange()
จาก View.OnFocusChangeListener โดยวิธีนี้เรียกว่าเมื่อผู้ใช้ไปยังส่วนต่างๆ ไปยังหรือออกจากรายการดังกล่าว โดยใช้แป้นนำทางหรือแทร็กบอล
onKey()
จาก View.OnKeyListener โดยระบบจะเรียกการดำเนินการนี้เมื่อผู้ใช้โฟกัสที่รายการดังกล่าว และกดหรือปล่อยคีย์ฮาร์ดแวร์ในอุปกรณ์
onTouch()
จาก View.OnTouchListener วิธีนี้เรียกว่าเมื่อผู้ใช้ดำเนินการที่มีคุณสมบัติเป็นกิจกรรมการแตะ ซึ่งได้แก่ ข่าว ข่าวประชาสัมพันธ์ หรือท่าทางสัมผัสการเคลื่อนไหวใดๆ บนหน้าจอ (ภายในขอบเขตของรายการ)
onCreateContextMenu()
จาก View.OnCreateContextMenuListener ซึ่งจะเรียกว่าเมื่อมีการสร้างเมนูตามบริบท (เป็นผลมาจาก "การคลิกนานเป็นเวลานาน") ดูการสนทนา บนเมนูตามบริบทในเมนู คู่มือนักพัฒนาซอฟต์แวร์

วิธีการเหล่านี้เป็นผู้อยู่อาศัยคนเดียวในอินเทอร์เฟซที่เกี่ยวข้อง หากต้องการกำหนดหนึ่งในวิธีเหล่านี้ และจัดการกิจกรรมของคุณ ติดตั้งอินเทอร์เฟซที่ซ้อนกันในกิจกรรม หรือกำหนดเป็นคลาสที่ไม่ระบุตัวตน จากนั้น ส่งตัวอย่างการติดตั้งใช้งาน ลงในเมธอด View.set...Listener() ที่เกี่ยวข้อง (เช่น การโทร setOnClickListener() และส่งต่อการใช้งาน OnClickListener ของคุณ)

ตัวอย่างด้านล่างแสดงวิธีลงทะเบียน Listener เมื่อคลิกสำหรับปุ่ม

Kotlin

protected void onCreate(savedValues: Bundle) {
    ...
    val button: Button = findViewById(R.id.corky)
    // Register the onClick listener with the implementation above
    button.setOnClickListener { view ->
        // do something when the button is clicked
    }
    ...
}

Java

// Create an anonymous implementation of OnClickListener
private OnClickListener corkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(corkyListener);
    ...
}

นอกจากนี้ คุณอาจพบว่าการใช้ OnClickListener เป็นส่วนหนึ่งของกิจกรรมของคุณจะสะดวกกว่า วิธีนี้จะช่วยหลีกเลี่ยงภาระงานของคลาสและการจัดสรรออบเจ็กต์เพิ่มเติม เช่น

Kotlin

class ExampleActivity : Activity(), OnClickListener {
  
    protected fun onCreate(savedValues: Bundle) {
        val button: Button = findViewById(R.id.corky)
        button.setOnClickListener(this)
    }

    // Implement the OnClickListener callback
    fun onClick(v: View) {
        // do something when the button is clicked
    }
}

Java

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

โปรดสังเกตว่า Callback onClick() ในตัวอย่างด้านบนมี ไม่มีค่าที่แสดงผล แต่เมธอด Listener เหตุการณ์อื่นๆ บางเมธอดจะต้องแสดงผลบูลีน เหตุผล ขึ้นอยู่กับเหตุการณ์ เนื่องจากเหตุผล 2-3 รายการต่อไปนี้

  • onLongClick() - การดำเนินการนี้จะแสดงผลบูลีนเพื่อบ่งบอกว่าคุณได้ใช้เหตุการณ์แล้วและไม่ควรใช้งานต่อ กล่าวคือ ให้คืนค่า true เพื่อระบุว่าคุณได้จัดการเหตุการณ์แล้ว และเหตุการณ์ควรหยุดที่นี่ แสดงผล false หากคุณยังไม่ได้จัดการ และ/หรือเหตุการณ์ควรดำเนินการต่อไปยัง เมื่อคลิก Listener ของคุณ
  • onKey() - การดำเนินการนี้จะแสดงผลบูลีนเพื่อบ่งบอกว่าคุณได้ใช้เหตุการณ์แล้วและไม่ควรใช้งานต่อ กล่าวคือ ให้คืนค่า true เพื่อระบุว่าคุณได้จัดการเหตุการณ์แล้ว และเหตุการณ์ควรหยุดที่นี่ แสดงผล false หากคุณยังไม่ได้จัดการ และ/หรือเหตุการณ์ควรดำเนินการต่อไปยัง ผู้ฟังที่ไม่คุ้นเคย
  • onTouch() - การดำเนินการนี้จะแสดงผลบูลีนเพื่อระบุว่า Listener ของคุณใช้เหตุการณ์นี้หรือไม่ สิ่งสำคัญก็คือ กิจกรรมนี้อาจมีการกระทำหลายอย่างเกิดขึ้นพร้อมกัน ดังนั้นถ้าคุณแสดงผล false เมื่อเมธอด ได้รับเหตุการณ์การดำเนินการดาวน์ เป็นการระบุว่าคุณยังไม่เคยใช้เหตุการณ์และ ไม่สนใจการดำเนินการที่ตามมาจากกิจกรรมนี้ ดังนั้น เราจะไม่ขอให้คุณดำเนินการใดๆ เพิ่มเติม ภายในเหตุการณ์ เช่น ท่าทางสัมผัสแบบนิ้ว หรือเหตุการณ์การทำงานในตอนท้าย

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

นอกจากนี้ เมื่อนึกถึงการป้อนข้อความสำหรับแอปพลิเคชัน ให้ระลึกไว้เสมอว่าอุปกรณ์จำนวนมากมีเพียงอินพุตซอฟต์แวร์เท่านั้น วิธีการดังกล่าวไม่จำเป็นต้องอิงตามคีย์ บางคนอาจใช้การป้อนข้อมูลด้วยเสียง การเขียนด้วยลายมือ และอื่นๆ แม้ว่า วิธีการป้อนข้อมูลมีอินเทอร์เฟซที่เหมือนแป้นพิมพ์ ซึ่งโดยทั่วไปจะไม่ทริกเกอร์ กลุ่มเหตุการณ์ onKeyDown() กลุ่ม คุณไม่ควร สร้าง UI ที่จำเป็นต้องควบคุมการกดแป้นเฉพาะ เว้นแต่คุณต้องการจำกัดแอปพลิเคชันไว้เฉพาะอุปกรณ์ ด้วยแป้นพิมพ์ที่เป็นฮาร์ดแวร์ โดยเฉพาะอย่างยิ่ง โปรดอย่าใช้วิธีการเหล่านี้เพื่อตรวจสอบความถูกต้องของอินพุตเมื่อผู้ใช้กด คีย์การคืนสินค้า ให้ใช้การดำเนินการ เช่น IME_ACTION_DONE แทนเพื่อส่งสัญญาณ วิธีการป้อนข้อมูลว่าแอปพลิเคชันของคุณคาดว่าจะตอบสนองอย่างไร ซึ่งอาจเป็นการเปลี่ยนแปลง UI ไปในทางที่สำคัญ หลีกเลี่ยงสมมติฐาน ว่าวิธีการป้อนข้อมูลของซอฟต์แวร์ควรทำงานอย่างไร และเพียงแค่วางใจให้วิธีการนั้นจัดหาข้อความที่จัดรูปแบบแล้วให้กับแอปพลิเคชันของคุณ

หมายเหตุ: Android จะเรียกใช้เครื่องจัดการเหตุการณ์ก่อน แล้วจึงเรียกใช้ค่าเริ่มต้นที่เหมาะสม จากคำจำกัดความคลาสเป็นอันดับที่ 2 ด้วยเหตุนี้ การแสดงผล true จาก Listener เหตุการณ์เหล่านี้จะหยุด การเผยแพร่เหตุการณ์ไปยัง Listener เหตุการณ์อื่นๆ และจะบล็อก Callback ไปยัง เครื่องจัดการเหตุการณ์เริ่มต้นในมุมมอง ดังนั้นโปรดแน่ใจว่าต้องการสิ้นสุดเหตุการณ์เมื่อคืนค่า true

เครื่องจัดการกิจกรรม

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

  • onKeyDown(int, KeyEvent) - เรียกใช้เมื่อมีเหตุการณ์สำคัญใหม่
  • onKeyUp(int, KeyEvent) - เรียกใช้เมื่อมีเหตุการณ์สำคัญเกิดขึ้น
  • onTrackballEvent(MotionEvent) - เรียกใช้เมื่อเกิดเหตุการณ์การเคลื่อนไหวของแทร็กบอล
  • onTouchEvent(MotionEvent) - เรียกใช้เมื่อเกิดเหตุการณ์การเคลื่อนไหวบนหน้าจอสัมผัส
  • onFocusChanged(boolean, int, Rect) - เรียกใช้เมื่อยอดดูเพิ่มขึ้นหรือหายไป

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

โหมดสัมผัส

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

สำหรับอุปกรณ์ที่รองรับระบบสัมผัส เมื่อผู้ใช้แตะหน้าจอ จะเข้าสู่โหมดสัมผัส จากจุดนี้เป็นต้นไป เฉพาะมุมมองที่ isFocusableInTouchMode() เป็น "จริง" จะสามารถโฟกัสได้ เช่น วิดเจ็ตแก้ไขข้อความ มุมมองอื่นๆ ที่สามารถแตะได้ เช่น ปุ่ม จะไม่จับโฟกัสเมื่อแตะ พวกเขาจะ เพียงแค่เริ่มการทำงานของ Listener เมื่อคลิกเมื่อกด

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

สถานะของโหมดสัมผัสจะยังคงอยู่ตลอดทั้งระบบ (หน้าต่างและกิจกรรมทั้งหมด) ถ้าต้องการสอบถามสถานะปัจจุบัน คุณสามารถโทรติดต่อ isInTouchMode() เพื่อดูว่าอุปกรณ์อยู่ในโหมดสัมผัสอยู่หรือไม่

โฟกัสการจัดการ

เฟรมเวิร์กจะจัดการการเคลื่อนไหวโฟกัสตามกิจวัตรเพื่อตอบสนองต่อข้อมูลจากผู้ใช้ ซึ่งรวมถึงการเปลี่ยนโฟกัสเมื่อนำมุมมองออก ซ่อนมุมมอง หรือเป็นมุมมองใหม่ ยอดดูจะพร้อมใช้งาน ยอดดูบ่งชี้ถึงความเต็มใจที่จะจดจ่อกับสิ่งที่ดู ผ่านเมธอด isFocusable() ถ้าต้องการเปลี่ยนว่าจะให้มุมมองสามารถใช้ โฟกัส โทรหา setFocusable() เมื่ออยู่ในโหมดสัมผัส คุณอาจสอบถามว่าข้อมูลพร็อพเพอร์ตี้อนุญาตให้โฟกัสโดยใช้ isFocusableInTouchMode() หรือไม่ คุณจะเปลี่ยนการตั้งค่านี้ได้ด้วยsetFocusableInTouchMode()

สำหรับอุปกรณ์ที่ใช้ Android 9 (API ระดับ 28) ขึ้นไป กิจกรรมจะไม่กำหนด โฟกัสเริ่มต้น แต่คุณต้องขอโฟกัสเริ่มต้นอย่างชัดแจ้ง หากต้องการ

การเคลื่อนไหวแบบโฟกัสจะอิงตามอัลกอริทึมซึ่งจะค้นหาเพื่อนบ้านที่ใกล้ที่สุดใน ทิศทางที่กำหนด ในบางกรณีที่เกิดขึ้นไม่บ่อยนัก อัลกอริทึมเริ่มต้นอาจไม่ตรงกับ พฤติกรรมที่ตั้งใจไว้ ของนักพัฒนาแอป ในกรณีเหล่านี้ คุณสามารถให้ การลบล้างที่ชัดเจนด้วยแอตทริบิวต์ XML ต่อไปนี้ในไฟล์การออกแบบ nextFocusDown, nextFocusLeft, nextFocusRight และ nextFocusUp เพิ่มหนึ่งในแอตทริบิวต์เหล่านี้ลงในข้อมูลพร็อพเพอร์ตี้จาก ซึ่ง โฟกัสจะหายไป กำหนดค่าของแอตทริบิวต์ให้เป็นรหัสของข้อมูลพร็อพเพอร์ตี้ ถึง สิ่งที่ควรให้ความสำคัญ เช่น

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

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

หากคุณต้องการประกาศว่ามุมมองนั้นสามารถโฟกัสได้ใน UI ของคุณ (แต่ในความเป็นจริงมักจะไม่โฟกัส) เพิ่มแอตทริบิวต์ XML android:focusable ไปยังมุมมองในการประกาศเลย์เอาต์ กำหนดค่า true คุณยังสามารถประกาศมุมมอง โฟกัสได้ขณะอยู่ในโหมดสัมผัสกับ android:focusableInTouchMode

หากต้องการให้ระบบพิจารณาเฉพาะมุมมองใดโดยเฉพาะ โปรดโทร requestFocus()

หากต้องการฟังเหตุการณ์ที่ต้องการสมาธิ (รับการแจ้งเตือนเมื่อมุมมองรับหรือหลุดโฟกัส) ให้ใช้ onFocusChange(), ตามที่ได้อธิบายไว้ในส่วน Listener เหตุการณ์