深入剖析 Android Compose 框架的自動動畫:AnimatedVisibility 與 AnimatedContent(二十四)

深入剖析 Android Compose 框架的自動動畫:AnimatedVisibility 與 AnimatedContent

引言

在 Android 應用開發中,動畫是提升用戶體驗的重要手段。它能夠讓界面元素的顯示與隱藏、狀態的切換變得更加自然和流暢,避免生硬的變化給用戶帶來不佳的感受。Android Compose 作為新一代的 Android UI 工具包,為開發者提供了強大而便捷的動畫支持,其中?AnimatedVisibility?和?AnimatedContent?這兩個組件是實現自動動畫的關鍵部分。

AnimatedVisibility?主要用于實現元素的顯示與隱藏動畫,開發者只需控制元素的可見性狀態,Compose 會自動為其添加過渡動畫。而?AnimatedContent?則專注于內容的動態變化動畫,當內容發生改變時,能夠平滑地過渡到新的內容。

本文將從源碼級別深入分析?AnimatedVisibility?和?AnimatedContent?這兩個組件,詳細解讀它們的實現原理、使用方法以及如何進行性能優化,幫助開發者更好地掌握 Android Compose 中的自動動畫技術。

一、Android Compose 自動動畫概述

1.1 自動動畫在 Android 開發中的重要性

在現代 Android 應用中,用戶對于界面的交互體驗要求越來越高。自動動畫能夠為應用帶來以下優勢:

  • 提升用戶體驗:通過自然流暢的動畫效果,讓用戶在操作界面時感受到更加舒適和愉悅,增強用戶對應用的好感度。例如,在顯示或隱藏一個菜單時,使用動畫過渡可以避免界面的突然變化,讓用戶更容易理解操作的結果。
  • 增強界面的可讀性:動畫可以引導用戶的注意力,使重要的信息更加突出。比如,在更新界面內容時,使用動畫過渡可以讓用戶更清晰地看到哪些內容發生了變化。
  • 提高應用的專業性:精美的動畫效果能夠讓應用看起來更加專業和高端,與競爭對手形成差異化。

1.2 Android Compose 中的自動動畫特性

Android Compose 為自動動畫提供了一系列簡潔而強大的 API,具有以下特性:

  • 聲明式編程:與傳統的 Android 動畫開發方式相比,Compose 采用聲明式編程模型,開發者只需描述動畫的起始和結束狀態,Compose 會自動處理中間的過渡過程,大大簡化了動畫的實現。
  • 高性能:Compose 對動畫進行了優化,能夠高效地利用系統資源,確保動畫的流暢性。它采用智能的重組機制,只有當動畫相關的狀態發生變化時,才會重新計算和繪制界面。
  • 可組合性:Compose 的動畫組件可以輕松地與其他組件組合使用,開發者可以根據需要創建復雜的動畫效果。

1.3?AnimatedVisibility?和?AnimatedContent?的基本概念

  • AnimatedVisibility:該組件用于控制元素的可見性,并在元素顯示或隱藏時添加動畫效果。開發者可以通過設置?visible?參數來控制元素的可見性,Compose 會自動應用預設的動畫或自定義動畫。

  • AnimatedContent:這個組件用于在內容發生變化時添加動畫過渡。當傳遞給?AnimatedContent?的內容發生改變時,它會平滑地過渡到新的內容,而不是直接替換。

下面是一個簡單的?AnimatedVisibility?示例:

kotlin

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*@OptIn(ExperimentalAnimationApi::class)
@Composable
fun SimpleAnimatedVisibilityExample() {// 定義一個可變狀態,用于控制元素的可見性var isVisible by remember { mutableStateOf(false) }// 創建一個按鈕,點擊時切換元素的可見性Button(onClick = { isVisible = !isVisible }) {Text(text = if (isVisible) "Hide" else "Show")}// 使用 AnimatedVisibility 組件,根據 isVisible 的值控制元素的顯示與隱藏,并添加淡入淡出動畫AnimatedVisibility(visible = isVisible,enter = fadeIn(),  // 元素顯示時的動畫exit = fadeOut()   // 元素隱藏時的動畫) {Text(text = "This is a visible text.")}
}

在這個示例中,我們通過一個按鈕來控制?Text?組件的可見性。當點擊按鈕時,isVisible?的值會發生變化,AnimatedVisibility?會根據這個值決定是否顯示?Text?組件,并應用相應的淡入淡出動畫。

二、AnimatedVisibility?源碼分析

2.1?AnimatedVisibility?的基本定義與結構

AnimatedVisibility?是一個 Composable 函數,其定義如下:

kotlin

@ExperimentalAnimationApi
@Composable
fun AnimatedVisibility(visible: Boolean,  // 控制元素的可見性modifier: Modifier = Modifier,  // 修飾符,用于設置組件的布局和樣式enter: EnterTransition = fadeIn() + expandVertically(),  // 元素顯示時的動畫exit: ExitTransition = fadeOut() + shrinkVertically(),  // 元素隱藏時的動畫initiallyVisible: Boolean = visible,  // 初始可見性content: @Composable () -> Unit  // 要顯示的內容
) {// 內部實現邏輯val transition = updateTransition(targetState = visible, label = "AnimatedVisibility")transition.AnimatedVisibilityScope(modifier = modifier,enter = enter,exit = exit,initiallyVisible = initiallyVisible,content = content)
}

從代碼中可以看出,AnimatedVisibility?接受多個參數:

  • visible:一個布爾值,用于控制元素的可見性。

  • modifier:用于設置組件的布局和樣式。

  • enter:元素顯示時的動畫,默認為淡入和垂直展開動畫。

  • exit:元素隱藏時的動畫,默認為淡出和垂直收縮動畫。

  • initiallyVisible:初始可見性,默認為?visible?的值。

  • content:要顯示的內容,是一個 Composable 函數。

