سازگاری ورودی در صفحه نمایش های بزرگ

در دستگاه‌های صفحه‌نمایش بزرگ، کاربران اغلب با استفاده از صفحه‌کلید، ماوس، ترک‌پد، قلم، یا گیم‌پد با برنامه‌ها تعامل دارند. برای فعال کردن برنامه خود برای پذیرش ورودی از دستگاه های خارجی، موارد زیر را انجام دهید:

  • پشتیبانی اولیه از صفحه کلید را آزمایش کنید ، مانند Ctrl+Z برای لغو، Ctrl+C برای کپی و Ctrl+S برای ذخیره. برای فهرستی از میانبرهای پیش‌فرض صفحه کلید ، به کنترل عملکردهای صفحه‌کلید مراجعه کنید.
  • پشتیبانی پیشرفته صفحه‌کلید را آزمایش کنید ، به‌عنوان مثال، پیمایش صفحه‌کلید کلید Tab و پیکان، تأیید ورود متن کلید را وارد کنید ، و Spacebar پخش و مکث در برنامه‌های رسانه‌ای.
  • فعل و انفعالات اساسی ماوس را آزمایش کنید ، از جمله کلیک راست برای منوی زمینه، تغییرات نماد در شناور، و رویدادهای اسکرول چرخ ماوس یا صفحه لمسی در اجزای سفارشی.
  • دستگاه‌های ورودی مخصوص برنامه مانند قلم، کنترل‌کننده‌های بازی، و کنترل‌کننده‌های MIDI برنامه موسیقی را آزمایش کنید .
  • پشتیبانی ورودی پیشرفته را در نظر بگیرید که می‌تواند برنامه را در محیط‌های دسک‌تاپ متمایز کند، به‌عنوان مثال، پد لمسی به‌عنوان یک فیدر متقاطع برای برنامه‌های دی‌جی، ضبط ماوس برای بازی‌ها، و میان‌برهای صفحه‌کلید برای کاربران صفحه‌کلید محور.

صفحه کلید

روشی که برنامه شما به ورودی صفحه‌کلید پاسخ می‌دهد به تجربه کاربر صفحه بزرگ کمک می‌کند. سه نوع ورودی صفحه کلید وجود دارد: ناوبری ، فشار دادن کلید ، و میانبر .

پیمایش صفحه‌کلید به ندرت در برنامه‌های لمس محور اجرا می‌شود، اما کاربران زمانی که از یک برنامه استفاده می‌کنند و دستشان روی صفحه‌کلید است، انتظار آن را دارند. ناوبری صفحه‌کلید می‌تواند در تلفن‌ها، تبلت‌ها، تاشوها و دستگاه‌های رومیزی برای کاربرانی که نیازهای دسترسی دارند ضروری باشد.

برای بسیاری از برنامه‌ها، کلید پیکان و پیمایش کلید Tab به طور خودکار توسط چارچوب Android مدیریت می‌شوند. به عنوان مثال، برخی از composable ها به طور پیش فرض قابل فوکوس هستند، مانند یک Button یا یک Composable با تغییر دهنده clickable . پیمایش صفحه کلید معمولاً باید بدون کد اضافی کار کند. برای فعال کردن پیمایش صفحه‌کلید برای کامپوزیشن‌های سفارشی که به‌طور پیش‌فرض قابل فوکوس نیستند، اصلاح‌کننده focusable را اضافه کنید:

var color by remember { mutableStateOf(Green) }
Box(
    Modifier
        .background(color)
        .onFocusChanged { color = if (it.isFocused) Blue else Green }
        .focusable()
) {
    Text("Focusable 1")
}

برای اطلاعات بیشتر، به ساختن یک فوکوس پذیر قابل ترکیب مراجعه کنید.

هنگامی که فوکوس فعال است، چارچوب Android یک نقشه ناوبری برای همه اجزای قابل فوکوس بر اساس موقعیت آنها ایجاد می کند. این معمولاً مطابق انتظار عمل می کند و نیازی به توسعه بیشتر نیست.

با این حال، Compose همیشه مورد بعدی صحیح را برای پیمایش زبانه‌ها برای ترکیب‌پذیرهای پیچیده مانند برگه‌ها و فهرست‌ها تعیین نمی‌کند، به عنوان مثال، زمانی که یکی از قابلیت‌های composable یک اسکرول افقی است که به طور کامل قابل مشاهده نیست.

برای کنترل رفتار فوکوس، اصلاح‌کننده focusGroup را به والد قابل ترکیب مجموعه‌ای از ترکیب‌پذیرها اضافه کنید. فوکوس به گروه منتقل می شود، سپس از طریق گروه قبل از حرکت به مؤلفه قابل تمرکز بعدی، به عنوان مثال:

Row {
    Column(Modifier.focusGroup()) {
        Button({}) { Text("Row1 Col1") }
        Button({}) { Text("Row2 Col1") }
        Button({}) { Text("Row3 Col1") }
    }
    Column(Modifier.focusGroup()) {
        Button({}) { Text("Row1 Col2") }
        Button({}) { Text("Row2 Col2") }
        Button({}) { Text("Row3 Col2") }
    }
}

برای اطلاعات بیشتر، به ارائه پیمایش منسجم با گروه‌های کانونی مراجعه کنید.

فقط با استفاده از صفحه کلید دسترسی به هر عنصر رابط کاربری برنامه خود را آزمایش کنید. عناصری که اغلب استفاده می شوند باید بدون ورودی ماوس یا لمسی در دسترس باشند.

به یاد داشته باشید، پشتیبانی از صفحه کلید ممکن است برای کاربرانی که نیازهای دسترسی دارند ضروری باشد.

ضربات کلید

برای ورودی متنی که توسط یک صفحه کلید مجازی روی صفحه ( IME ) مدیریت می شود، مانند براییک TextField، برنامه ها باید همانطور که انتظار می رود در دستگاه های صفحه نمایش بزرگ بدون کار توسعه اضافی رفتار کنند. برای کلیدهایی که توسط چارچوب قابل پیش بینی نیست، برنامه ها باید خودشان رفتار را مدیریت کنند. این امر به ویژه برای برنامه هایی با نمای سفارشی صادق است.

برخی از نمونه‌ها برنامه‌های چت هستند که از کلید Enter برای ارسال پیام استفاده می‌کنند، برنامه‌های رسانه‌ای که پخش را با Spacebar شروع و متوقف می‌کنند و بازی‌هایی که حرکت را با کلیدهای w ، a ، s و d کنترل می‌کنند.

می‌توانید ضربه‌های کلیدی جداگانه را با اصلاح‌کننده onKeyEvent انجام دهید، که لامبدا را می‌پذیرد که وقتی مؤلفه اصلاح‌شده یک رویداد کلیدی را دریافت می‌کند، فراخوانی می‌شود. ویژگی KeyEvent#type شما را قادر می‌سازد تا تعیین کنید که آیا رویداد فشار دادن کلید ( KeyDown ) یا انتشار کلید ( KeyUp ) است:

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

همچنین، می‌توانید فراخوانی onKeyUp() را لغو کنید و رفتار مورد انتظار را برای هر کد کلید دریافتی اضافه کنید:

override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
    return when (keyCode) {
        KeyEvent.KEYCODE_ENTER -> {
            sendChatMessage()
            true
        }
        KeyEvent.KEYCODE_SPACE -> {
            playOrPauseMedia()
            true
        }
        else -> super.onKeyUp(keyCode, event)
    }
}

یک رویداد onKeyUp زمانی رخ می دهد که یک کلید آزاد شود. اگر کلیدی به آرامی نگه داشته شود یا به آرامی رها شود، استفاده از پاسخ به تماس، از نیاز برنامه‌ها به پردازش چندین رویداد onKeyDown جلوگیری می‌کند. بازی‌ها و برنامه‌هایی که باید لحظه فشار دادن یک کلید را تشخیص دهند یا اینکه کاربر کلیدی را پایین نگه داشته است، می‌توانند به رویداد onKeyDown گوش دهند و رویدادهای تکراری onKeyDown خودشان مدیریت کنند.

برای اطلاعات بیشتر، به کنترل عملکردهای صفحه کلید مراجعه کنید.

میانبرها

هنگام استفاده از صفحه کلید سخت‌افزاری، میانبرهای رایج صفحه کلید که شامل کلیدهای Ctrl ، Alt ، Shift و Meta می‌شوند، انتظار می‌رود. اگر یک برنامه میانبرها را پیاده سازی نکند، تجربه می تواند برای کاربران خسته کننده باشد. کاربران پیشرفته همچنین از میانبرها برای کارهای خاص برنامه که اغلب استفاده می شوند قدردانی می کنند. میانبرها استفاده از برنامه را آسان تر می کند و آن را از برنامه هایی که میانبر ندارند متمایز می کند.

برخی از میانبرهای رایج عبارتند از Ctrl+S (ذخیره)، Ctrl+Z (لغو) و Ctrl+Shift+Z (دوباره). برای فهرستی از میانبرهای پیش فرض، به کنترل عملکردهای صفحه کلید مراجعه کنید.

یک شی KeyEvent دارای ویژگی های زیر است که نشان می دهد آیا کلیدهای اصلاح کننده فشرده شده اند یا خیر:

به عنوان مثال:

Box(
    Modifier.onKeyEvent {
        if (it.isAltPressed && it.key == Key.A) {
            println("Alt + A is pressed")
            true
        } else {
            false
        }
    }
    .focusable()
)

برای اطلاعات بیشتر به ادامه مطلب مراجعه کنید:

قلم

بسیاری از دستگاه های صفحه نمایش بزرگ دارای قلم هستند. برنامه‌های اندروید قلم‌ها را به عنوان ورودی صفحه لمسی کنترل می‌کنند. ممکن است برخی از دستگاه‌ها مانند Wacom Intuos دارای یک میز طراحی USB یا بلوتوث باشند. برنامه‌های اندروید می‌توانند ورودی بلوتوث را دریافت کنند اما ورودی USB را دریافت نمی‌کنند.

برای دسترسی به اشیاء استایلوس MotionEvent ، مدیفایر pointerInteropFilter را به سطح طراحی اضافه کنید. یک کلاس ViewModel را با روشی که رویدادهای حرکت را پردازش می کند، پیاده سازی کنید. متد را به عنوان onTouchEvent lambda اصلاح کننده pointerInteropFilter ارسال کنید:

@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
   Canvas(modifier = modifier
       .clipToBounds()
       .pointerInteropFilter {
           viewModel.processMotionEvent(it)
       }

   ) {
       // Drawing code here.
   }
}

شی MotionEvent حاوی اطلاعاتی در مورد رویداد است:

نکات تاریخی

Android رویدادهای ورودی را دسته‌بندی می‌کند و آنها را یک بار در هر فریم ارائه می‌کند. یک قلم می تواند رویدادها را با فرکانس های بسیار بالاتر از نمایشگر گزارش دهد. هنگام ایجاد برنامه های طراحی، با استفاده از getHistorical API ها، رویدادهایی را که ممکن است در گذشته نزدیک باشند بررسی کنید:

رد کف دست

هنگامی که کاربران با استفاده از قلم طراحی می کنند، می نویسند یا با برنامه شما تعامل می کنند، گاهی اوقات صفحه را با کف دست لمس می کنند. رویداد لمسی (روی ACTION_DOWN یا ACTION_POINTER_DOWN تنظیم شده است) را می توان قبل از اینکه سیستم لمس ناخواسته کف دست را تشخیص دهد و نادیده بگیرد، به برنامه شما گزارش شود.

Android رویدادهای لمس کف دست را با ارسال MotionEvent لغو می‌کند. اگر برنامه شما ACTION_CANCEL را دریافت کرد، حرکت را لغو کنید. اگر برنامه شما ACTION_POINTER_UP دریافت کرد، بررسی کنید که آیا FLAG_CANCELED تنظیم شده است یا خیر. اگر چنین است، ژست را لغو کنید.

فقط FLAG_CANCELED را بررسی نکنید. در Android 13 (سطح API 33) و بالاتر، سیستم FLAG_CANCELED برای رویدادهای ACTION_CANCEL تنظیم می‌کند، اما سیستم پرچم را در نسخه‌های پایین‌تر Android تنظیم نمی‌کند.

اندروید 12

در Android 12 (سطح API 32) و پایین‌تر، تشخیص رد کف دست فقط برای رویدادهای لمسی تک اشاره‌ای امکان‌پذیر است. اگر لمس کف دست تنها نشانگر باشد، سیستم با تنظیم ACTION_CANCEL روی شی رویداد حرکتی، رویداد را لغو می‌کند. اگر سایر نشانگرها پایین باشند، سیستم ACTION_POINTER_UP را تنظیم می کند که برای تشخیص رد کف دست کافی نیست.

اندروید 13

در Android 13 (سطح API 33) و بالاتر، اگر تنها اشاره‌گر لمس کف دست باشد، سیستم با تنظیم ACTION_CANCEL و FLAG_CANCELED روی شی رویداد حرکتی، رویداد را لغو می‌کند. اگر سایر نشانگرها پایین باشند، سیستم ACTION_POINTER_UP و FLAG_CANCELED تنظیم می‌کند.

هر زمان که برنامه شما یک رویداد حرکتی با ACTION_POINTER_UP دریافت کرد، FLAG_CANCELED را بررسی کنید تا مشخص شود آیا رویداد نشان دهنده رد کف دست (یا لغو رویداد دیگر) است.

برنامه های یادداشت برداری

ChromeOS هدف خاصی دارد که برنامه‌های ثبت‌شده یادداشت‌برداری را در اختیار کاربران قرار می‌دهد. برای ثبت یک برنامه به عنوان یک برنامه یادداشت برداری، موارد زیر را به مانیفست برنامه خود اضافه کنید:

<intent-filter>
    <action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

وقتی یک برنامه در سیستم ثبت می شود، کاربر می تواند آن را به عنوان برنامه پیش فرض یادداشت برداری انتخاب کند. وقتی یادداشت جدیدی درخواست می‌شود، برنامه باید یک یادداشت خالی آماده برای ورودی قلم ایجاد کند. هنگامی که کاربر می خواهد یک تصویر را حاشیه نویسی کند (مانند یک اسکرین شات یا تصویر بارگیری شده)، برنامه با ClipData شامل یک یا چند مورد با content:// URI راه اندازی می شود. برنامه باید یادداشتی ایجاد کند که از اولین تصویر پیوست شده به عنوان تصویر پس‌زمینه استفاده کند و حالتی را وارد کند که کاربر بتواند با یک قلم روی صفحه نمایش بکشد.

اهداف یادداشت برداری را بدون قلم تست کنید

[بخش حذف TBD.]

برای آزمایش اینکه آیا یک برنامه بدون قلم فعال به اهداف یادداشت‌برداری به درستی پاسخ می‌دهد، از روش زیر برای نمایش گزینه‌های یادداشت‌برداری در ChromeOS استفاده کنید:

  1. به حالت توسعه دهنده بروید و دستگاه را قابل نوشتن کنید
  2. Ctrl+Alt+F2 را فشار دهید تا ترمینال باز شود
  3. دستور sudo vi /etc/chrome_dev.conf را اجرا کنید
  4. i برای ویرایش فشار دهید و --ash-enable-palette به خط جدیدی در انتهای فایل اضافه کنید
  5. با فشار دادن Esc و سپس تایپ کردن : , w , q و فشردن Enter ذخیره کنید
  6. برای بازگشت به رابط کاربری عادی ChromeOS ، Ctrl+Alt+F1 را فشار دهید
  7. از سیستم خارج شوید، سپس دوباره وارد شوید

یک منوی قلم اکنون باید در قفسه باشد:

  • روی دکمه قلم در قفسه ضربه بزنید و یادداشت جدید را انتخاب کنید. این باید یک یادداشت نقاشی خالی را باز کند.
  • اسکرین شات بگیرید از قفسه، دکمه قلم > ضبط صفحه را انتخاب کنید یا یک تصویر را دانلود کنید. باید گزینه Annotate image در اعلان وجود داشته باشد. این باید برنامه را با تصویر آماده برای حاشیه نویسی راه اندازی کند.

پشتیبانی از ماوس و تاچ پد

اکثر برنامه‌ها معمولاً فقط به سه رویداد بزرگ صفحه‌نمایش نیاز دارند: کلیک راست ، شناور ، و کشیدن و رها کردن .

کلیک راست کنید

هر اقدامی که باعث می‌شود برنامه منوی زمینه را نشان دهد، مانند لمس و نگه‌داشتن یک مورد فهرست، باید به رویدادهای کلیک راست نیز واکنش نشان دهد.

برای مدیریت رویدادهای کلیک راست، برنامه‌ها باید یک View.OnContextClickListener ثبت کنند.OnContextClickListener:

Box(modifier = Modifier.fillMaxSize()) {
    AndroidView(
        modifier = Modifier.fillMaxSize(),
        factory = { context ->
            val rootView = FrameLayout(context)
            val onContextClickListener =
                View.OnContextClickListener { view ->
                    showContextMenu()
                    true
                }
            rootView.setOnContextClickListener(onContextClickListener)
            rootView
        },
    )
}

برای جزئیات در مورد ساخت منوهای زمینه، به ایجاد یک منوی متنی مراجعه کنید.

شناور

می‌توانید با مدیریت رویدادهای شناور، چیدمان‌های برنامه‌تان را صیقلی‌تر و آسان‌تر کنید. این به ویژه در مورد عرف صادق استاجزاء:

دو نمونه رایج در این مورد عبارتند از:

  • با تغییر نماد اشاره گر ماوس به کاربران نشان می دهد که آیا یک عنصر رفتار تعاملی دارد، مانند قابل کلیک یا قابل ویرایش بودن
  • افزودن بازخورد بصری به موارد موجود در یک لیست یا شبکه بزرگ هنگامی که نشانگر روی آنها قرار دارد

بکشید و رها کنید

در یک محیط چند پنجره ای، کاربران انتظار دارند که بتوانند آیتم ها را بین برنامه ها بکشند و رها کنند. این امر برای دستگاه‌های رومیزی و همچنین تبلت‌ها، تلفن‌ها، و تاشوها در حالت تقسیم صفحه صادق است.

در نظر بگیرید که آیا کاربران ممکن است موارد را به برنامه شما بکشند یا خیر. به عنوان مثال، ویرایشگرهای عکس باید انتظار دریافت عکس، پخش کننده های صوتی را برای دریافت فایل های صوتی و برنامه های طراحی باید انتظار دریافت عکس داشته باشند.

برای افزودن پشتیبانی کشیدن و رها کردن، رجوع کنیدبکشید و رها کنیدو نگاهی به Android در ChromeOS بیاندازید — پیاده سازی پست وبلاگ Drag & Drop .

ملاحظات ویژه برای ChromeOS

پشتیبانی از اشاره گر پیشرفته

برنامه‌هایی که کنترل پیشرفته‌ای از ورودی ماوس و صفحه لمسی را انجام می‌دهند باید aتغییر دهنده pointerInput برای به دست آوردن PointerEvent :

@Composable
private fun LogPointerEvents(filter: PointerEventType? = null) {
    var log by remember { mutableStateOf("") }
    Column {
        Text(log)
        Box(
            Modifier
                .size(100.dp)
                .background(Color.Red)
                .pointerInput(filter) {
                    awaitPointerEventScope {
                        while (true) {
                            val event = awaitPointerEvent()
                            // handle pointer event
                            if (filter == null || event.type == filter) {
                                log = "${event.type}, ${event.changes.first().position}"
                            }
                        }
                    }
                }
        )
    }
}

شی PointerEvent را برای تعیین موارد زیر بررسی کنید:

کنترلرهای بازی

برخی از دستگاه های اندرویدی با صفحه نمایش بزرگ تا چهار کنترلر بازی را پشتیبانی می کنند. از APIهای استاندارد کنترلر بازی اندروید برای کنترل کنترلرهای بازی استفاده کنید ( به پشتیبانی از کنترلرهای بازی مراجعه کنید).

دکمه‌های کنترل‌کننده بازی به دنبال یک نقشه‌برداری مشترک به مقادیر رایج نگاشت می‌شوند. اما همه سازندگان کنترلرهای بازی از قوانین نقشه برداری یکسانی پیروی نمی کنند. اگر به کاربران اجازه دهید تا نگاشت های مختلف کنترلر محبوب را انتخاب کنند، می توانید تجربه بسیار بهتری ارائه دهید. برای اطلاعات بیشتر به فرآیند فشار دادن دکمه گیم پد مراجعه کنید.

حالت ترجمه ورودی

ChromeOS حالت ترجمه ورودی را به طور پیش‌فرض فعال می‌کند. برای اکثر برنامه‌های اندروید، این حالت به برنامه‌ها کمک می‌کند تا همانطور که انتظار می‌رود در محیط دسکتاپ کار کنند. برخی از نمونه‌ها عبارتند از فعال کردن خودکار پیمایش با دو انگشت روی صفحه لمسی، پیمایش چرخ ماوس، و نگاشت مختصات صفحه نمایش خام به مختصات پنجره. به طور کلی، توسعه دهندگان اپلیکیشن نیازی به پیاده سازی هیچ یک از این رفتارها ندارند.

اگر برنامه‌ای رفتار ورودی سفارشی را پیاده‌سازی کند، به‌عنوان مثال، یک عمل چسباندن صفحه لمسی با دو انگشت سفارشی را تعریف کند، یا این ترجمه‌های ورودی رویدادهای ورودی مورد انتظار برنامه را ارائه نمی‌کنند، می‌توانید حالت ترجمه ورودی را با افزودن برچسب زیر به آن غیرفعال کنید. مانیفست اندروید:

<uses-feature
    android:name="android.hardware.type.pc"
    android:required="false" />

منابع اضافی