iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
Mobile Development

github裡永遠有一個還沒做的SideProject :用Kotlin來開發點沒用的酷東西系列 第 21

Day21:Jetpack Compose中使用AnimatedVisibility呈現元件的動畫方法

  • 分享至 

  • xImage
  •  

前言

經過我們20天的努力,我們成功完成了一個沒有用的app(除非你和我的工作流是一樣的,不然這app應該是對你沒啥用),今天我們要讓來他變酷一點(...?)

AnimatedVisibility

AnimatedVisibility是Jetpack Compose中用來實現元素顯示與隱藏時附帶動畫效果的API。透過 AnimatedVisibility,我們可以在狀態變化時平滑地控制UI元素的可見性,而不用手動設置動畫過渡。它適合應用於當我們需要隨著狀態改變,讓某些UI元素在出現或消失時添加過渡動畫的場景。

  • AnimatedVisibility基本屬性
基本屬性 說明
visible 控制這個 UI 元素是否可見。當 visible = true,元素會顯示;當 visible = false,元素會隱藏。
enter 設置元素顯示時的動畫效果,例如淡入、滑入、展開等。
exit 設置元素隱藏時的動畫效果,例如淡出、滑出、收縮等。

下面我們舉三個例子做示範

1.淡入淡出效果

  • kotlin
@Composable
fun AnimatedVisibilityExample() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(text = if (isVisible) "Hide" else "Show")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(
            visible = isVisible,
            enter = fadeIn(),
            exit = fadeOut()
        ) {
            Text(text = "Hello, I'm visible!", style = MaterialTheme.typography.bodyLarge)
        }
    }
}

當你點擊按鈕時,會切換isVisible狀態,進而控制AnimatedVisibilityvisible屬性,讓內部的Text元素顯示或隱藏。

2.垂直滑入滑出動畫

  • kotlin
@Composable
fun CustomAnimatedVisibilityExample() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(text = if (isVisible) "Hide" else "Show")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(
            visible = isVisible,
            enter = slideInVertically { fullHeight -> fullHeight } + fadeIn(),
            exit = slideOutVertically { fullHeight -> fullHeight } + fadeOut()
        ) {
            Text(text = "Slide and Fade!", style = MaterialTheme.typography.bodyLarge)
        }
    }
}

透過slideInVerticallyslideOutVertically函數實現了從底部滑入和滑出的效果,並且搭配fadeIn()fadeOut()讓過渡更順暢。

3.垂直展開與收縮動畫

  • kotlin
@Composable
fun ExpandShrinkVisibilityExample() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(text = if (isVisible) "Hide" else "Show")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(
            visible = isVisible,
            enter = expandVertically() + fadeIn(),
            exit = shrinkVertically() + fadeOut()
        ) {
            Text(text = "Expand and Shrink!", style = MaterialTheme.typography.bodyLarge)
        }
    }
}

使用expandVertically()shrinkVertically()函數控制了元素的展開和收縮,並且搭配fadeIn()fadeOut()讓過渡更順暢。

完整測試的程式碼如下

  • kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.IntOffset

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TestAnimatedVisibility()
        }
    }
}

@Composable
fun TestAnimatedVisibility() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        // 第一個範例:淡入淡出
        AnimatedVisibilityExample()

        Spacer(modifier = Modifier.height(40.dp))

        // 第二個範例:自訂垂直滑入與滑出
        CustomAnimatedVisibilityExample()

        Spacer(modifier = Modifier.height(40.dp))

        // 第三個範例:垂直展開與收縮
        ExpandShrinkVisibilityExample()
    }
}

// 範例 1: 基本的淡入淡出動畫
@Composable
fun AnimatedVisibilityExample() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(text = if (isVisible) "Hide" else "Show")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(
            visible = isVisible,
            enter = fadeIn(),
            exit = fadeOut()
        ) {
            Text(text = "Hello, I'm visible!", style = MaterialTheme.typography.bodyLarge)
        }
    }
}

// 範例 2: 垂直滑入滑出動畫
@Composable
fun CustomAnimatedVisibilityExample() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(text = if (isVisible) "Hide" else "Show")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(
            visible = isVisible,
            enter = slideInVertically { fullHeight -> fullHeight } + fadeIn(),
            exit = slideOutVertically { fullHeight -> fullHeight } + fadeOut()
        ) {
            Text(text = "Slide and Fade!", style = MaterialTheme.typography.bodyLarge)
        }
    }
}

// 範例 3: 垂直展開與收縮動畫
@Composable
fun ExpandShrinkVisibilityExample() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(text = if (isVisible) "Hide" else "Show")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(
            visible = isVisible,
            enter = expandVertically() + fadeIn(),
            exit = shrinkVertically() + fadeOut()
        ) {
            Text(text = "Expand and Shrink!", style = MaterialTheme.typography.bodyLarge)
        }
    }
}

@Preview(showBackground = true)
@Composable
fun PreviewAnimatedVisibility() {
    TestAnimatedVisibility()
}

由於該功能是動畫功能,沒辦法用截圖呈現,我之後再找時間補上影片的測試樣本。

後話

今天稍微講了一下元件的動畫方法,主要是app目前想不到啥可加的,看著我的標題沒用的酷東西,沒用的東西弄好了,但沒有很酷,這時候我想到我第一次學ppt看到他能有動畫時的心情,確實很符合沒用的酷東西的標題,所以就拿這個內容水一下了,今天的內容就先到這邊,我們明天再見


上一篇
Day20:使用核取方塊元件來完成代辦事項,並將其同步到GOOGLE Task
下一篇
Day22:使用NavHost呈現啟動動畫
系列文
github裡永遠有一個還沒做的SideProject :用Kotlin來開發點沒用的酷東西30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言