اشاره‌های با یک دست با Compose


در Wear OS 7 (سطح میانای برنامه‌سازی کاربردی ۳۷) و بالاتر، چارچوب اشاره یک‌دستی، به‌همراه میانای برنامه‌سازی کاربردی که بخشی از Compose برای Wear OS است، به کاربران امکان می‌دهد بدون لمس کردن با برنامه‌تان تعامل داشته باشند.

درحالی‌که این چارچوب در ابتدا در دستگاه‌های Pixel Watch (‏Pixel Watch 3 و نسخه‌های جدیدتر) پشتیبانی می‌شد، اکنون برای همه سازندگان اصلی دردسترس است. با اتخاذ این میانای برنامه‌سازی کاربردی، پشتیبانی از اشاره در برنامه شما به‌طور خودکار در سراسر بوم‌سازگان گسترش می‌یابد، زیرا پشتیبانی سخت‌افزاری گسترش می‌یابد.

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

اشاره‌ها و کنش‌های پشتیبانی‌شده

چارچوب اشاره‌های Wear OS از دو نوع اشاره پشتیبانی می‌کند:

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

پیکربندی اشاره‌ها در Compose

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

همانند رفتارهای Compose استاندارد، اشاره‌های یک‌دستی را در عناصر میانای کاربر بااستفاده از اصلاح‌کننده‌ها فعال می‌کنید. اشاره‌های برنامه‌تان را براساس کنشی که باید انجام شود (کنش اصلی یا رد کردن) و gestureId پیکربندی می‌کنید تا با اولویت‌های کاربر در سطح سیستم (مثل آهنگ نمایش اشاره و بی‌صدا کردن تکرار) هماهنگ شود. این پیکربندی را با ایجاد شیء OneHandedGestureConfiguration بیان می‌کنید؛ توصیه می‌کنیم از تابع rememberOneHandedGestureConfiguration برای ایجاد آن استفاده کنید. OneHandedGestureConfiguration همچنین جایی است که می‌توانید اولویت اشاره را ارائه دهید.

تابع rememberOneHandedGestureConfiguration سابقه تعامل کاربر را در ترکیب‌های مجدد بدون افشای وضعیت برنامه ردیابی می‌کند. وقتی برنامه پیکربندی را ایجاد کرد، باید پیکربندی را به Modifier.oneHandedGesture در ترکیب‌پذیر تعاملی شما ارسال کند.

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

اجزای تعاملی

برای فعال کردن اشاره‌ها در کنترل تعاملی مانند دکمه، پیکربندی‌ای ایجاد کنید که OneHandedGestureAction.Primary را مشخص کند و اصلاح‌کننده oneHandedGesture را اعمال کنید. همان MutableInteractionSource را به هر دو کنترل و اصلاح‌کننده ارسال کنید تا رویدادهای اشاره بازخورد فشار بصری را به کنترل منتقل کنند.

برای فعال کردن نشانگر اشاره، نمونه‌ای از OneHandedGestureClickIndicatorState را ایجاد کنید و به‌خاطر بسپارید. سپس، برای راه‌اندازی بازخورد تصویری، showIndicator را در onGestureAvailable فراخوانی برگشتی ارائه‌شده توسط اصلاح‌کننده oneHandedGesture فراخوانی کنید، که به سیستم نشان می‌دهد رویداد نشانگر رخ داده است. پس‌از فراخوانی، مؤلفه به‌طور خلاصه محتوای عادی خود را با پویانمایی اشاره جایگزین می‌کند.

var isPlaying by remember { mutableStateOf(false) }
val onClick = { isPlaying = !isPlaying }

val gestureConfig = rememberOneHandedGestureConfiguration(
    action = OneHandedGestureAction.Primary
)
val indicatorState = remember { OneHandedGestureClickIndicatorState() }
val coroutineScope = rememberCoroutineScope()
val interactionSource = remember { MutableInteractionSource() }

Button(
    onClick = onClick,
    interactionSource = interactionSource,
    modifier = Modifier
        .fillMaxWidth()
        .oneHandedGesture(
            gestureConfiguration = gestureConfig,
            interactionSource = interactionSource,
            onGestureLabel = if (isPlaying) "pause" else "play",
            onGestureAvailable = { coroutineScope.launch { indicatorState.showIndicator() } },
            onGesture = onClick
        )
) {
    OneHandedGestureClickIndicator(
        gestureConfiguration = gestureConfig,
        state = indicatorState
    ) {
        Text(if (isPlaying) "Pause" else "Play", modifier = Modifier.fillMaxWidth())
    }
}

