اسکرول، اسکرول

اصلاح کننده های اسکرول

اصلاح‌کننده‌های verticalScroll و horizontalScroll ساده‌ترین راه را برای کاربر فراهم می‌کنند که به کاربر اجازه می‌دهد یک عنصر را زمانی که محدوده محتویات آن بزرگ‌تر از حداکثر محدودیت اندازه آن است، اسکرول کند. با اصلاح‌کننده‌های verticalScroll و horizontalScroll نیازی به ترجمه یا افست کردن محتوا ندارید.

@Composable
private fun ScrollBoxes() {
    Column(
        modifier = Modifier
            .background(Color.LightGray)
            .size(100.dp)
            .verticalScroll(rememberScrollState())
    ) {
        repeat(10) {
            Text("Item $it", modifier = Modifier.padding(2.dp))
        }
    }
}

یک لیست عمودی ساده که به حرکات اسکرول پاسخ می دهد

ScrollState به شما امکان می دهد موقعیت اسکرول را تغییر دهید یا وضعیت فعلی آن را بدست آورید. برای ایجاد آن با پارامترهای پیش فرض، از rememberScrollState() استفاده کنید.

@Composable
private fun ScrollBoxesSmooth() {
    // Smoothly scroll 100px on first composition
    val state = rememberScrollState()
    LaunchedEffect(Unit) { state.animateScrollTo(100) }

    Column(
        modifier = Modifier
            .background(Color.LightGray)
            .size(100.dp)
            .padding(horizontal = 8.dp)
            .verticalScroll(state)
    ) {
        repeat(10) {
            Text("Item $it", modifier = Modifier.padding(2.dp))
        }
    }
}

اصلاح کننده قابل پیمایش

اصلاح‌کننده scrollable با اصلاح‌کننده‌های پیمایشی تفاوت دارد زیرا scrollable حرکات اسکرول را تشخیص می‌دهد و دلتاها را می‌گیرد، اما محتویات آن را به طور خودکار تعدیل نمی‌کند. در عوض از طریق ScrollableState به کاربر واگذار می‌شود، که برای درست کار کردن این اصلاح‌کننده لازم است.

هنگام ساخت ScrollableState باید یک تابع consumeScrollDelta ارائه کنید که در هر مرحله اسکرول (با ورودی اشاره، اسکرول صاف یا پرت کردن) با دلتا به پیکسل فراخوانی می شود. این تابع باید مقدار مسافت پیمایش مصرف شده را برگرداند تا اطمینان حاصل شود که در مواردی که عناصر تودرتو که دارای اصلاح کننده scrollable هستند، رویداد به درستی منتشر می شود.

قطعه زیر ژست‌ها را تشخیص می‌دهد و یک مقدار عددی برای یک افست نمایش می‌دهد، اما هیچ عنصری را افست نمی‌کند:

@Composable
private fun ScrollableSample() {
    // actual composable state
    var offset by remember { mutableStateOf(0f) }
    Box(
        Modifier
            .size(150.dp)
            .scrollable(
                orientation = Orientation.Vertical,
                // Scrollable state: describes how to consume
                // scrolling delta and update offset
                state = rememberScrollableState { delta ->
                    offset += delta
                    delta
                }
            )
            .background(Color.LightGray),
        contentAlignment = Alignment.Center
    ) {
        Text(offset.toString())
    }
}

یک عنصر UI که فشار انگشت را تشخیص می دهد و مقدار عددی مکان انگشت را نشان می دهد

پیمایش تو در تو

پیمایش تودرتو سیستمی است که در آن چندین مؤلفه اسکرول موجود در یکدیگر با واکنش به یک حرکت پیمایشی واحد و ارتباط دلتاهای پیمایشی (تغییرات) با هم کار می کنند.

سیستم پیمایش تو در تو، هماهنگی بین اجزایی که قابل پیمایش هستند و به صورت سلسله مراتبی به هم مرتبط هستند (اغلب با به اشتراک گذاری یک والد) امکان پذیر است. این سیستم کانتینرهای پیمایشی را به هم پیوند می‌دهد و امکان تعامل با دلتاهای پیمایشی را می‌دهد که در حال انتشار و اشتراک‌گذاری بین آن‌ها هستند.

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

