بازگرداندن تمرکز

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

بازیابی تمرکز در محفظه‌های پیمایش‌شدنی

در Jetpack Compose، محفظه‌های پیمایش‌پذیر مانند LazyColumn،‏ LazyRow، و LazyVerticalGrid به‌طور خودکار به‌عنوان گروه‌های کانونی عمل می‌کنند. برای فعال کردن بازیابی تمرکز در فهرست یا شبکه تنبل، اصلاح‌کننده focusRestorer را پیوست کنید:

LazyColumn(
    modifier = Modifier.focusRestorer()
) {
    items(items) { item ->
        Button(onClick = { /* Handle click */ }) {
            Text(item)
        }
    }
}

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

بازیابی تمرکز در «ردیف» و «ستون»

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

برای فعال کردن بازیابی تمرکز در Row یا Column، focusGroup را با focusRestorer ترکیب کنید:

Row(
    modifier = Modifier
        .focusGroup()
        .focusRestorer()
) {
    Button(onClick = { /* Action 1 */ }) {
        Text("First item")
    }
    Button(onClick = { /* Action 2 */ }) {
        Text("Second item")
    }
    Button(onClick = { /* Action 3 */ }) {
        Text("Third item")
    }
}

مشخص کردن هدف تمرکز بازگشتی

وقتی کانون برای اولین‌بار وارد ظرفی می‌شود، هیچ فرزند کانونی‌شده قبلی وجود ندارد. Compose از ترتیب تمرکز پیش‌فرض برای تعیین اینکه کدام فرزند تمرکز کند پیروی می‌کند.

می‌توانید با ارسال یک FocusRequester جایگزین به focusRestorer (یا یک لامبدا که یک FocusRequester را در نسخه‌های قبلی Compose برمی‌گرداند)، سفارشی کنید که کدام فرزند در اولین ورودی تمرکز را دریافت کند:

val firstItemRequester = remember { FocusRequester() }

LazyColumn(
    modifier = Modifier.focusRestorer(firstItemRequester)
) {
    itemsIndexed(items) { index, item ->
        val itemModifier = if (index == 0) {
            Modifier.focusRequester(firstItemRequester)
        } else {
            Modifier
        }
        Button(
            onClick = { /* Handle click */ },
            modifier = itemModifier
        ) {
            Text(item)
        }
    }
}

اگر قبلاً روی هیچ فرزند تمرکز نشده باشد (یا اگر بازیابی تمرکز ناموفق باشد)، Compose تمرکز را به هدف جایگزین مرتبط منتقل می‌کند.

در مؤلفه‌های پیمایش مثل NavigationRail،‏ NavigationBar، NavigationDrawer، یا TabRow، کاربران انتظار دارند هنگام ورود به مؤلفه از ناحیه محتوا، تمرکز روی مقصد انتخاب‌شده فعلی قرار گیرد.

می‌توانید با ترکیب کردن Modifier.focusGroup() با focusProperties و تنظیم کردن ویژگی onEnter (یا enter در نسخه‌های قدیمی‌تر Compose)، تمرکز را به مقصد فعال هدایت کنید:

val (homeRequester, searchRequester, settingsRequester) = remember { FocusRequester.createRefs() }

val selectedRequester = when (currentDestination) {
    "home" -> homeRequester
    "search" -> searchRequester
    "settings" -> settingsRequester
    else -> homeRequester
}

NavigationRail(
    modifier = modifier
        .focusProperties {
            // Redirect focus to the selected item when focus enters the navigation rail
            onEnter = { selectedRequester.requestFocus() }
        }
        .focusGroup()
) {
    NavigationRailItem(
        selected = currentDestination == "home",
        onClick = { onNavigate("home") },
        icon = { Icon(Icons.Default.Home, contentDescription = "Home") },
        label = { Text("Home") },
        modifier = Modifier.focusRequester(homeRequester)
    )
    NavigationRailItem(
        selected = currentDestination == "search",
        onClick = { onNavigate("search") },
        icon = { Icon(Icons.Default.Search, contentDescription = "Search") },
        label = { Text("Search") },
        modifier = Modifier.focusRequester(searchRequester)
    )
    NavigationRailItem(
        selected = currentDestination == "settings",
        onClick = { onNavigate("settings") },
        icon = { Icon(Icons.Default.Settings, contentDescription = "Settings") },
        label = { Text("Settings") },
        modifier = Modifier.focusRequester(settingsRequester)
    )
}

بازیابی تمرکز در انتقال‌های صفحه

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

برای حفظ و بازیابی تمرکز در سراسر انتقال‌های صفحه:

  1. محفظه را با FocusRequester مرتبط کنید.
  2. قبل‌از راه‌اندازی رویداد پیمایش، saveFocusedChild() را در FocusRequester محفظه فراخوانی کنید.
  3. وقتی کاربر به صفحه برمی‌گردد، تمرکز اولیه را روی محفظه درخواست کنید یا restoreFocusedChild() را فراخوانی کنید.