محفظه‌های قابل‌پیمایش

برای صفحه‌ها یا فهرست‌های پیمایش‌شدنی، پیکربندی‌ای ایجاد کنید که OneHandedGestureAction.Primary را مشخص کند و اصلاح‌کننده oneHandedGesture را برای محفظه‌تان اعمال کند، و دستیار پیمایش مثل scrollDown را فراخوانی کند.

برای ارائه بازخورد دیداری برای کنش‌های پیمایش، می‌توانید از OneHandedGestureScrollIndicator استفاده کنید. این مؤلفه به‌عنوان نشانگر پیمایش استاندارد عمل می‌کند که موقعیت پیمایش را نشان می‌دهد، اما می‌تواند نشان دهد که اشاره پیمایش برای کاربر دردسترس است. این نشانگر معمولاً به جایگاه scrollIndicator از ScreenScaffold منتقل می‌شود و با وضعیت محفظه پیمایشی، مانند TransformingLazyColumn، جفت می‌شود. همچنین OneHandedGestureScrollIndicatorState را برای مدیریت انتقال‌های بصری خود مشاهده می‌کند.

برای راه‌اندازی بازخورد تصویری، showIndicator را در این وضعیت فراخوانی کنید—معمولاً درون فراخوانی برگشتی onGestureAvailable از اصلاح‌کننده oneHandedGesture. پس‌از فعال شدن، نشانگر به‌طور موقت حالت دیداری استاندارد خود را با یک توالی پویانمایی اشاره‌ای جایگزین می‌کند تا به کاربر هشدار دهد.

val scrollState = rememberTransformingLazyColumnState()
val gestureConfig = rememberOneHandedGestureConfiguration(
    action = OneHandedGestureAction.Primary,
    priority = OneHandedGesturePriority.Scrollable
)
val indicatorState = remember(gestureConfig) { OneHandedGestureScrollIndicatorState() }
val coroutineScope = rememberCoroutineScope()

ScreenScaffold(
    scrollState = scrollState,
    scrollIndicator = {
        OneHandedGestureScrollIndicator(
            gestureConfiguration = gestureConfig,
            indicatorState = indicatorState,
            scrollState = scrollState,
            modifier = Modifier.align(Alignment.CenterEnd)
        )
    }
) { contentPadding ->
    TransformingLazyColumn(
        state = scrollState,
        contentPadding = contentPadding,
        modifier = Modifier
            .fillMaxSize()
            .oneHandedGesture(
                gestureConfiguration = gestureConfig,
                onGestureLabel = "scroll",
                onGestureAvailable = {
                    coroutineScope.launch { indicatorState.showIndicator() }
                },
                onGesture = { OneHandedGestureDefaults.scrollDown(scrollState) }
            )
    ) {
        items(10) { index ->
            Text("Item $index", modifier = Modifier.padding(8.dp))
        }
    }
}

ترکیب کردن چند اشاره

می‌توانید با افزودن gesturePriority به شیء OneHandedGestureConfiguration، هم اشاره پیمایش و هم اشاره کلیک را با کنش اصلی یکسان پیکربندی کنید:

  • OneHandedGesturePriority.Clickable (بالاترین): به کنترل‌های تعاملی (مثل کنترل‌های دارای نوع Button یا Card) اختصاص دهید تا وقتی در صفحه نمایان هستند، اشاره‌ها را ضبط کنند.
  • OneHandedGesturePriority.Scrollable (متوسط): به محفظه‌های پیمایشی یا صفحه‌بندی‌شده اختصاص دهید تا به فرزندان قابل‌کلیک واگذار شوند اما وقتی کنترل قابل‌کلیکی نمایان نیست پیمایش شوند.
  • OneHandedGesturePriority.Unspecified (پایین‌ترین): اولویت تخصیص‌نیافته. این مقدار پیش‌فرض برای اشاره‌ای است که priority برای آن تنظیم نشده است.

با تنظیم صریح priority = OneHandedGesturePriority.Clickable روی دکمه داخلی و priority = OneHandedGesturePriority.Scrollable روی فهرست اصلی آن، سیستم می‌تواند این رفتار اولویت اشاره را نشان دهد. وقتی کاربر کنش اصلی را با اشاره یک‌دستی راه‌اندازی می‌کند، ابتدا فهرست را به پایین پیمایش می‌کند تا دکمه نمایان شود، و سپس کنش کلیک دکمه را ضبط می‌کند.

