لیست هایی با Compose for Wear OS


لیست‌ها به کاربران اجازه می‌دهند تا یک مورد را از مجموعه‌ای از گزینه‌ها در دستگاه‌های Wear OS انتخاب کنند.

بسیاری از دستگاه‌های Wear OS از صفحه نمایش‌های گرد استفاده می‌کنند که دیدن آیتم‌های لیست که در نزدیکی بالا و پایین صفحه نمایش ظاهر می‌شوند را دشوارتر می‌کند. به همین دلیل، Compose for Wear OS شامل نسخه‌ای از کلاس LazyColumn به نام TransformingLazyColumn است که از انیمیشن‌های مقیاس‌بندی و تغییر شکل پشتیبانی می‌کند. وقتی آیتم‌ها به لبه‌ها حرکت می‌کنند، کوچک‌تر و محو می‌شوند.

برای اعمال جلوه‌های مقیاس‌بندی و پیمایش توصیه‌شده:

  1. از Modifier.transformedHeight استفاده کنید تا Compose بتواند تغییر ارتفاع را هنگام اسکرول کردن آیتم در صفحه محاسبه کند.
  2. برای اعمال جلوه‌های بصری، از جمله کوچک کردن محتوای آیتم، از transformation = SurfaceTransformation(transformationSpec) استفاده کنید.
  3. برای کامپوننت‌هایی که transformation به عنوان پارامتر نمی‌پذیرند، مانند Text از یک TransformationSpec سفارشی استفاده کنید.

انیمیشن زیر نشان می‌دهد که چگونه یک عنصر لیست هنگام نزدیک شدن به بالا و پایین صفحه، تغییر اندازه می‌دهد و شکل آن تغییر می‌کند:

قطعه کد زیر نحوه ایجاد یک لیست با استفاده از طرح TransformingLazyColumn را نشان می‌دهد تا محتوایی ایجاد شود که در اندازه‌های مختلف صفحه نمایش Wear OS عالی به نظر برسد .

این قطعه کد همچنین استفاده از اصلاح‌کننده‌ی minimumVerticalContentPadding را نشان می‌دهد که باید آن را روی آیتم‌های لیست تنظیم کنید تا فاصله‌ی (padding) صحیح در بالا و پایین لیست اعمال شود.

برای نمایش نشانگر اسکرول، columnState بین ScreenScaffold و TransformingLazyColumn به اشتراک بگذارید:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec),
                onClick = { /* ... */ },
                icon = {
                    Icon(
                        imageVector = Icons.Default.Build,
                        contentDescription = "build",
                    )
                },
            ) {
                Text(
                    text = "Build",
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
        }
    }
}

یک افکت ضربه محکم و ناگهانی اضافه کنید

قابلیت Snapping تضمین می‌کند که وقتی کاربر اسکرول یا حرکت Fling را تمام می‌کند، لیست با یک آیتم که دقیقاً در یک نقطه خاص، معمولاً مرکز صفحه، قرار گرفته است، تنظیم شود. در صفحه‌های نمایش گرد، که آیتم‌ها با دور شدن از مرکز، تغییر اندازه می‌دهند و شکل می‌گیرند، Snapping به ویژه برای اطمینان از اینکه مرتبط‌ترین آیتم در ناحیه دید بهینه کاملاً قابل مشاهده و خوانا باقی می‌ماند، مفید است.

برای افزودن رفتار snap-and-fling، پارامتر flingBehavior را روی TransformingLazyColumnDefaults.snapFlingBehavior(columnState) تنظیم کنید. برای ایجاد یک تجربه سازگار هنگام استفاده از تاج یا قاب فیزیکی، rotaryScrollableBehavior را با استفاده از RotaryScrollableDefaults.snapBehavior(columnState) مطابقت دهید.

val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(scrollState = columnState) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        flingBehavior = TransformingLazyColumnDefaults.snapFlingBehavior(columnState),
        rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior(columnState)
    ) {
        // ...
        // ...
    }
}

طرح‌بندی معکوس

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

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

برای پشتیبانی از این موارد استفاده، TransformingLazyColumn به شما امکان می‌دهد با تنظیم reverseLayout = true ، طرح‌بندی را معکوس کنید. این کار لنگر لیست را از لبه بالا به لبه پایین تغییر می‌دهد.

برای راحتی، تنظیم reverseLayout = true ترتیب بصری آیتم‌ها و جهت اسکرول کردن را نیز معکوس می‌کند:

  • آیتم‌ها از پایین به بالا تشکیل می‌شوند، به این معنی که اندیس ۰ در پایین صفحه نمایش داده می‌شود.
  • با اسکرول کردن به بالا، آیتم‌هایی با شاخص‌های بالاتر نمایش داده می‌شوند.

برای افزودن رفتار snap-and-fling به همراه طرح‌بندی معکوس، می‌توانید flingBehavior و rotaryScrollableBehavior را همانطور که در قطعه کد زیر نشان داده شده است، ترکیب کنید:

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(scrollState = columnState) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding,
        reverseLayout = true,
        modifier = Modifier.fillMaxWidth()
    ) {
        items(10) { index ->
            Button(
                label = {
                    Text(
                        text = "Item ${index + 1}"
                    )
                },
                onClick = {},
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            )
        }
        item {
            // With reverseLayout = true, the last item declared appears at the top.
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text("Header")
            }
        }
    }
}

تصاویر زیر تفاوت بین یک لیست معمولی و یک لیست معکوس را نشان می‌دهند:

یک ستون TransformingLazyColumn با طرح‌بندی معمولی، که آیتم ۱ را در بالا و آیتم‌ها را به ترتیب صعودی نشان می‌دهد.
شکل ۱. یک طرح‌بندی استاندارد فهرست که در آن محتوا از بالا به پایین پر می‌شود.
یک ستون TransformingLazyColumn با طرح‌بندی معکوس، که آیتم ۱ را در پایین و آیتم‌ها را به ترتیب نزولی به سمت بالا نشان می‌دهد.
شکل ۲. طرح‌بندی لیست معکوس که در آن محتوا از پایین به بالا پر می‌شود.

دکمه‌های لبه‌ای در لیست‌ها

برای متریال ۳، می‌توانید یک EdgeButton اضافه کنید که یک دکمه‌ی لبه‌دار در پایین لیست‌ها است. با این حال، مراقب باشید که این را به عنوان یک آیتم در TransformingLazyColumn اضافه نکنید، بلکه از جایگاه edgeButton در ScreenScaffold استفاده کنید.

استفاده از اسلات edgeButton تضمین می‌کند که دکمه به درستی در پایین صفحه قرار گرفته و هنگام پیمایش لیست، رفتار مناسبی داشته باشد.

قطعه کد زیر نحوه پیاده‌سازی EdgeButton را نشان می‌دهد:

val columnState = rememberTransformingLazyColumnState()
ScreenScaffold(
    scrollState = columnState,
    edgeButton = {
        EdgeButton(
            onClick = { /* TODO */ },
            modifier = Modifier.scrollable(
                columnState,
                orientation = Orientation.Vertical,
                reverseDirection = true,
                // Apply overscroll to the EdgeButton for proper scrolling behavior.
                overscrollEffect = rememberOverscrollEffect(),
            )
        ) {
            Text("More")
        }
    }
) { contentPadding ->
    TransformingLazyColumn(
        contentPadding = contentPadding,
        state = columnState,
    ) {
        // ...
        // ...
    }
}

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

کامپوننت SwipeToReveal به شما امکان می‌دهد با کشیدن انگشت، به اقدامات مربوط به یک آیتم لیست، مانند Card یا Chip ، دسترسی پیدا کنید. کشیدن انگشت معمولاً یک یا دو دکمه عملیاتی (مانند "حذف" یا "بیشتر") را در کنار صفحه نمایش می‌دهد.

هنگام استفاده از SwipeToReveal درون یک TransformingLazyColumn ، این دستورالعمل‌ها را دنبال کنید:

  • تنظیم مجدد هنگام اسکرول : وقتی کاربر لیست را اسکرول می‌کند، هر آیتمی که با کشیدن انگشت باز شده را به حالت پوشیده شده‌اش برمی‌گرداند.
  • ارتفاع‌های ثابت : ارتفاع دکمه‌های عملیاتی را طوری تنظیم کنید که با آیتم داخلی که روی آن کشیده می‌شود (چه یک Button باشد و چه یک Card ) مطابقت داشته باشد تا ظاهری ثابت داشته باشد.
  • تغییر شکل دادن کانتینر : اصلاح‌کننده transformedHeight و transformationSpec را روی خود کامپوننت SwipeToReveal اعمال کنید.
  • تبدیل دوگانه انجام ندهید : اصلاح‌کننده‌های transformedHeight یا transformation را روی آیتم داخلیِ سوایپ‌شده (کارت یا دکمه‌ی داخل کانتینر SwipeToReveal ) اعمال نکنید.
{% کلمه به کلمه %} {% فعل کمکی %} {% کلمه به کلمه %} {% فعل کمکی %}