عملکردهای صفحه کلید را مدیریت کنید

هنگامی که کاربر به یک جزء متنی قابل ویرایش مانند یک TextField تمرکز می کند و دستگاه دارای صفحه کلید سخت افزاری متصل است، تمام ورودی ها توسط سیستم مدیریت می شود. با مدیریت رویدادهای کلیدی می توانید میانبرهای صفحه کلید را ارائه دهید.

میانبرهای پیش فرض صفحه کلید

میانبرهای صفحه کلید زیر خارج از جعبه در دسترس هستند.

میانبر صفحه کلید اقدام Composable ها از میانبر پشتیبانی می کنند
Shift + Ctrl + فلش چپ / فلش راست متن را به ابتدا / انتهای کلمه انتخاب کنید BasicTextField ، TextField
Shift + Ctrl + فلش بالا / فلش پایین متن را به ابتدا / انتهای پاراگراف انتخاب کنید BasicTextField ، TextField
Shift + Alt + فلش رو به بالا / فلش رو به پایین یا Shift + متا + فلش چپ / پیکان راست متن را به ابتدا / انتهای متن انتخاب کنید 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 / Page Up اسکرول کنید LazyColumn ، اصلاح‌کننده verticalScroll ، اصلاح‌کننده scrollable

رویدادهای کلیدی

در Compose، می‌توانید با تغییر دهنده onKeyEvent ، یک ضربه کلید جداگانه انجام دهید. اصلاح‌کننده یک لامبدا را می‌پذیرد که وقتی مؤلفه اصلاح‌شده یک رویداد کلیدی را دریافت می‌کند، فراخوانی می‌شود. یک رویداد کلیدی به عنوان یک شی KeyEvent توصیف می شود. شما می توانید با مراجعه به شیء موجود در لامبدا که به اصلاح کننده onKeyEvent ارسال شده است، اطلاعات مربوط به هر رویداد کلیدی را دریافت کنید.

یک ضربه کلید دو رویداد کلیدی را ارسال می کند. هنگامی که کاربر کلید را فشار می دهد، یکی فعال می شود. زمانی که کلید آزاد می شود، دیگری فعال می شود. با مراجعه به ویژگی 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")
}

فاصله و رویدادهای کلیک کلید را وارد کنید

کلید Spacebar و Enter نیز رویدادهای کلیک را راه‌اندازی می‌کنند. به عنوان مثال، کاربران می‌توانند با استفاده از نوار فاصله یا کلید Enter، پخش رسانه‌ها را به صورت زیر تغییر دهند (پخش یا مکث کنند):

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

اصلاح‌کننده clickable رویدادهای کلیدی را قطع می‌کند و هنگامی که کلید Spacebar یا Enter فشار داده می‌شود، onClick() را فراخوانی می‌کند. به همین دلیل است که تابع 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 یک مورد معمولی است. قطعه زیر به کاربران امکان می دهد با فشار دادن کلید تب به مؤلفه قابل فوکوس بعدی بروند.

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() lambda رویداد کلیدی را با برگرداندن true قطع می کند.

مؤلفه والد می تواند رویداد کلیدی را که روی فرزندانش اتفاق می افتد رهگیری کند. در قطعه زیر، تابع previewSKey() زمانی فراخوانی می شود که کاربران به جای فراخوانی تابع actionForPreview() ، کلید S را فشار دهند.

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() ابتدا روی مولفه والد فراخوانی می شود، سپس onPreviewKeyEvent() در مولفه فرزند فراخوانی می شود. با استفاده از این رفتار می‌توانید میانبرهای صفحه‌کلید گسترده را پیاده‌سازی کنید.

منابع اضافی

،

هنگامی که کاربر به یک جزء متنی قابل ویرایش مانند یک TextField تمرکز می کند و دستگاه دارای صفحه کلید سخت افزاری متصل است، تمام ورودی ها توسط سیستم مدیریت می شود. با مدیریت رویدادهای کلیدی می توانید میانبرهای صفحه کلید را ارائه دهید.

میانبرهای پیش فرض صفحه کلید

میانبرهای صفحه کلید زیر خارج از جعبه در دسترس هستند.

میانبر صفحه کلید اقدام Composable ها از میانبر پشتیبانی می کنند
Shift + Ctrl + فلش چپ / فلش راست متن را به ابتدا / انتهای کلمه انتخاب کنید BasicTextField ، TextField
Shift + Ctrl + فلش بالا / فلش پایین متن را به ابتدا / انتهای پاراگراف انتخاب کنید BasicTextField ، TextField
Shift + Alt + فلش رو به بالا / فلش رو به پایین یا Shift + متا + فلش چپ / پیکان راست متن را به ابتدا / انتهای متن انتخاب کنید 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 / Page Up اسکرول کنید LazyColumn ، اصلاح‌کننده verticalScroll ، اصلاح‌کننده scrollable

رویدادهای کلیدی

در Compose، می‌توانید با تغییر دهنده onKeyEvent ، یک ضربه کلید جداگانه انجام دهید. اصلاح‌کننده یک لامبدا را می‌پذیرد که وقتی مؤلفه اصلاح‌شده یک رویداد کلیدی را دریافت می‌کند، فراخوانی می‌شود. یک رویداد کلیدی به عنوان یک شی KeyEvent توصیف می شود. شما می توانید با مراجعه به شیء موجود در لامبدا که به اصلاح کننده onKeyEvent ارسال شده است، اطلاعات مربوط به هر رویداد کلیدی را دریافت کنید.

یک ضربه کلید دو رویداد کلیدی را ارسال می کند. هنگامی که کاربر کلید را فشار می دهد، یکی فعال می شود. زمانی که کلید آزاد می شود، دیگری فعال می شود. با مراجعه به ویژگی 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")
}

فاصله و رویدادهای کلیک کلید را وارد کنید

کلید Spacebar و Enter نیز رویدادهای کلیک را راه‌اندازی می‌کنند. به عنوان مثال، کاربران می‌توانند با استفاده از نوار فاصله یا کلید Enter، پخش رسانه‌ها را به صورت زیر تغییر دهند (پخش یا مکث کنند):

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

اصلاح‌کننده clickable رویدادهای کلیدی را قطع می‌کند و هنگامی که کلید Spacebar یا Enter فشار داده می‌شود، onClick() را فراخوانی می‌کند. به همین دلیل است که تابع 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 یک مورد معمولی است. قطعه زیر به کاربران امکان می دهد با فشار دادن کلید تب به مؤلفه قابل فوکوس بعدی بروند.

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() lambda رویداد کلیدی را با برگرداندن true قطع می کند.

مؤلفه والد می تواند رویداد کلیدی را که روی فرزندانش اتفاق می افتد رهگیری کند. در قطعه زیر، تابع previewSKey() زمانی فراخوانی می شود که کاربران به جای فراخوانی تابع actionForPreview() ، کلید S را فشار دهند.

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() ابتدا روی مولفه والد فراخوانی می شود، سپس onPreviewKeyEvent() در مولفه فرزند فراخوانی می شود. با استفاده از این رفتار می‌توانید میانبرهای صفحه‌کلید گسترده را پیاده‌سازی کنید.

منابع اضافی