آزمایش و اشکال‌زدایی اشاره‌ها با ADB

می‌توانید اشاره‌های یک‌دستی را در دستگاه فیزیکی یا شبیه‌ساز بدون انجام حرکات فیزیکی مچ دست بااستفاده از Android Debug Bridge (adb) و سرویس سیستم IWearGestureService آزمایش کنید.

فعال کردن شبیه‌سازی اشاره

قبل‌از شبیه‌سازی اشاره‌ها بااستفاده از ADB، تنظیمات دستگاه و لغوهای محدودیت را پیکربندی کنید:

  1. مطمئن شوید دستگاه Wear OS شما Wear OS 7 (سطح API‏ ۳۷) و بالاتر را اجرا می‌کند:

    adb shell getprop ro.build.version.sdk
    
  2. اگر درحال آزمایش روی دستگاه فیزیکی‌ای هستید که روی مچ دستتان نیست یا روی شارژر قرار دارد، محدودیت «خارج از بدن» را لغو کنید تا چارچوب اشاره فعال بماند:

    adb shell cmd IWearGestureService override-constraints offbody-state
    

راه‌اندازی کردن رویدادهای اشاره بااستفاده از ADB

برای شبیه‌سازی اشاره دونیشگون گرفتن (که کنش Primary در ساعت‌های Pixel است)، فرمان پوسته ADB زیر را اجرا کنید:

adb shell cmd IWearGestureService gesture DoublePinch

برای شبیه‌سازی اشاره چرخاندن مچ (که کنش Dismiss در ساعت‌های Pixel است)، فرمان پوسته ADB زیر را اجرا کنید:

adb shell cmd IWearGestureService gesture WristTurn

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

سیستم سابقه تعامل کاربر را ردیابی می‌کند و اشاره‌های اشاره‌ای شناور را براساس تنظیم آهنگ جهانی (مانند همیشه یا روزانه) نمایش می‌دهد. هنگام اشکال‌زدایی نشانگرهای اشاره برنامه، این سابقه ردیابی را بازنشانی کنید تا اشاره‌ها دوباره برای بسته‌تان نشان داده شود:

  • در ساخت‌ها یا شبیه‌سازهای userdebug:

    adb shell cmd IWearGestureService hint clear <your_package_name>
    
  • در ساخت‌های خرده‌فروشی (user):

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

    adb shell pm clear <your_package_name>
    

بازگرداندن محدودیت‌های پیش‌فرض

برای بازنشانی همه لغوهای محدودیت اشکال‌زدایی پس‌از اتمام آزمایش:

adb shell cmd IWearGestureService override-constraints reset

عیب‌یابی تزریق اشاره

اگر برنامه‌تان اشاره‌های شبیه‌سازی‌شده را دریافت نمی‌کند:

  1. مطمئن شوید صفحه‌نمایش ساعت فعال و روشن باشد. وقتی صفحه‌نمایش خاموش است یا در حالت محیطی قرار دارد، چارچوب اشاره‌ها اشاره‌ها را به برنامه‌ها ارسال نمی‌کند. برای بیدار کردن نمایشگر بااستفاده از ADB، این فرمان را اجرا کنید:

    adb shell input keyevent KEYCODE_WAKEUP
    
  2. بررسی کنید که آیا برنامه‌تان به‌عنوان مشترک اشاره فعال ثبت شده است و درحال‌حاضر تمرکز پنجره را دارد یا نه:

    adb shell cmd IWearGestureService get-active-gestures -readable
    

    وقتی صفحه اشاره برنامه شما در پیش‌زمینه باشد و صفحه‌نمایش روشن باشد، این فرمان [DoublePinch] یا [DoublePinch, WristTurn] را برمی‌گرداند. اگر فهرست خالی ([]) برگردانده شد، بررسی کنید که آیا پنجره شما در کانون توجه است یا محدودیت‌های خارج از بدن مانع فعال‌سازی می‌شوند.

  3. بررسی وضعیت سرویس اشاره داخلی و نشان‌های مشترک فعال:

    adb shell dumpsys IWearGestureService
    

منابع بیشتر

برای راهنمایی طراحی درباره زمان و مکان استفاده از اشاره‌های یک‌دستی، به اشاره‌های یک‌دستی مراجعه کنید.