在函數內部,首先調用?updateTransition?函數創建一個?Transition?對象,用于管理動畫的過渡狀態。然后調用?AnimatedVisibilityScope?函數,將過渡狀態、動畫和內容傳遞給它。

2.2?updateTransition?函數源碼解讀

updateTransition?函數用于創建一個?Transition?對象,其源碼如下:

kotlin

@Composable
fun <T> updateTransition(targetState: T,  // 目標狀態label: String = "Transition"  // 過渡的標簽,用于調試
): Transition<T> {// 創建一個可變狀態,用于存儲當前狀態val transitionState = remember { MutableTransitionState(targetState) }// 更新當前狀態為目標狀態transitionState.targetState = targetState// 返回一個 Transition 對象return remember(transitionState) {Transition(transitionState = transitionState,label = label)}
}

updateTransition?函數接受兩個參數:

  • targetState:目標狀態,即動畫要過渡到的狀態。

  • label:過渡的標簽,用于調試目的。

在函數內部,首先使用?remember?函數創建一個?MutableTransitionState?對象,用于存儲當前狀態。然后將目標狀態賦值給?targetState?屬性。最后,使用?remember?函數創建一個?Transition?對象,并返回它。

2.3?AnimatedVisibilityScope?函數源碼分析

AnimatedVisibilityScope?函數用于處理元素的顯示與隱藏動畫,其源碼如下:

kotlin

@ExperimentalAnimationApi
@Composable
fun Transition<Boolean>.AnimatedVisibilityScope(modifier: Modifier = Modifier,enter: EnterTransition = fadeIn() + expandVertically(),exit: ExitTransition = fadeOut() + shrinkVertically(),initiallyVisible: Boolean = currentState,content: @Composable () -> Unit
) {// 根據當前狀態和初始可見性計算是否需要執行動畫val shouldAnimate = initiallyVisible != currentState || initiallyVisible != targetState// 創建一個動畫狀態,用于控制元素的顯示與隱藏val visibleState = remember { MutableTransitionState(initiallyVisible) }visibleState.targetState = currentState// 根據是否需要執行動畫,決定是否應用動畫if (shouldAnimate) {val enterTransition = enter.createInitialValues(visibleState)val exitTransition = exit.createInitialValues(visibleState)val transition = updateTransition(visibleState, label = "AnimatedVisibilityScope")transition.AnimatedContent(modifier = modifier,transitionSpec = {if (targetState) {enterTransition} else {exitTransition}},content = content)} else {// 如果不需要執行動畫,直接顯示或隱藏內容if (currentState) {content()}}
}

AnimatedVisibilityScope?函數是?Transition<Boolean>?的擴展函數,接受多個參數:

  • modifier:用于設置組件的布局和樣式。

  • enter:元素顯示時的動畫。

  • exit:元素隱藏時的動畫。

  • initiallyVisible:初始可見性。

  • content:要顯示的內容。

在函數內部,首先計算是否需要執行動畫。如果需要執行動畫,則創建進入和退出動畫的初始值,并使用?updateTransition?函數創建一個新的?Transition?對象。然后調用?AnimatedContent?函數,根據目標狀態選擇合適的動畫進行過渡。如果不需要執行動畫,則直接根據當前狀態顯示或隱藏內容。

2.4?AnimatedVisibility?的使用示例與代碼解析

下面是一個更復雜的?AnimatedVisibility?使用示例:

kotlin

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.expandHorizontally
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp@OptIn(ExperimentalAnimationApi::class)
@Composable
fun ComplexAnimatedVisibilityExample() {// 定義一個可變狀態,用于控制元素的可見性var isVisible by remember { mutableStateOf(false) }// 創建一個 Column 組件,用于布局按鈕和要顯示的內容Column(modifier = Modifier.fillMaxWidth().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally) {// 創建一個按鈕,點擊時切換元素的可見性Button(onClick = { isVisible = !isVisible }) {Text(text = if (isVisible) "Hide" else "Show")}// 使用 AnimatedVisibility 組件,根據 isVisible 的值控制元素的顯示與隱藏,并添加水平展開和收縮動畫AnimatedVisibility(visible = isVisible,enter = fadeIn() + expandHorizontally(),  // 元素顯示時的動畫exit = fadeOut() + shrinkHorizontally()   // 元素隱藏時的動畫) {// 創建一個 Box 組件,設置背景顏色和高度Box(modifier = Modifier.fillMaxWidth().height(100.dp).background(Color.Blue).padding(16.dp)) {// 在 Box 中顯示文本Text(text = "This is a visible box.", color = Color.White)}}}
}

代碼解析:

  • 首先,使用?remember?函數創建一個可變狀態?isVisible,用于控制元素的可見性。
  • 然后,創建一個?Column?組件,用于布局按鈕和要顯示的內容。
  • 接著,創建一個按鈕,點擊時切換?isVisible?的值。
  • 最后,使用?AnimatedVisibility?組件,根據?isVisible?的值控制?Box?組件的顯示與隱藏。在顯示時,應用淡入和水平展開動畫;在隱藏時,應用淡出和水平收縮動畫。

三、AnimatedContent?源碼分析

3.1?AnimatedContent?的基本定義與結構

AnimatedContent?是一個 Composable 函數,用于在內容發生變化時添加動畫過渡,其定義如下:

kotlin

@ExperimentalAnimationApi
@Composable
fun <T> AnimatedContent(targetState: T,  // 目標狀態modifier: Modifier = Modifier,  // 修飾符,用于設置組件的布局和樣式transitionSpec: AnimatedContentScope<T>.() -> ContentTransform = {fadeIn() with fadeOut()},  // 過渡動畫的規范contentAlignment: Alignment = Alignment.TopStart,  // 內容的對齊方式content: @Composable AnimatedContentScope<T>.(T) -> Unit  // 要顯示的內容
) {// 內部實現邏輯val transition = updateTransition(targetState, label = "AnimatedContent")transition.AnimatedContent(modifier = modifier,transitionSpec = transitionSpec,contentAlignment = contentAlignment,content = content)
}

AnimatedContent?接受多個參數:

  • targetState:目標狀態,即內容要過渡到的狀態。

  • modifier:用于設置組件的布局和樣式。

  • transitionSpec:過渡動畫的規范,定義了內容變化時的動畫效果。

  • contentAlignment:內容的對齊方式,默認為左上角對齊。

  • content:要顯示的內容,是一個 Composable 函數,接受當前狀態作為參數。

在函數內部,首先調用?updateTransition?函數創建一個?Transition?對象,用于管理動畫的過渡狀態。然后調用?AnimatedContent?函數的擴展方法,將過渡狀態、過渡動畫規范、內容對齊方式和內容傳遞給它。

3.2?transitionSpec?參數的作用與實現

transitionSpec?參數是一個?AnimatedContentScope<T>.() -> ContentTransform?類型的函數,用于定義內容變化時的動畫效果。ContentTransform?是一個包含進入動畫和退出動畫的對象。

下面是一個自定義?transitionSpec?的示例:

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment@OptIn(ExperimentalAnimationApi::class)
@Composable
fun CustomTransitionSpecExample() {// 定義一個可變狀態,用于控制內容的變化var state by remember { mutableStateOf(1) }// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 使用 AnimatedContent 組件,根據 state 的值顯示不同的內容,并應用自定義過渡動畫AnimatedContent(targetState = state,transitionSpec = customTransitionSpec,contentAlignment = Alignment.Center) { currentState ->// 根據當前狀態顯示不同的文本Text(text = "State: $currentState")}// 創建一個按鈕,點擊時切換狀態Button(onClick = { state = if (state == 1) 2 else 1 }) {Text(text = "Change State")}
}

在這個示例中,我們自定義了一個?transitionSpec,定義了進入動畫為淡入和縮放進入,退出動畫為淡出和縮放退出,并添加了大小變換動畫。當點擊按鈕時,state?的值會發生變化,AnimatedContent?會根據新的狀態顯示不同的內容,并應用自定義的過渡動畫。

3.3?AnimatedContent?的內容更新與動畫觸發機制

AnimatedContent?的內容更新和動畫觸發機制主要依賴于?targetState?參數。當?targetState?的值發生變化時,AnimatedContent?會檢測到這個變化,并根據?transitionSpec?中定義的動畫效果進行過渡。

在?AnimatedContent?內部,updateTransition?函數會監聽?targetState?的變化,并創建一個?Transition?對象。當?targetState?發生變化時,Transition?對象會自動觸發動畫過渡。

3.4?AnimatedContent?的使用示例與代碼解析

下面是一個更詳細的?AnimatedContent?使用示例:

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@OptIn(ExperimentalAnimationApi::class)
@Composable
fun DetailedAnimatedContentExample() {// 定義一個可變狀態,用于控制內容的變化var state by remember { mutableStateOf("A") }// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 創建一個 Column 組件,用于布局按鈕和 AnimatedContent 組件Column(modifier = Modifier.fillMaxWidth().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally) {// 使用 AnimatedContent 組件,根據 state 的值顯示不同的內容,并應用自定義過渡動畫AnimatedContent(targetState = state,transitionSpec = customTransitionSpec,contentAlignment = Alignment.Center) { currentState ->// 根據當前狀態顯示不同的文本Box(modifier = Modifier.fillMaxWidth().padding(16.dp).background(if (currentState == "A") androidx.compose.ui.graphics.Color.Red else androidx.compose.ui.graphics.Color.Blue)) {Text(text = "State: $currentState", color = androidx.compose.ui.graphics.Color.White)}}// 創建兩個按鈕,分別用于切換到狀態 A 和狀態 BButton(onClick = { state = "A" }) {Text(text = "Change to State A")}Button(onClick = { state = "B" }) {Text(text = "Change to State B")}}
}

代碼解析:

  • 首先,使用?remember?函數創建一個可變狀態?state,用于控制內容的變化。
  • 然后,自定義一個?transitionSpec,定義了進入動畫、退出動畫和大小變換動畫。
  • 接著,創建一個?Column?組件,用于布局按鈕和?AnimatedContent?組件。
  • 在?AnimatedContent?組件中,根據?state?的值顯示不同的內容,并應用自定義的過渡動畫。
  • 最后,創建兩個按鈕,分別用于切換到狀態 A 和狀態 B。

四、AnimatedVisibility?與?AnimatedContent?的對比與結合

4.1?AnimatedVisibility?與?AnimatedContent?的功能對比

  • 功能側重點

    • AnimatedVisibility:主要側重于控制元素的可見性,并在顯示和隱藏元素時添加動畫效果。它關注的是元素的整體顯示與隱藏狀態的變化。
    • AnimatedContent:主要側重于在內容發生變化時添加動畫過渡。它關注的是內容的動態更新,而不僅僅是元素的可見性。
  • 使用場景

    • AnimatedVisibility:適用于需要顯示或隱藏某個元素的場景,如菜單的展開與收縮、提示信息的顯示與隱藏等。
    • AnimatedContent:適用于內容頻繁變化的場景,如列表項的更新、文本內容的切換等。

4.2 如何在項目中結合使用?AnimatedVisibility?與?AnimatedContent

在實際項目中,可以將?AnimatedVisibility?和?AnimatedContent?結合使用,以實現更復雜的動畫效果。下面是一個結合使用的示例:

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@OptIn(ExperimentalAnimationApi::class)
@Composable
fun CombinedExample() {// 定義一個可變狀態,用于控制元素的可見性var isVisible by remember { mutableStateOf(false) }// 定義一個可變狀態,用于控制內容的變化var state by remember { mutableStateOf("A") }// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 創建一個 Column 組件,用于布局按鈕、AnimatedVisibility 組件和 AnimatedContent 組件Column(modifier = Modifier.fillMaxWidth().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally) {// 創建一個按鈕,點擊時切換元素的可見性Button(onClick = { isVisible = !isVisible }) {Text(text = if (isVisible) "Hide" else "Show")}// 使用 AnimatedVisibility 組件,根據 isVisible 的值控制元素的顯示與隱藏,并添加淡入淡出動畫AnimatedVisibility(visible = isVisible,enter = fadeIn(),exit = fadeOut()) {// 使用 AnimatedContent 組件,根據 state 的值顯示不同的內容,并應用自定義過渡動畫AnimatedContent(targetState = state,transitionSpec = customTransitionSpec,contentAlignment = Alignment.Center) { currentState ->// 根據當前狀態顯示不同的文本Box(modifier = Modifier.fillMaxWidth().padding(16.dp).background(if (currentState == "A") androidx.compose.ui.graphics.Color.Red else androidx.compose.ui.graphics.Color.Blue)) {Text(text = "State: $currentState", color = androidx.compose.ui.graphics.Color.White)}}}// 創建兩個按鈕,分別用于切換到狀態 A 和狀態 BButton(onClick = { state = "A" }) {Text(text = "Change to State A")}Button(onClick = { state = "B" }) {Text(text = "Change to State B")}}
}

在這個示例中,我們使用?AnimatedVisibility?控制整個內容區域的顯示與隱藏,同時使用?AnimatedContent?控制內容區域內的內容變化。當點擊 “Show/Hide” 按鈕時,內容區域會淡入淡出顯示或隱藏;當點擊 “Change to State A” 或 “Change to State B” 按鈕時,內容區域內的內容會根據狀態的變化進行平滑過渡。

五、自動動畫的應用場景與案例分析

5.1 常見的應用場景舉例

菜單的展開與收縮

在很多應用中,會有菜單的展開與收縮功能。使用?AnimatedVisibility?可以輕松實現菜單的平滑展開和收縮動畫,提升用戶體驗。

kotlin

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MenuExpandCollapseExample() {// 定義一個可變狀態,用于控制菜單的可見性var isMenuVisible by remember { mutableStateOf(false) }// 創建一個 Column 組件,用于布局按鈕和菜單Column(modifier = Modifier.fillMaxWidth().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally) {// 創建一個按鈕,點擊時切換菜單的可見性Button(onClick = { isMenuVisible = !isMenuVisible }) {Text(text = if (isMenuVisible) "Collapse Menu" else "Expand Menu")}// 使用 AnimatedVisibility 組件,根據 isMenuVisible 的值控制菜單的顯示與隱藏,并添加淡入淡出和垂直滑動動畫AnimatedVisibility(visible = isMenuVisible,enter = fadeIn() + slideInVertically(),exit = fadeOut() + slideOutVertically()) {// 創建一個 Column 組件,用于布局菜單項Column(modifier = Modifier.fillMaxWidth().padding(16.dp),verticalArrangement = Arrangement.spacedBy(8.dp)) {// 菜單項 1Text(text = "Menu Item 1")// 菜單項 2Text(text = "Menu Item 2")// 菜單項 3Text(text = "Menu Item 3")}}}
}
數據加載提示

當應用需要加載數據時,可以使用?AnimatedVisibility?顯示加載提示,數據加載完成后隱藏提示。

kotlin

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay@OptIn(ExperimentalAnimationApi::class)
@Composable
fun DataLoadingExample() {// 定義一個可變狀態,用于控制加載提示的可見性var isLoading by remember { mutableStateOf(false) }// 創建一個 Box 組件,用于布局按鈕和加載提示Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center) {// 創建一個按鈕,點擊時模擬數據加載Button(onClick = {isLoading = true// 模擬 2 秒的數據加載時間LaunchedEffect(Unit) {delay(2000)isLoading = false}}) {Text(text = "Load Data")}// 使用 AnimatedVisibility 組件,根據 isLoading 的值控制加載提示的顯示與隱藏,并添加淡入淡出動畫AnimatedVisibility(visible = isLoading,enter = fadeIn(),exit = fadeOut()) {// 創建一個 Box 組件,用于布局加載進度指示器Box(modifier = Modifier.fillMaxWidth().padding(16.dp),contentAlignment = Alignment.Center) {// 加載進度指示器CircularProgressIndicator()}}}
}
列表項的更新

在列表中,當列表項的數據發生變化時,可以使用?AnimatedContent?實現平滑的過渡動畫。

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@OptIn(ExperimentalAnimationApi::class)
@Composable
fun ListItemUpdateExample() {// 定義一個可變狀態,用于存儲列表項的數據var itemData by remember { mutableStateOf("Initial Data") }// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 創建一個 Column 組件,用于布局按鈕和列表項Column(modifier = Modifier.fillMaxWidth().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally) {// 創建一個按鈕,點擊時更新列表項的數據Button(onClick = {itemData = "Updated Data"}) {Text(text = "Update Item")}// 使用 AnimatedContent 組件,根據 itemData 的值顯示不同的內容,并應用自定義過渡動畫AnimatedContent(targetState = itemData,transitionSpec = customTransitionSpec,contentAlignment = Alignment.Center) { currentData ->// 根據當前數據顯示不同的文本Text(text = "Item Data: $currentData")}}
}

5.2 實際項目案例分析

社交應用的消息列表更新

在社交應用的消息列表中,當有新消息到來時,需要更新列表并顯示新消息。可以使用?AnimatedContent?實現列表項的平滑更新動畫,讓用戶更清晰地看到新消息的到來。

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay@OptIn(ExperimentalAnimationApi::class)
@Composable
fun SocialMessageListExample() {// 定義一個可變狀態,用于存儲消息列表var messages by remember { mutableStateOf(listOf("Message 1", "Message 2")) }// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 模擬新消息到來LaunchedEffect(Unit) {delay(3000)messages = messages + "New Message"}// 創建一個 Column 組件,用于布局消息列表Column(modifier = Modifier.fillMaxWidth().padding(16.dp),verticalArrangement = Arrangement.spacedBy(8.dp)) {// 使用 AnimatedContent 組件,根據 messages 的值顯示不同的消息列表,并應用自定義過渡動畫AnimatedContent(targetState = messages,transitionSpec = customTransitionSpec,contentAlignment = Alignment.TopStart) { currentMessages ->// 遍歷消息列表,顯示每個消息current

五、自動動畫的應用場景與案例分析

5.2 實際項目案例分析

社交應用的消息列表更新

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay@OptIn(ExperimentalAnimationApi::class)
@Composable
fun SocialMessageListExample() {// 定義一個可變狀態,用于存儲消息列表var messages by remember { mutableStateOf(listOf("Message 1", "Message 2")) }// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 模擬新消息到來LaunchedEffect(Unit) {delay(3000)messages = messages + "New Message"}// 創建一個 Column 組件,用于布局消息列表Column(modifier = Modifier.fillMaxWidth().padding(16.dp),verticalArrangement = Arrangement.spacedBy(8.dp)) {// 使用 AnimatedContent 組件,根據 messages 的值顯示不同的消息列表,并應用自定義過渡動畫AnimatedContent(targetState = messages,transitionSpec = customTransitionSpec,contentAlignment = Alignment.TopStart) { currentMessages ->// 遍歷消息列表,顯示每個消息currentMessages.forEach { message ->Text(text = message,modifier = Modifier.fillMaxWidth().padding(8.dp))}}}
}

代碼分析

  • 狀態管理:通過?remember?創建可變狀態?messages?來存儲消息列表。初始時,消息列表包含兩條消息。
  • 過渡動畫規范customTransitionSpec?自定義了進入和退出動畫,使用?fadeIn?和?scaleIn?組合作為進入動畫,fadeOut?和?scaleOut?組合作為退出動畫,同時使用?SizeTransform?處理大小變換。
  • 模擬新消息:使用?LaunchedEffect?模擬 3 秒后有新消息到來,更新?messages?列表。
  • 消息列表顯示:使用?AnimatedContent?組件,根據?messages?的變化更新顯示的消息列表。當新消息到來時,新消息會以淡入和縮放的動畫效果顯示出來,舊消息則以淡出和縮放的動畫效果消失。
電商應用的商品篩選動畫

在電商應用中,用戶可能會使用篩選功能來查找特定的商品。可以使用?AnimatedVisibility?和?AnimatedContent?結合實現篩選條件的顯示與隱藏,以及篩選結果的平滑過渡。

kotlin

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp@OptIn(ExperimentalAnimationApi::class)
@Composable
fun EcommerceProductFilterExample() {// 定義一個可變狀態,用于控制篩選條件的可見性var isFilterVisible by remember { mutableStateOf(false) }// 定義一個可變狀態,用于存儲篩選條件var filter by remember { mutableStateOf("All") }// 模擬商品列表val allProducts = listOf("Product 1", "Product 2", "Product 3", "Product 4")// 根據篩選條件過濾商品列表val filteredProducts = when (filter) {"All" -> allProducts"Even" -> allProducts.filterIndexed { index, _ -> index % 2 == 0 }"Odd" -> allProducts.filterIndexed { index, _ -> index % 2 != 0 }else -> allProducts}// 自定義過渡動畫規范val customTransitionSpec = {// 定義進入動畫為淡入和縮放進入val enterTransition = fadeIn() + scaleIn()// 定義退出動畫為淡出和縮放退出val exitTransition = fadeOut() + scaleOut()// 定義大小變換動畫val sizeTransform = SizeTransform(clip = false)// 返回一個 ContentTransform 對象,包含進入動畫、退出動畫和大小變換動畫ContentTransform(targetContentEnter = enterTransition,initialContentExit = exitTransition,sizeTransform = sizeTransform)}// 創建一個 Column 組件,用于布局篩選按鈕、篩選條件和商品列表Column(modifier = Modifier.fillMaxWidth().padding(16.dp),verticalArrangement = Arrangement.spacedBy(8.dp)) {// 創建一個按鈕,點擊時切換篩選條件的可見性Button(onClick = { isFilterVisible = !isFilterVisible }) {Text(text = if (isFilterVisible) "Hide Filters" else "Show Filters")}// 使用 AnimatedVisibility 組件,根據 isFilterVisible 的值控制篩選條件的顯示與隱藏,并添加淡入淡出動畫AnimatedVisibility(visible = isFilterVisible,enter = fadeIn(),exit = fadeOut()) {// 創建一個 Column 組件,用于布局篩選條件按鈕Column(modifier = Modifier.fillMaxWidth().padding(8.dp),verticalArrangement = Arrangement.spacedBy(8.dp)) {// 全部篩選條件按鈕Button(onClick = { filter = "All" }) {Text(text = "All Products")}// 偶數索引商品篩選條件按鈕Button(onClick = { filter = "Even" }) {Text(text = "Even Index Products")}// 奇數索引商品篩選條件按鈕Button(onClick = { filter = "Odd" }) {Text(text = "Odd Index Products")}}}// 使用 AnimatedContent 組件,根據 filteredProducts 的值顯示不同的商品列表,并應用自定義過渡動畫AnimatedContent(targetState = filteredProducts,transitionSpec = customTransitionSpec,contentAlignment = Alignment.TopStart) { currentProducts ->// 遍歷商品列表,顯示每個商品currentProducts.forEach { product ->Text(text = product,modifier = Modifier.fillMaxWidth().padding(8.dp))}}}
}

代碼分析

  • 狀態管理

    • isFilterVisible?用于控制篩選條件的可見性。
    • filter?用于存儲當前的篩選條件。
    • allProducts?模擬了所有商品的列表,filteredProducts?根據?filter?的值進行篩選。
  • 篩選條件顯示:使用?AnimatedVisibility?組件,根據?isFilterVisible?的值控制篩選條件的顯示與隱藏,添加淡入淡出動畫。

  • 篩選結果顯示:使用?AnimatedContent?組件,根據?filteredProducts?的變化更新顯示的商品列表,應用自定義的過渡動畫。當篩選條件改變時,新的商品列表會以平滑的動畫效果顯示出來。

5.3 自動動畫在提升用戶體驗方面的作用

  • 增強交互反饋:自動動畫可以為用戶的操作提供直觀的反饋。例如,在點擊按鈕展開菜單時,菜單以動畫的形式平滑展開,讓用戶清楚地知道操作已經生效。這種反饋能夠增強用戶與界面的交互感,使用戶更加自信地操作應用。
  • 引導用戶注意力:通過動畫效果,可以引導用戶的注意力到重要的信息或操作上。例如,在有新消息到來時,消息提示以閃爍或縮放的動畫效果顯示,吸引用戶的注意力,讓用戶及時發現新消息。
  • 提升界面的流暢感:自動動畫可以使界面元素的顯示和隱藏、狀態的切換更加自然流暢,避免界面的突然變化給用戶帶來的不適感。例如,在切換列表項內容時,使用動畫過渡可以讓用戶感覺界面的變化是連續的,提升了界面的整體流暢感。
  • 增加應用的趣味性:精美的動畫效果可以為應用增添趣味性,使應用更具吸引力。例如,在游戲應用中,角色的移動、技能的釋放等都可以通過動畫來表現,讓用戶在游戲過程中獲得更好的體驗。

六、自動動畫的性能優化與注意事項

6.1 性能優化策略

合理選擇動畫類型

不同的動畫類型對性能的影響不同。例如,簡單的淡入淡出動畫相對來說性能開銷較小,而復雜的縮放、旋轉動畫可能會消耗更多的資源。在選擇動畫類型時,應根據實際需求進行權衡,優先選擇性能開銷較小的動畫。

kotlin

// 簡單的淡入淡出動畫
AnimatedVisibility(visible = isVisible,enter = fadeIn(),exit = fadeOut()
) {// 內容
}// 復雜的縮放和旋轉動畫
// 這種動畫可能會消耗更多資源,需要謹慎使用
AnimatedVisibility(visible = isVisible,enter = scaleIn() + rotateIn(),exit = scaleOut() + rotateOut()
) {// 內容
}
控制動畫時長和幀率

動畫的時長和幀率也會影響性能。過長的動畫時長會增加用戶的等待時間,而過短的動畫時長可能會導致動畫效果不明顯。幀率方面,過高的幀率會增加 CPU 和 GPU 的負擔,一般將幀率控制在 60fps 左右即可。

kotlin

// 設置動畫時長為 300 毫秒
val enterTransition = fadeIn(animationSpec = tween(durationMillis = 300))
val exitTransition = fadeOut(animationSpec = tween(durationMillis = 300))AnimatedVisibility(visible = isVisible,enter = enterTransition,exit = exitTransition
) {// 內容
}
避免不必要的動畫

在開發過程中,應避免添加不必要的動畫。只有在確實需要增強用戶體驗的地方才使用動畫,避免過度使用動畫導致性能下降。例如,在一些靜態頁面中,不需要添加動畫效果。

優化動畫狀態管理

合理管理動畫的狀態可以減少不必要的動畫計算和重繪。例如,使用?remember?函數來緩存可變狀態,避免在每次重組時重新創建狀態。

kotlin

// 使用 remember 緩存可變狀態
var isVisible by remember { mutableStateOf(false) }AnimatedVisibility(visible = isVisible,enter = fadeIn(),exit = fadeOut()
) {// 內容
}

6.2 注意事項

兼容性問題

不同的 Android 設備和版本可能對動畫的支持有所不同。在開發過程中,應進行充分的測試,確保動畫在各種設備和版本上都能正常顯示。特別是在使用一些新的動畫特性時,要注意其兼容性。

內存管理

動畫可能會占用一定的內存資源,特別是在處理復雜動畫或大量動畫時。要注意及時釋放不再使用的動畫資源,避免內存泄漏。例如,在組件銷毀時,停止正在運行的動畫。

動畫沖突

在一個界面中,如果同時存在多個動畫,可能會出現動畫沖突的問題。例如,一個元素正在進行淡入動畫,同時又要進行縮放動畫,可能會導致動畫效果不理想。在設計動畫時,要避免這種沖突的發生,或者使用合適的動畫組合方式來解決沖突。

七、總結與展望

7.1 總結

Android Compose 中的?AnimatedVisibility?和?AnimatedContent?為開發者提供了強大而便捷的自動動畫功能。通過這兩個組件,開發者可以輕松實現元素的顯示與隱藏動畫,以及內容的動態變化動畫,從而提升應用的用戶體驗。

AnimatedVisibility?主要用于控制元素的可見性,通過設置?visible?參數和動畫效果,可以讓元素在顯示和隱藏時具有平滑的過渡。其內部通過?updateTransition?函數管理動畫的過渡狀態,利用?AnimatedVisibilityScope?函數處理動畫的執行。

AnimatedContent?則專注于內容的動態更新,當傳遞給它的內容發生變化時,會根據?transitionSpec?中定義的動畫效果進行平滑過渡。開發者可以自定義過渡動畫,實現淡入淡出、縮放、旋轉等多種效果。

在實際項目中,AnimatedVisibility?和?AnimatedContent?可以結合使用,以實現更復雜的動畫效果。同時,合理運用自動動畫可以增強交互反饋、引導用戶注意力、提升界面的流暢感和增加應用的趣味性。

7.2 展望

更多動畫效果和特性

未來,Android Compose 可能會提供更多豐富的動畫效果和特性。例如,支持更多基于物理模擬的動畫,如彈性動畫、重力動畫等,讓動畫更加逼真和自然。同時,可能會增加更多的動畫插值器和過渡類型,為開發者提供更多的選擇。

性能進一步優化

隨著 Android 系統和硬件的不斷發展,Android Compose 的動畫性能也有望得到進一步優化。例如,采用更高效的動畫計算和渲染算法,減少動畫對 CPU 和 GPU 的負擔,提高動畫的流暢度和響應速度。

跨平臺動畫支持

隨著跨平臺開發的趨勢不斷增強,Android Compose 可能會提供更好的跨平臺動畫支持。開發者可以使用相同的代碼在不同的平臺上實現一致的動畫效果,降低開發成本和維護難度。

更便捷的動畫調試工具

目前,Android Compose 的動畫調試相對來說還比較困難。未來,可能會提供更便捷的動畫調試工具,幫助開發者快速定位和解決動畫問題,提高開發效率。

總之,Android Compose 的自動動畫功能為開發者帶來了很多便利,未來也有著廣闊的發展前景。開發者可以充分利用這些功能,為用戶打造更加出色的 Android 應用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898869.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898869.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898869.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

文件上傳的小點總結(1)

2.文件類型繞過 問題插入&#xff1a;BP無法攔截本地流量 ①插件限制 不代理的地址列表通常寫有localhost和127.0.0.1&#xff0c;把本地的全都刪掉&#xff0c;然后應用保存。 ②瀏覽器限制 Firefox瀏覽器設置&#xff1a;檢查瀏覽器代理配置和proxy listeners都沒問題后&…

AI基礎01-文本數據采集

本篇文章是學習文本數據的采集&#xff0c;作為人工智能訓練師或者數據分析師有時需要先獲取數據&#xff0c;然后進行數據清洗、數據標注。很明顯數據采集是后續步驟的基礎。 1&#xff09;數據采集定義 數據采集&#xff1a;data acquisition&#xff0c;DAQ 又稱為數據獲取…

深度學習Python編程:從入門到工程實踐

第一章 Python語言概述與生態體系 1.3 Python在工業界的應用場景 # 示例:使用FastAPI構建RESTful接口 from fastapi import FastAPI from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strprice: float@app.post("/items/") async def cr…

使用CSS3實現炫酷的3D翻轉卡片效果

使用CSS3實現炫酷的3D翻轉卡片效果 這里寫目錄標題 使用CSS3實現炫酷的3D翻轉卡片效果項目介紹技術要點分析1. 3D空間設置2. 核心CSS屬性3. 布局和定位 實現難點和解決方案1. 3D效果的流暢性2. 卡片內容布局3. 響應式設計 性能優化建議瀏覽器兼容性總結 項目介紹 在這個項目中…

HAl庫開發中斷方式接收Can報文的詳細流程

下面給出一個基于 HAL 庫的中斷方式接收 CAN 報文的詳細流程說明&#xff0c;描述每一步的硬件配置、軟件調用和中斷處理機制&#xff0c;而不涉及具體代碼細節&#xff0c;只講解整體原理和步驟&#xff1a; 在使用 HAL 庫時&#xff0c;不需要手動清除中斷標志位。原因如下&…

【讀書筆記】華為《從偶然到必然》

note 華為的成功并非偶然&#xff0c;而是通過IPD體系、投資組合管理、平臺戰略等系統性工具&#xff0c;將研發投資轉化為可持續的商業競爭力。書中強調的“管理即內部因素”理念&#xff0c;揭示了企業規模擴張與管理能力匹配的深層規律&#xff0c;為高科技企業提供了可借鑒…

6.4考研408數據結構圖論核心知識點深度解析

一、最小生成樹(Minimum Spanning Tree) 1.1 Prim算法 易錯點與難點 lowcost數組更新邏輯 錯誤將已加入生成樹的頂點距離重置為0后繼續參與計算,導致后續頂點選擇錯誤未正確處理非連通圖情況,可能陷入死循環(需結合visited數組判斷)示例錯誤:for(int j=0; j<G.vexn…

HashMap添加元素的流程圖

文章目錄 JDK7 vs JDK8 的 HashMap 結構變化Java8 中哈希表的紅黑樹優化機制HashMap 添加元素的完整流程解析1. 計算 key 的哈希值并確定索引2. 檢查該索引位置是否已有元素3. 處理哈希沖突4. 判斷當前存儲結構&#xff08;鏈表還是紅黑樹&#xff09;5. 判斷鏈表長度是否超過 …

Excel(進階篇):powerquery詳解、PowerQuery的各種用法,逆透視表格、雙行表頭如何制作透視表、不規則數據如何制作數據透視表

目錄 PowerQuery工具基礎修改現有數據理規則PowerQuery抓取數據的兩種方式多文件合并透視不同表結構多表追加數據透視追加與合并整理橫向表格:逆透視 數據用拆分工具整理數據算賬齡 不等步長值組合合并文件夾中所有文件PowerQuery處理CSV文件雙行表頭、帶合并單元格如何做數據…

從零開始:使用 Cython + JNI 在 Android 上運行 Python 算法

1. 引言 在 Android 設備上運行 Python 代碼通常面臨性能、兼容性和封裝等挑戰。尤其是當你希望在 Android 應用中使用 Python 編寫的計算密集型算法時&#xff0c;直接運行 Python 代碼可能導致較高的 CPU 占用和較差的性能。為了解決這個問題&#xff0c;我們可以使用 Cytho…

請為下面的html添加一個修改按鈕,以便對書名、價格進行修改

下面的HTML段落&#xff0c;在書名和價格輸入錯誤的情況下&#xff0c;無法進行修改。添加一個按鈕&#xff0c;對已經輸入的信息進行修改。 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></…

FFmpeg + ?Qt? 簡單視頻播放器代碼

一個基于 ?FFmpeg 4.x? 和 ?Qt? 的簡單視頻播放器代碼示例&#xff0c;實現視頻解碼和渲染到 Qt 窗口的功能。 1&#xff09;ffmpeg庫界面&#xff0c;視頻解碼支持軟解和硬解方式。 2&#xff09;QImage/QPixmap顯示視頻圖片。 ?1. Qt 項目配置&#xff08;.pro 文件&…

如何在百度搜索上刪除與自己名字相關的資料

個人信息的網絡足跡如同一張無形的網&#xff0c;將我們與世界的每一個角落緊密相連。然而&#xff0c;當某些與自己名字相關的資料不再希望被公眾輕易檢索到時&#xff0c;如何在百度搜索中有效“隱身”&#xff0c;成為了一個亟待解決的問題。面對復雜多變的網絡環境&#xf…

WebSocket:現代實時通信協議的深度解析與實踐

一、背景與演進歷程 1.1 傳統實時通信的困境 // 典型的HTTP輪詢偽代碼 while(true) {auto response http_client.get("/messages");if(response.has_data()) process(response);std::this_thread::sleep_for(1s); // 固定間隔輪詢 } 高延遲&#xff1a;輪詢間隔導…

[貪心算法]最長回文串 增減字符串匹配 分發餅干

1.最長回文串 我們可以存下每個字母的個數&#xff0c;然后分類討論 如果是奇數就減一加到結果中如果是偶數就直接加入即可 最后判斷長度跟原字符串的差距&#xff0c;如果小于原數組說明有奇數結果1 class Solution { public:int longestPalindrome(string s) {int ret0;//1.計…

STM32 的tf卡驅動

基于STM32的TF卡驅動的基本實現步驟和相關代碼示例,主要使用SPI接口來與TF卡進行通信。 硬件連接 將TF卡的SPI接口與STM32的SPI引腳連接,通常需要連接SCK(時鐘)、MOSI(主出從入)、MISO(主入從出)和CS(片選)引腳。 軟件實現 初始化SPI 配置SPI的工作模式、時鐘頻率…

目標檢測中的非極大值抑制(NMS)原理與實現解析

一、技術背景 在目標檢測任務中&#xff0c;模型通常會對同一目標生成多個重疊的候選框&#xff08;如錨框或預測框&#xff09;。非極大值抑制&#xff08;Non-Maximum Suppression, NMS&#xff09; 是一種關鍵的后處理技術&#xff0c;用于去除冗余的檢測結果&#xff0c;保…

探秘鴻蒙 HarmonyOS NEXT:鴻蒙存儲核心技術全解析

引言 本文章基于HarmonyOS NEXT操作系統&#xff0c;API12以上的版本。 在 ArkTS (ArkUI 框架) 中&#xff0c;用戶首選項 (Preferences) 和 持久化存儲 (PersistentStorage) 都用于數據存儲&#xff0c;但它們有不同的應用場景和特點。 1. 用戶首選項 (Preferences) 概念&a…

Leetcode—15. 三數之和(哈希表—基礎算法)

題目&#xff1a; 給你一個整數數組 nums &#xff0c;判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i ! j、i ! k 且 j ! k &#xff0c;同時還滿足 nums[i] nums[j] nums[k] 0 。請你返回所有和為 0 且不重復的三元組。 注意&#xff1a;答案中不可以包含重復的…

Linux 啟動Jar腳本設置開機自啟【超級詳細】

Linux 啟動Jar腳本&&設置開機自啟【超級詳細】 概要服務器開機自啟服務重啟腳本 概要 最近在Linux服務器中部署了一個項目&#xff08;單機版&#xff09;&#xff0c;每次更新服務的時候需要用到好幾個命令&#xff0c;停止服務&#xff0c;再重啟&#xff0c;并且服…