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

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

اصلاح‌کننده‌های 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))
        }
    }
}

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

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

اگرچه scrollableArea برای پیاده‌سازی‌های سفارشی استفاده می‌شود، اما شما معمولاً باید راه‌حل‌های آماده‌ای مانند verticalScroll ، horizontalScroll یا کامپوننت‌هایی مانند LazyColumn را برای لیست‌های پیمایش استاندارد ترجیح دهید. این کامپوننت‌های سطح بالاتر برای موارد استفاده رایج ساده‌تر هستند و خودشان با استفاده از scrollableArea ساخته می‌شوند.

تفاوت بین اصلاح‌کننده‌های scrollableArea و scrollable

تفاوت اصلی بین scrollableArea و scrollable در نحوه تفسیر حرکات اسکرول کاربر است:

  • scrollable (دلتای خام): دلتا مستقیماً حرکت فیزیکی ورودی کاربر (مثلاً کشیدن اشاره‌گر) روی صفحه را منعکس می‌کند.
  • scrollableArea (دلتای محتواگرا): delta از نظر معنایی معکوس شده است تا تغییر انتخاب شده در موقعیت اسکرول را نشان دهد تا به نظر برسد که محتوا با حرکت کاربر حرکت می‌کند، که معمولاً برعکس حرکت اشاره‌گر است.

به این شکل به آن فکر کنید: scrollable به شما می‌گوید که اشاره‌گر چگونه حرکت کرده است، در حالی که scrollableArea آن حرکت اشاره‌گر را به نحوه حرکت محتوا در یک نمای پیمایش‌پذیر معمولی تبدیل می‌کند. این وارونگی دلیل طبیعی‌تر به نظر رسیدن scrollableArea هنگام پیاده‌سازی یک کانتینر پیمایش‌پذیر استاندارد است.

جدول زیر علائم دلتا را برای سناریوهای رایج خلاصه می‌کند:

ژست کاربر

دلتا توسط scrollable به dispatchRawDelta گزارش شد

دلتا توسط scrollableArea به dispatchRawDelta گزارش شد *

اشاره‌گر به سمت بالا حرکت می‌کند

منفی

مثبت

اشاره‌گر به پایین حرکت می‌کند

مثبت

منفی

اشاره‌گر به سمت چپ حرکت می‌کند

منفی

مثبت (منفی برای RTL)

اشاره‌گر به سمت راست حرکت می‌کند

مثبت

منفی (مثبت برای RTL)

(*) نکته‌ای در مورد علامت دلتای scrollableArea : علامت دلتای scrollableArea فقط یک وارونگی ساده نیست. این علامت هوشمندانه موارد زیر را در نظر می‌گیرد:

  1. جهت : عمودی یا افقی.
  2. LayoutDirection : چپ به راست یا راست به چپ (به‌ویژه برای پیمایش افقی مهم است).
  3. پرچم reverseScrolling : آیا جهت اسکرول معکوس است یا خیر.

علاوه بر معکوس کردن دلتای اسکرول، scrollableArea همچنین محتوا را به مرزهای طرح‌بندی می‌چسباند و رندر جلوه‌های overscroll را مدیریت می‌کند. به طور پیش‌فرض، از جلوه‌ای که توسط LocalOverscrollFactory ارائه می‌شود استفاده می‌کند. می‌توانید این را با استفاده از overload scrollableArea که یک پارامتر OverscrollEffect می‌پذیرد، سفارشی یا غیرفعال کنید.

چه زمانی از اصلاح‌کننده‌ی scrollableArea استفاده کنیم؟

شما باید از اصلاح‌کننده scrollableArea زمانی استفاده کنید که نیاز به ساخت یک کامپوننت اسکرول سفارشی دارید که به اندازه کافی توسط اصلاح‌کننده‌های horizontalScroll یا verticalScroll یا طرح‌بندی‌های Lazy پشتیبانی نمی‌شود. این اغلب شامل مواردی با موارد زیر است:

  • منطق طرح‌بندی سفارشی : زمانی که چیدمان آیتم‌ها به صورت پویا بر اساس موقعیت اسکرول تغییر می‌کند.
  • جلوه‌های بصری منحصر به فرد : اعمال تغییرات، مقیاس‌بندی یا سایر جلوه‌ها به عناصر کودک هنگام پیمایش آنها.
  • کنترل مستقیم : نیاز به کنترل دقیق‌تر بر روی مکانیزم‌های اسکرول، فراتر از آنچه که طرح‌بندی‌های verticalScroll یا Lazy ارائه می‌دهند.

ایجاد لیست‌های چرخ‌مانند سفارشی با استفاده از scrollableArea

نمونه زیر استفاده از scrollableArea را برای ساخت یک لیست عمودی سفارشی نشان می‌دهد که در آن آیتم‌ها با دور شدن از مرکز، کوچک می‌شوند و یک جلوه بصری "چرخ مانند" ایجاد می‌کنند. این نوع تبدیل وابسته به اسکرول، یک مورد استفاده عالی برای scrollableArea است.

شکل ۲. یک لیست عمودی سفارشی با استفاده از scrollableArea .

@Composable
private fun ScrollableAreaSample() {
    // ...
    Layout(
        modifier =
            Modifier
                .size(150.dp)
                .scrollableArea(scrollState, Orientation.Vertical)
                .background(Color.LightGray),
        // ...
    ) { measurables, constraints ->
        // ...
        // Update the maximum scroll value to not scroll beyond limits and stop when scroll
        // reaches the end.
        scrollState.maxValue = (totalHeight - viewportHeight).coerceAtLeast(0)

        // Position the children within the layout.
        layout(constraints.maxWidth, viewportHeight) {
            // The current vertical scroll position, in pixels.
            val scrollY = scrollState.value
            val viewportCenterY = scrollY + viewportHeight / 2

            var placeableLayoutPositionY = 0
            placeables.forEach { placeable ->
                // This sample applies a scaling effect to items based on their distance
                // from the center, creating a wheel-like effect.
                // ...
                // Place the item horizontally centered with a layer transformation for
                // scaling to achieve wheel-like effect.
                placeable.placeRelativeWithLayer(
                    x = constraints.maxWidth / 2 - placeable.width / 2,
                    // Offset y by the scroll position to make placeable visible in the viewport.
                    y = placeableLayoutPositionY - scrollY,
                ) {
                    scaleX = scaleFactor
                    scaleY = scaleFactor
                }
                // Move to the next item's vertical position.
                placeableLayoutPositionY += placeable.height
            }
        }
    }
}
// ...

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

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

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

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

@Composable
private fun ScrollableSample() {
    // actual composable state
    var offset by remember { mutableFloatStateOf(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())
    }
}

یک عنصر رابط کاربری که فشار انگشت را تشخیص می‌دهد و مقدار عددی محل انگشت را نمایش می‌دهد
شکل ۳. یک عنصر رابط کاربری که فشار انگشت را تشخیص می‌دهد و مقدار عددی محل انگشت را نمایش می‌دهد.
{% کلمه به کلمه %} {% فعل کمکی %} {% کلمه به کلمه %} {% فعل کمکی %}