پیمایش تو در تو خودکار

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

پیمایش تو در تو خودکار توسط برخی از مؤلفه‌ها و اصلاح‌کننده‌های Compose پشتیبانی و ارائه می‌شود: verticalScroll ، horizontalScroll ، scrollable ، Lazy API و TextField . این بدان معناست که وقتی کاربر یک فرزند درونی اجزای تودرتو را پیمایش می‌کند، اصلاح‌کننده‌های قبلی دلتاهای پیمایشی را به والدینی که پشتیبانی پیمایش تودرتو دارند منتشر می‌کنند.

مثال زیر عناصری را نشان می‌دهد که یک اصلاح‌کننده verticalScroll روی آن‌ها در داخل یک ظرف اعمال شده است که یک اصلاح‌کننده verticalScroll نیز روی آن اعمال شده است.

@Composable
private fun AutomaticNestedScroll() {
    val gradient = Brush.verticalGradient(0f to Color.Gray, 1000f to Color.White)
    Box(
        modifier = Modifier
            .background(Color.LightGray)
            .verticalScroll(rememberScrollState())
            .padding(32.dp)
    ) {
        Column {
            repeat(6) {
                Box(
                    modifier = Modifier
                        .height(128.dp)
                        .verticalScroll(rememberScrollState())
                ) {
                    Text(
                        "Scroll here",
                        modifier = Modifier
                            .border(12.dp, Color.DarkGray)
                            .background(brush = gradient)
                            .padding(24.dp)
                            .height(150.dp)
                    )
                }
            }
        }
    }
}

دو عنصر UI پیمایش عمودی تو در تو که به حرکات داخل و خارج عنصر داخلی پاسخ می دهند

با استفاده از اصلاح کننده nestedScroll

اگر نیاز به ایجاد یک اسکرول هماهنگ پیشرفته بین چندین عنصر دارید، اصلاح کننده nestedScroll با تعریف سلسله مراتب پیمایش تودرتو انعطاف پذیری بیشتری به شما می دهد. همانطور که در بخش قبل ذکر شد، برخی از مؤلفه ها دارای پشتیبانی داخلی تو در تو هستند. با این حال، برای کامپوزیتی‌هایی که به‌طور خودکار قابل پیمایش نیستند، مانند Box یا Column ، دلتاهای پیمایشی روی چنین مؤلفه‌هایی در سیستم پیمایش تودرتو منتشر نمی‌شوند و دلتاها به NestedScrollConnection یا مؤلفه والد نمی‌رسند. برای حل این مشکل، می‌توانید از nestedScroll برای ارائه چنین پشتیبانی به سایر مؤلفه‌ها، از جمله مؤلفه‌های سفارشی، استفاده کنید.

چرخه پیمایش تو در تو

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

مراحل چرخه پیمایش تو در تو

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

مراحل چرخه پیمایش تو در تو

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

مرحله قبل از اسکرول - ارسال به بالا

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

مرحله قبل از اسکرول - حباب کردن به پایین

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

فاز مصرف گره

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

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

مرحله پس از اسکرول - ارسال به بالا

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

مرحله پس از اسکرول - حباب کردن

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

در چرخه پیمایش تودرتو شرکت کنید

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

اگر چرخه پیمایش تودرتو سیستمی است که بر روی زنجیره ای از گره ها عمل می کند، اصلاح کننده nestedScroll راهی برای رهگیری و درج در این تغییرات و تأثیرگذاری بر داده ها (دلتاهای اسکرول) است که در زنجیره منتشر می شوند. این اصلاح کننده را می توان در هر جایی از سلسله مراتب قرار داد و با نمونه های اصلاح کننده اسکرول تودرتو در بالای درخت ارتباط برقرار می کند تا بتواند اطلاعات را از طریق این کانال به اشتراک بگذارد. بلوک های سازنده این اصلاح کننده NestedScrollConnection و NestedScrollDispatcher هستند.

NestedScrollConnection راهی برای پاسخ به مراحل چرخه پیمایش تودرتو و تأثیرگذاری بر سیستم پیمایش تو در تو فراهم می کند. این متشکل از چهار روش برگشت تماس است که هر کدام یکی از مراحل مصرف را نشان می‌دهد: پیش/پس از اسکرول و پیش/پس از پرتاب:

val nestedScrollConnection = object : NestedScrollConnection {
    override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
        println("Received onPreScroll callback.")
        return Offset.Zero
    }

    override fun onPostScroll(
        consumed: Offset,
        available: Offset,
        source: NestedScrollSource
    ): Offset {
        println("Received onPostScroll callback.")
        return Offset.Zero
    }
}

هر فراخوانی همچنین اطلاعاتی در مورد دلتای در حال انتشار می دهد: دلتای available برای آن فاز خاص و دلتای consumed مصرف شده در فازهای قبلی. اگر در هر نقطه ای بخواهید انتشار دلتا در سلسله مراتب را متوقف کنید، می توانید از اتصال پیمایش تودرتو برای این کار استفاده کنید:

val disabledNestedScrollConnection = remember {
    object : NestedScrollConnection {
        override fun onPostScroll(
            consumed: Offset,
            available: Offset,
            source: NestedScrollSource
        ): Offset {
            return if (source == NestedScrollSource.SideEffect) {
                available
            } else {
                Offset.Zero
            }
        }
    }
}

همه فراخوان‌ها اطلاعاتی در مورد نوع NestedScrollSource ارائه می‌کنند.

NestedScrollDispatcher چرخه پیمایش تودرتو را مقداردهی اولیه می کند. استفاده از دیسپچر و فراخوانی متدهای آن چرخه را راه اندازی می کند. ظروف قابل پیمایش دارای یک توزیع کننده داخلی هستند که دلتاهای گرفته شده در حین حرکات را به سیستم ارسال می کند. به همین دلیل، بیشتر موارد استفاده از سفارشی کردن پیمایش تودرتو شامل استفاده از NestedScrollConnection به جای توزیع کننده، برای واکنش به دلتاهای موجود به جای ارسال موارد جدید است. برای استفاده بیشتر به NestedScrollDispatcherSample مراجعه کنید.

تودرتو پیمایش interop

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

این موضوع نتیجه انتظارات ساخته شده در کامپوزیشن های قابل پیمایش است. ترکیب‌های قابل پیمایش دارای قانون «پیمایش تودرتو» هستند، به این معنی که هر ظرف قابل پیمایش باید در زنجیره پیمایش تودرتو مشارکت کند، هم به‌عنوان والد از طریق NestedScrollConnection و هم به‌عنوان فرزند از طریق NestedScrollDispatcher . هنگامی که کودک در محدوده است، کودک یک طومار تو در تو را برای والدین می راند. به عنوان مثال، این قانون به Compose Pager و Compose LazyRow اجازه می دهد تا به خوبی با هم کار کنند. با این حال، هنگامی که پیمایش قابلیت همکاری با ViewPager2 یا RecyclerView انجام می‌شود، چون NestedScrollingParent3 را پیاده‌سازی نمی‌کنند، پیمایش مداوم از فرزند به والد امکان‌پذیر نیست.

برای فعال کردن Nested Scroll Interop API بین عناصر View قابل پیمایش و composableهای قابل پیمایش، تودرتو در هر دو جهت، می‌توانید از API interop پیمایش تودرتو برای کاهش این مشکلات در سناریوهای زیر استفاده کنید.

یک View والدین همکار که حاوی ComposeView فرزند است

یک View والد همکار، نمایشی است که قبلاً NestedScrollingParent3 را پیاده‌سازی می‌کند و بنابراین می‌تواند دلتاهای پیمایشی را از یک فرزند تودرتوی همکاری‌کننده دریافت کند. ComposeView در این مورد به عنوان یک کودک عمل می کند و باید (غیر مستقیم) NestedScrollingChild3 را پیاده سازی کند. یک نمونه از والدین همکار androidx.coordinatorlayout.widget.CoordinatorLayout است.

اگر به قابلیت همکاری پیمایش تودرتو بین View کانتینرهای والد قابل پیمایش و composableهای فرزند قابل پیمایش تودرتو نیاز دارید، می توانید از rememberNestedScrollInteropConnection() استفاده کنید.

rememberNestedScrollInteropConnection() اجازه می دهد و NestedScrollConnection را به خاطر می آورد که قابلیت همکاری پیمایش تودرتو را بین یک View والد که NestedScrollingParent3 را اجرا می کند و یک فرزند Compose را فعال می کند. این باید همراه با یک اصلاح کننده nestedScroll استفاده شود. از آنجایی که پیمایش تودرتو به طور پیش‌فرض در سمت Compose فعال است، می‌توانید از این اتصال برای فعال کردن پیمایش تودرتو در سمت View و اضافه کردن منطق چسب لازم بین Views و Composable استفاده کنید.

یک مورد استفاده مکرر استفاده از CoordinatorLayout ، CollapsingToolbarLayout و یک فرزند composable است که در این مثال نشان داده شده است:

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <!--...-->

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

در Activity یا Fragment خود، باید فرزند خود را composable و NestedScrollConnection لازم را تنظیم کنید:

open class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalComposeUiApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<ComposeView>(R.id.compose_view).apply {
            setContent {
                val nestedScrollInterop = rememberNestedScrollInteropConnection()
                // Add the nested scroll connection to your top level @Composable element
                // using the nestedScroll modifier.
                LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop)) {
                    items(20) { item ->
                        Box(
                            modifier = Modifier
                                .padding(16.dp)
                                .height(56.dp)
                                .fillMaxWidth()
                                .background(Color.Gray),
                            contentAlignment = Alignment.Center
                        ) {
                            Text(item.toString())
                        }
                    }
                }
            }
        }
    }
}

یک والد قابل ترکیب حاوی AndroidView فرزند

این سناریو اجرای API interop پیمایش تودرتو در سمت Compose را پوشش می‌دهد - زمانی که یک Composable والدین حاوی AndroidView فرزند دارید. AndroidView NestedScrollDispatcher را پیاده‌سازی می‌کند، زیرا به‌عنوان فرزند برای یک والد پیمایشی Compose و همچنین NestedScrollingParent3 عمل می‌کند، زیرا به‌عنوان والد برای یک فرزند درحال پیمایش View عمل می‌کند. سپس والد نوشتن می‌تواند دلتاهای پیمایش تودرتو را از View فرزند قابل پیمایش تودرتو دریافت کند.

مثال زیر نشان می‌دهد که چگونه می‌توانید در این سناریو، به همراه نوار ابزار جمع‌شده Compose، به interop پیمایش تودرتو دست یابید:

@Composable
private fun NestedScrollInteropComposeParentWithAndroidChildExample() {
    val toolbarHeightPx = with(LocalDensity.current) { ToolbarHeight.roundToPx().toFloat() }
    val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }

    // Sets up the nested scroll connection between the Box composable parent
    // and the child AndroidView containing the RecyclerView
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                // Updates the toolbar offset based on the scroll to enable
                // collapsible behaviour
                val delta = available.y
                val newOffset = toolbarOffsetHeightPx.value + delta
                toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
                return Offset.Zero
            }
        }
    }

    Box(
        Modifier
            .fillMaxSize()
            .nestedScroll(nestedScrollConnection)
    ) {
        TopAppBar(
            modifier = Modifier
                .height(ToolbarHeight)
                .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) }
        )

        AndroidView(
            { context ->
                LayoutInflater.from(context)
                    .inflate(R.layout.view_in_compose_nested_scroll_interop, null).apply {
                        with(findViewById<RecyclerView>(R.id.main_list)) {
                            layoutManager = LinearLayoutManager(context, VERTICAL, false)
                            adapter = NestedScrollInteropAdapter()
                        }
                    }.also {
                        // Nested scrolling interop is enabled when
                        // nested scroll is enabled for the root View
                        ViewCompat.setNestedScrollingEnabled(it, true)
                    }
            },
            // ...
        )
    }
}

private class NestedScrollInteropAdapter :
    Adapter<NestedScrollInteropAdapter.NestedScrollInteropViewHolder>() {
    val items = (1..10).map { it.toString() }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): NestedScrollInteropViewHolder {
        return NestedScrollInteropViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(R.layout.list_item, parent, false)
        )
    }

    override fun onBindViewHolder(holder: NestedScrollInteropViewHolder, position: Int) {
        // ...
    }

    class NestedScrollInteropViewHolder(view: View) : ViewHolder(view) {
        fun bind(item: String) {
            // ...
        }
    }
    // ...
}

این مثال نشان می دهد که چگونه می توانید از API با یک اصلاح کننده scrollable استفاده کنید:

@Composable
fun ViewInComposeNestedScrollInteropExample() {
    Box(
        Modifier
            .fillMaxSize()
            .scrollable(rememberScrollableState {
                // View component deltas should be reflected in Compose
                // components that participate in nested scrolling
                it
            }, Orientation.Vertical)
    ) {
        AndroidView(
            { context ->
                LayoutInflater.from(context)
                    .inflate(android.R.layout.list_item, null)
                    .apply {
                        // Nested scrolling interop is enabled when
                        // nested scroll is enabled for the root View
                        ViewCompat.setNestedScrollingEnabled(this, true)
                    }
            }
        )
    }
}

و در نهایت، این مثال نشان می دهد که چگونه API interop پیمایش تودرتو با BottomSheetDialogFragment برای دستیابی به یک رفتار کشیدن و رد کردن موفقیت آمیز استفاده می شود:

class BottomSheetFragment : BottomSheetDialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val rootView: View = inflater.inflate(R.layout.fragment_bottom_sheet, container, false)

        rootView.findViewById<ComposeView>(R.id.compose_view).apply {
            setContent {
                val nestedScrollInterop = rememberNestedScrollInteropConnection()
                LazyColumn(
                    Modifier
                        .nestedScroll(nestedScrollInterop)
                        .fillMaxSize()
                ) {
                    item {
                        Text(text = "Bottom sheet title")
                    }
                    items(10) {
                        Text(
                            text = "List item number $it",
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                }
            }
            return rootView
        }
    }
}

توجه داشته باشید که rememberNestedScrollInteropConnection() یک NestedScrollConnection را در عنصری که آن را به آن متصل می کنید نصب می کند. NestedScrollConnection مسئول انتقال دلتاها از سطح Compose به سطح View است. این عنصر را قادر می سازد تا در پیمایش تودرتو شرکت کند، اما پیمایش عناصر را به صورت خودکار فعال نمی کند. برای کامپوزیشن‌هایی که به‌طور خودکار قابل پیمایش نیستند، مانند Box یا Column ، دلتاهای پیمایش روی چنین مؤلفه‌هایی در سیستم پیمایش تودرتو منتشر نمی‌شوند و دلتاها به NestedScrollConnection ارائه‌شده توسط rememberNestedScrollInteropConnection() نمی‌رسند، بنابراین آن دلتاها نمی‌توانند به مؤلفه View والد برسید. برای حل این مشکل، مطمئن شوید که اصلاح‌کننده‌های قابل پیمایش را نیز برای این نوع ترکیب‌پذیرهای تودرتو تنظیم کرده‌اید. برای اطلاعات بیشتر می توانید به بخش قبلی در مورد پیمایش تودرتو مراجعه کنید.

یک View والدین غیر همکار که حاوی ComposeView فرزند است

یک View غیر همکار، نمایشی است که رابط های NestedScrolling لازم را در سمت View پیاده سازی نمی کند. توجه داشته باشید که این بدان معنی است که قابلیت همکاری پیمایش تودرتو با این Views به خوبی کار نمی کند. Views غیر همکار RecyclerView و ViewPager2 هستند.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}