จัดการการดำเนินการของแป้นพิมพ์

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

แป้นพิมพ์ลัดเริ่มต้น

แป้นพิมพ์ลัดต่อไปนี้พร้อมใช้งานโดยค่าเริ่มต้น

แป้นพิมพ์ลัด การทำงาน คอมโพสิเบิลที่รองรับแป้นพิมพ์ลัด
Shift+Ctrl+ลูกศรซ้าย/ขวา เลือกข้อความไปยังตอนต้น/ตอนท้ายของคำ BasicTextField, TextField
Shift+Ctrl+ลูกศรขึ้น/ลูกศรลง เลือกข้อความจนถึงตอนต้น/ตอนท้ายของย่อหน้า BasicTextField, TextField
Shift+Alt+ลูกศรขึ้น/ลูกศรลง หรือ Shift+Meta+ลูกศรซ้าย/ลูกศรขวา เลือกข้อความไปยังตอนต้น/ตอนท้ายของข้อความ BasicTextField, TextField
Shift+ลูกศรซ้าย/ขวา เลือกอักขระ BasicTextField, TextField
Ctrl+A เลือกทั้งหมด BasicTextField, TextField
Ctrl+C/Ctrl+X/Ctrl+V คัดลอก/ตัด/วาง BasicTextField, TextField
Ctrl+Z/Ctrl+Shift+Z เลิกทำ/ทำซ้ำ BasicTextField, TextField
PageDown/PageUp เลื่อน LazyColumn, ตัวปรับแต่ง verticalScroll, ตัวปรับแต่ง scrollable

กิจกรรมสำคัญ

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

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

ผลลัพธ์ค่าแลมด้า onKeyEvent บ่งบอกว่า ไม่ว่าจะมีการจัดการเหตุการณ์สำคัญหรือไม่ แสดงผล true หากแอปจัดการเหตุการณ์สําคัญ ซึ่งจะหยุดการนำไปใช้งานเหตุการณ์

ข้อมูลโค้ดต่อไปนี้แสดงวิธีเรียกใช้ฟังก์ชัน doSomething() เมื่อผู้ใช้ปล่อยปุ่ม S ในคอมโพเนนต์ Box

Box(
    modifier = Modifier.focusable().onKeyEvent {
        if(
            it.type == KeyEventType.KeyUp &&
            it.key == Key.S
        ) {
            doSomething()
            true
        } else {
            false
        }
    }
)  {
    Text("Press S key")
}

แป้นกดร่วม

ออบเจ็กต์ KeyEvent มีแอตทริบิวต์ต่อไปนี้ซึ่งระบุว่ามีการกดแป้นแปรสภาพหรือไม่

อธิบายเหตุการณ์สําคัญที่แอปจัดการอย่างเจาะจง ข้อมูลโค้ดต่อไปนี้เรียกฟังก์ชัน doSomething() เฉพาะเมื่อผู้ใช้ปล่อยเฉพาะคีย์ S หากผู้ใช้กดแป้นกดร่วม เช่น แป้น Shift แอปจะไม่เรียกใช้ฟังก์ชัน

Box(
  modifier = Modifier.focusable().onKeyEvent{
     if(
       it.type == KeyEventType.KeyUp &&
       it.key == Key.S &&
       !it.isAltPressed &&
       !it.isCtrlPressed &&
       !it.isMetaPressed &&
       !it.isShiftPressed
     ) {
       doSomething()
       true
     } else {
       false
     }
  }
)  {
    Text("Press S key with a modifier key")
}

เหตุการณ์คลิกแป้นเว้นวรรคและ Enter

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

MoviePlayer(
   modifier = Modifier.clickable { togglePausePlay() }
)

แป้นกดร่วม clickable จะขัดขวางเหตุการณ์สําคัญและเรียกใช้การเรียกกลับ onClick() เมื่อมีการกดแป้น Spacebar หรือ Enter นั่นคือเหตุผลที่เรียกฟังก์ชัน togglePausePlay() โดยกดแป้น Spacebar หรือ Enter ในข้อมูลโค้ด

เหตุการณ์สําคัญที่ไม่ได้รับ

เผยแพร่เหตุการณ์สําคัญที่ไม่ได้เกิดขึ้นจากคอมโพเนนต์ ที่เกิดเหตุการณ์กับคอมโพเนนต์ด้านนอกที่ล้อมรอบอยู่ ในตัวอย่างด้านล่าง InnerComponent ใช้เหตุการณ์สําคัญ เมื่อปล่อยคีย์ S ดังนั้น OuterComponent จะไม่ได้รับเหตุการณ์สำคัญใดๆ ที่ทริกเกอร์ ด้วยการปล่อยคีย์ S ด้วยเหตุนี้คุณจึงไม่เรียกใช้ฟังก์ชัน actionB()

เหตุการณ์สําคัญอื่นๆ ใน InnerComponent เช่น การปล่อยคีย์ D ซึ่งสามารถจัดการได้โดย OuterComponent ระบบเรียกฟังก์ชัน actionC() เนื่องจากเหตุการณ์สําคัญของ การเผยแพร่คีย์ D จะเผยแพร่ไปยัง OuterComponent

OuterComponent(
    modifier = Modifier.onKeyEvent {
        when {
           it.type == KeyEventType.KeyUp && it.key == Key.S -> {
               actionB() // This function is never called.
               true
           }
           it.type == KeyEventType.KeyUp && it.key == Key.D -> {
               actionC()
               true
           }
           else -> false
        }
    }
) {
    InnerComponent(
        modifier = Modifier.onKeyEvent {
            if(it.type == KeyEventType.KeyUp && it.key == Key.S) {
                actionA()
                true
            } else {
                false
            }
        }
    )
}

ตัวปรับ onKeyPreviewEvent

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

val focusManager = LocalFocusManager.current
var textFieldValue by remember { mutableStateOf(TextFieldValue()) }

TextField(
    textFieldValue,
    onValueChange = {
        textFieldValue = it
    },
    modifier = Modifier.onPreviewKeyEvent {
        if (it.type == KeyEventType.KeyUp && it.key == Key.Tab) {
            focusManager.moveFocus(FocusDirection.Next)
            true
        } else {
            false
        }
    }
)

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

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

Column(
  modifier = Modifier.onPreviewKeyEvent{
    if(it.key == Key.S){
      previewSKey()
      true
    }else{
      false
    }
  }
) {
  Box(
    modifier = Modifier
        .focusable()
        .onPreviewKeyEvent {
            actionForPreview(it)
            false
        }
        .onKeyEvent {
            actionForKeyEvent(it)
            true
        }
  ) {
    Text("Press any key")
  }
}

แลมดา onPreviewKeyEvent() สําหรับคอมโพเนนต์ Box จะไม่ทริกเกอร์เมื่อผู้ใช้กดแป้น Tab ด้วย ระบบจะเรียกใช้ onPreviewKeyEvent() lambda ในคอมโพเนนต์หลักก่อน แล้วจึงเรียกใช้ onPreviewKeyEvent() ในคอมโพเนนต์ย่อย คุณสามารถใช้แป้นพิมพ์ลัดสำหรับทั้งหน้าจอได้โดยใช้ลักษณะการทำงานนี้

แหล่งข้อมูลเพิ่มเติม