سفارشی کردن انیمیشن ها

بسیاری از API های انیمیشن معمولاً پارامترهایی را برای سفارشی کردن رفتار خود می پذیرند.

انیمیشن ها را با پارامتر AnimationSpec سفارشی کنید

اکثر API های انیمیشن به توسعه دهندگان اجازه می دهند تا مشخصات انیمیشن را با یک پارامتر اختیاری AnimationSpec شخصی سازی کنند.

val alpha: Float by animateFloatAsState(
    targetValue = if (enabled) 1f else 0.5f,
    // Configure the animation duration and easing.
    animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),
    label = "alpha"
)

انواع مختلفی از AnimationSpec برای ایجاد انواع مختلف انیمیشن وجود دارد.

با spring انیمیشن مبتنی بر فیزیک بسازید

spring یک انیمیشن مبتنی بر فیزیک بین مقادیر شروع و پایان ایجاد می کند. 2 پارامتر نیاز دارد: dampingRatio و stiffness .

dampingRatio تعیین می کند که فنر چقدر باید فنر باشد. مقدار پیش فرض Spring.DampingRatioNoBouncy است.

شکل 1. تنظیم نسبت های مختلف میرایی فنر.

stiffness تعیین می کند که فنر با چه سرعتی باید به سمت مقدار نهایی حرکت کند. مقدار پیش فرض Spring.StiffnessMedium است.

شکل 2. تنظیم سفتی فنرهای مختلف

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioHighBouncy,
        stiffness = Spring.StiffnessMedium
    ),
    label = "spring spec"
)

spring می‌تواند وقفه‌ها را راحت‌تر از انواع AnimationSpec مبتنی بر مدت زمان کنترل کند، زیرا تداوم سرعت را هنگام تغییر مقدار هدف در میان انیمیشن‌ها تضمین می‌کند. spring به عنوان AnimationSpec پیش فرض توسط بسیاری از APIهای انیمیشن مانند animate*AsState و updateTransition استفاده می شود.

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

شکل 3. تنظیم مشخصات tween مقابل spring برای انیمیشن، و قطع آن.

متحرک سازی بین مقادیر شروع و پایان با منحنی کاهش با tween

بین مقادیر شروع و پایان در طول durationMillis مشخص شده Millis با استفاده از یک منحنی کاهش متحرک سازی tween . tween مخفف کلمه between - زیرا بین دو مقدار است.

همچنین می توانید delayMillis برای به تعویق انداختن شروع انیمیشن مشخص کنید.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = tween(
        durationMillis = 300,
        delayMillis = 50,
        easing = LinearOutSlowInEasing
    ),
    label = "tween delay"
)

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

با استفاده از keyframes ، در زمان‌های خاص به مقادیر خاصی متحرک شوید

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

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

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = keyframes {
        durationMillis = 375
        0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms
        0.2f at 15 using FastOutLinearInEasing // for 15-75 ms
        0.4f at 75 // ms
        0.4f at 225 // ms
    },
    label = "keyframe"
)

یک انیمیشن را با repeatable تکرار کنید

repeatable یک انیمیشن مبتنی بر مدت زمان (مانند tween یا keyframes ) را به طور مکرر اجرا می کند تا زمانی که به تعداد تکرار مشخص شده برسد. شما می توانید پارامتر repeatMode را برای تعیین اینکه انیمیشن باید با شروع از ابتدا ( RepeatMode.Restart ) یا از پایان ( RepeatMode.Reverse ) تکرار شود، ارسال کنید.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = repeatable(
        iterations = 3,
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "repeatable spec"
)

یک انیمیشن را بی نهایت با infiniteRepeatable تکرار کنید

infiniteRepeatable مانند repeatable است، اما برای تعداد بی نهایت تکرار تکرار می شود.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = infiniteRepeatable(
        animation = tween(durationMillis = 300),
        repeatMode = RepeatMode.Reverse
    ),
    label = "infinite repeatable"
)

در تست‌هایی که از ComposeTestRule استفاده می‌کنند، انیمیشن‌هایی که از infiniteRepeatable استفاده می‌کنند اجرا نمی‌شوند. مؤلفه با استفاده از مقدار اولیه هر مقدار متحرک ارائه خواهد شد.

بلافاصله با snap به مقدار پایانی snap بزنید

snap یک AnimationSpec ویژه است که بلافاصله مقدار را به مقدار پایانی تغییر می دهد. برای تاخیر در شروع انیمیشن می توانید delayMillis را مشخص کنید.

val value by animateFloatAsState(
    targetValue = 1f,
    animationSpec = snap(delayMillis = 50),
    label = "snap spec"
)

یک تابع تسهیل سفارشی تنظیم کنید

عملیات AnimationSpec مبتنی بر مدت زمان (مانند tween یا keyframes ) از Easing برای تنظیم کسری انیمیشن استفاده می‌کند. این اجازه می دهد تا مقدار متحرک به جای حرکت با یک نرخ ثابت، سرعت و سرعت خود را کاهش دهد. کسر یک مقدار بین 0 (شروع) و 1.0 (پایان) است که نقطه فعلی در انیمیشن را نشان می دهد.

Easing در واقع تابعی است که مقدار کسری بین 0 و 1.0 می گیرد و یک float برمی گرداند. مقدار برگشتی می تواند خارج از مرز باشد تا بیش از حد یا کمتر از آن را نشان دهد. یک Easing سفارشی می تواند مانند کد زیر ایجاد شود.

val CustomEasing = Easing { fraction -> fraction * fraction }

@Composable
fun EasingUsage() {
    val value by animateFloatAsState(
        targetValue = 1f,
        animationSpec = tween(
            durationMillis = 300,
            easing = CustomEasing
        ),
        label = "custom easing"
    )
    // ……
}

Compose چندین عملکرد Easing داخلی را ارائه می دهد که بیشتر موارد استفاده را پوشش می دهد. به Speed ​​- Material Design برای اطلاعات بیشتر در مورد اینکه از چه Easing بسته به سناریوی شما استفاده کنید، مراجعه کنید.

  • FastOutSlowInEasing
  • LinearOutSlowInEasing
  • FastOutLinearEasing
  • LinearEasing
  • CubicBezierEasing
  • بیشتر ببینید

با تبدیل و تبدیل به AnimationVector ، انواع داده های سفارشی را متحرک کنید

اکثر APIهای انیمیشن Compose به طور پیش‌فرض از Float ، Color ، Dp و دیگر انواع داده‌های پایه به عنوان مقادیر انیمیشن پشتیبانی می‌کنند، اما گاهی اوقات لازم است انواع داده‌های دیگر از جمله انواع سفارشی خود را متحرک کنید. در طول انیمیشن، هر مقدار متحرک به عنوان AnimationVector نشان داده می شود. مقدار به یک AnimationVector و بالعکس توسط TwoWayConverter مربوطه تبدیل می شود تا سیستم انیمیشن هسته بتواند آنها را به طور یکنواخت مدیریت کند. به عنوان مثال، یک Int به عنوان AnimationVector1D نشان داده می شود که دارای یک مقدار شناور واحد است. TwoWayConverter برای Int به شکل زیر است:

val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
    TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })

Color اساسا مجموعه ای از 4 مقدار قرمز، سبز، آبی و آلفا است، بنابراین Color به AnimationVector4D تبدیل می شود که دارای 4 مقدار شناور است. به این ترتیب، هر نوع داده ای که در انیمیشن ها استفاده می شود بسته به ابعاد آن به AnimationVector1D ، AnimationVector2D ، AnimationVector3D یا AnimationVector4D تبدیل می شود. این اجازه می دهد تا اجزای مختلف جسم به طور مستقل متحرک شوند، هر کدام با ردیابی سرعت خاص خود. با استفاده از مبدل هایی مانند Color.VectorConverter یا Dp.VectorConverter می توان به مبدل های داخلی برای انواع داده های پایه دسترسی داشت.

هنگامی که می خواهید پشتیبانی از یک نوع داده جدید را به عنوان مقدار متحرک اضافه کنید، می توانید TwoWayConverter خود را ایجاد کرده و آن را به API ارائه دهید. به عنوان مثال، می توانید از animateValueAsState برای متحرک سازی نوع داده سفارشی خود مانند این استفاده کنید:

data class MySize(val width: Dp, val height: Dp)

@Composable
fun MyAnimation(targetSize: MySize) {
    val animSize: MySize by animateValueAsState(
        targetSize,
        TwoWayConverter(
            convertToVector = { size: MySize ->
                // Extract a float value from each of the `Dp` fields.
                AnimationVector2D(size.width.value, size.height.value)
            },
            convertFromVector = { vector: AnimationVector2D ->
                MySize(vector.v1.dp, vector.v2.dp)
            }
        ),
        label = "size"
    )
}

لیست زیر شامل برخی از VectorConverter داخلی است:

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