انتقال CoordinatorLayout به Compose

CoordinatorLayout یک ViewGroup است که چیدمان‌های پیچیده، هم‌پوشان، و تودرتو را فعال می‌کند. این عنصر به‌عنوان محفظه‌ای برای فعال کردن تعاملات خاص «طراحی مواد» مانند گسترش/جمع کردن نوارابزارها و برگه‌های پایین، برای «نماهای» موجود در آن استفاده می‌شود.

در Compose، نزدیک‌ترین معادل CoordinatorLayout، Scaffold است. Scaffold جایگاه‌های محتوایی را برای ترکیب کردن «مؤلفه‌های Material» در الگوها و تعامل‌های رایج صفحه ارائه می‌دهد. این صفحه توضیح می‌دهد که چگونه می‌توانید پیاده‌سازی CoordinatorLayout خود را برای استفاده از Scaffold در Compose انتقال دهید.

مراحل انتقال

برای انتقال CoordinatorLayout به Scaffold، این مراحل را دنبال کنید:

  1. در تکه‌کد زیر، CoordinatorLayout حاوی AppBarLayout برای حاوی ToolBar، ViewPager، و FloatingActionButton است. CoordinatorLayout و فرزندان آن را از سلسله‌مراتب میانای کاربری خود حذف کنید و یک ComposeView برای جایگزینی آن اضافه کنید.

    ```xml

    <!-- AppBarLayout contents here -->
    

    ```

  2. در Fragment یا Activity، مرجعی برای ComposeView که به‌تازگی اضافه کرده‌اید دریافت کنید و روش setContent را در آن فراخوانی کنید. در بدنه روش، Scaffold را به‌عنوان محتوای آن تنظیم کنید:

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            // Scaffold contents
            // ...
        }
    }

  3. در محتوای Scaffold، محتوای اصلی صفحه‌تان را به آن اضافه کنید. چون محتوای اصلی در XML بالا ViewPager2 است، از HorizontalPager استفاده می‌کنیم که معادل Compose آن است. ‫content lambda از Scaffold نیز نمونه‌ای از PaddingValues را دریافت می‌کند که باید به ریشه محتوا اعمال شود. می‌توانید از Modifier.padding برای اعمال همان PaddingValues به HorizontalPager استفاده کنید.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. از جایگاه‌های محتوای دیگری که Scaffold ارائه می‌دهد استفاده کنید تا عناصر صفحه بیشتری اضافه کنید و «نماهای» فرزند باقی‌مانده را منتقل کنید. می‌توانید از جایگاه topBar برای افزودن TopAppBar و از جایگاه floatingActionButton برای ارائه FloatingActionButton استفاده کنید.

    composeView.setContent {
        Scaffold(
            Modifier.fillMaxSize(),
            topBar = {
                TopAppBar(
                    title = {
                        Text("My App")
                    }
                )
            },
            floatingActionButton = {
                FloatingActionButton(
                    onClick = { /* Handle click */ }
                ) {
                    Icon(
                        Icons.Filled.Add,
                        contentDescription = "Add Button"
                    )
                }
            }
        ) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

موارد استفاده رایج

جمع کردن و ازهم بازکردن نوارابزارها

در سیستم View، برای جمع کردن و ازهم باز کردن نوارابزار با CoordinatorLayout، از AppBarLayout به‌عنوان محفظه‌ای برای نوارابزار استفاده می‌کنید. سپس می‌توانید Behavior تا layout_behavior را در XML در «نمای» پیمایشی مرتبط (مانند RecyclerView یا NestedScrollView) مشخص کنید تا نحوه جمع شدن/ازهم باز شدن نوارابزار را هنگام پیمایش اعلام کنید.

در Compose، می‌توانید ازطریق TopAppBarScrollBehavior به جلوه مشابهی دست پیدا کنید. برای مثال، برای پیاده‌سازی نوارابزار جمع‌شونده/گسترش‌یابنده به‌طوری‌که نوارابزار هنگام پیمایش به‌بالا ظاهر شود، این مراحل را دنبال کنید:

  1. برای ایجاد TopAppBarScrollBehavior، با TopAppBarDefaults.enterAlwaysScrollBehavior() تماس بگیرید.
  2. TopAppBarScrollBehavior ایجادشده را به TopAppBar ارائه دهید.
  3. NestedScrollConnection را ازطریق Modifier.nestedScroll در Scaffold متصل کنید تا Scaffold بتواند رویدادهای پیمایش تودرتو را هنگام پیمایش محتوای پیمایش‌شدنی به بالا/پایین دریافت کند. به‌این‌ترتیب، نوار برنامه موجود می‌تواند به‌طور مناسب با پیمایش محتوا جمع/باز شود.

    // 1. Create the TopAppBarScrollBehavior
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text("My App")
                },
                // 2. Provide scrollBehavior to TopAppBar
                scrollBehavior = scrollBehavior
            )
        },
        // 3. Connect the scrollBehavior.nestedScrollConnection to the Scaffold
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(scrollBehavior.nestedScrollConnection)
    ) { contentPadding ->
        /* Contents */
        // ...
    }

سفارشی‌سازی کردن جلوه پیمایش جمع‌شونده/گسترش‌یابنده

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

برای ایجاد یک جلوه کاملاً سفارشی (مثلاً جلوه اختلاف منظر)، می‌توانید NestedScrollConnection خودتان را نیز ایجاد کنید و نوارابزار را به‌صورت دستی با پیمایش محتوا جابه‌جا کنید. برای نمونه کد، نمونه پیمایش تودرتو را در AOSP ببینید.

کشوها

با «نماها»، کشوی پیمایش را بااستفاده از DrawerLayout به‌عنوان نمای ریشه پیاده‌سازی می‌کنید. به‌نوبه خود، CoordinatorLayout شما نمای فرعی DrawerLayout است. DrawerLayout همچنین حاوی نمای فرزند دیگری است، مانند NavigationView، تا گزینه‌های پیمایش را در کشو نمایش دهد.

در Compose، می‌توانید بااستفاده از ترکیب‌شدنی ModalNavigationDrawer، کشوی پیمایش را پیاده‌سازی کنید. ‫ModalNavigationDrawer یک جایگاه drawerContent برای کشو و یک جایگاه content برای محتوای صفحه ارائه می‌دهد.

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    Scaffold(Modifier.fillMaxSize()) { contentPadding ->
        // Scaffold content
        // ...
    }
}

برای کسب اطلاعات بیشتر، کشوها را ببینید.

نوار توضیحات

‫Scaffold یک شکاف snackbarHost ارائه می‌دهد که می‌تواند یک ترکیب‌پذیر SnackbarHost را برای نمایش Snackbar بپذیرد.

val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState)
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            text = { Text("Show snackbar") },
            icon = { Icon(Icons.Filled.Image, contentDescription = "") },
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("Snackbar")
                }
            }
        )
    }
) { contentPadding ->
    // Screen content
    // ...
}

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

بیشتر بدانید

برای اطلاعات بیشتر درباره انتقال CoordinatorLayout به Compose، منابع زیر را ببینید: