استعادة التركيز

عندما يتنقّل المستخدمون في واجهات المستخدم المعقّدة باستخدام لوحة مفاتيح خارجية أو لوحة مفاتيح الاتجاهات، ينتقلون بشكل متكرّر بين أقسام مختلفة من الشاشة، مثل الانتقال من شريط التنقّل الجانبي إلى قائمة المحتوى، والتفاعل مع أحد العناصر، ثم الرجوع. تتيح استعادة التركيز للحاويات تذكُّر العنصر الثانوي الذي تم التركيز عليه سابقًا وإعادة التركيز عليه عند إعادة التركيز على الحاوية.

استعادة التركيز في الحاويات القابلة للتمرير

في 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 (أو تعبير lambda يعرض 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().