Slide 1

Slide 1 text

$PNQPTF5SBOTJUJPO "OJNBUJPO ͋Μ͍͟Ώ͖ !ZBO[N %SPJE,BJHJDPMMFDU\!5PLZP^

Slide 2

Slide 2 text

:VLJ"O[BJ w (PPHMF%FWFMPQFS&YQFSUGPS"OESPJE w UXJUUFS!ZBO[N w CMPH:".ͷࡶهாZBO[NCMPHTQPUDPN w גࣜձࣾ΢ϑΟΧ

Slide 3

Slide 3 text

https://play.google.com/store/apps/details?id=jp.co.smartbank.b43 B/43

Slide 4

Slide 4 text

var item by remember { mutableStateOf(Item.A) } Box( contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().height(300.dp) ) { Spacer( modifier = Modifier .size(200.dp) .background( when (item) { Item.A -> Color.Red Item.B -> Color.Blue } ) ) } Column(modifier = Modifier.padding(horizontal = 16.dp)) { Item.values().forEach { RadioButtonWithText( text = it.name, selected = item == it, onClick = { item = it } ) } } ᶃJUFN͕มΘΔ ᶄSFDPNQPTF͕૸ͬͯมΘΔ

Slide 5

Slide 5 text

"OJNBUFE$POUFOU w ঢ়ଶʢ4UBUFʣ͕มΘͬͨͱ͖ͷ੾Γସ͑ʢFOUFSFYJUʣΛΞχϝʔγϣϯ ͢Δ @ExperimentalAnimationApi @Composable fun AnimatedContent( targetState: S, … content: @Composable() AnimatedVisibilityScope.(targetState: S) -> Unit ) { … }

Slide 6

Slide 6 text

"OJNBUFE$POUFOU w ঢ়ଶʢ4UBUFʣ͕มΘͬͨͱ͖ͷ੾Γସ͑ʢFOUFSFYJUʣΛΞχϝʔγϣϯ ͢Δ var myState by remember { mutableStateOf(Item.A) } AnimatedContent( label = "myState", targetState = myState ) { // content lambda ͷҾ਺ (it) Λ࢖͏ // when(myState) ͸μϝ when(it) { ... } }

Slide 7

Slide 7 text

var item by remember { mutableStateOf(Item.A) } AnimatedContent( label = "item", targetState = item, ) { Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() .height(300.dp) ) { Spacer( modifier = Modifier .size(200.dp) .background( when (it) { Item.A -> Color.Red Item.B -> Color.Blue } ) ) } } … "OJNBUFE$POUFOUΛ࢖͏ DPOUFOUMBNCEBͷҾ਺Λ࢖͏

Slide 8

Slide 8 text

var item by remember { mutableStateOf(Item.A) } AnimatedContent( label = "item", targetState = item, transitionSpec = { fadeIn(tween(300, 150)) + slideIntoContainer( towards = when (targetState) { Item.A -> SlideDirection.End Item.B -> SlideDirection.Start }, initialOffset = { it / 4 }, animationSpec = tween(1000, 150) ) with fadeOut(tween(150)) } ) { … } … NTͰGBEFPVU NT଴ͬͨ͋ͱʢGBEFPVU͕ऴΘͬͨޙʣ NTͰGBEFJO NT଴ͬͨ͋ͱ ʢGBEFPVU͕ऴΘͬͨޙʣ NTͰTMJEFJO

Slide 9

Slide 9 text

Android Studio Gira ff e

Slide 10

Slide 10 text

ը໘͕දࣔ͞Εͨͱ͖΋Ξχϝʔγϣϯ͍ͨ͠ #VUUPOΛλοϓͯ͠ը໘͕දࣔ͞Εͨ ͱ͖ʢDPNQPTF࣌ʣ͸Ξχϝʔγϣϯ ͳ͠Ͱ੺࢛͕֯දࣔ͞Ε͍ͯΔ

Slide 11

Slide 11 text

"OJNBUFE$POUFOUͷத਎ΛΈΔͱʜ @ExperimentalAnimationApi @Composable fun AnimatedContent( targetState: S, … ) { val transition = updateTransition(targetState = targetState, label = label) transition.AnimatedContent( modifier, transitionSpec, contentAlignment, content = content ) } VQEBUF5SBOTJUJPO Λ࢖͍ͬͯΔ 5SBOTJUJPOͷ"OJNBUFE$POUFOUΛ࢖͍ͬͯΔ

Slide 12

Slide 12 text

VQEBUF5SBOTJUJPO w ঢ়ଶʢ஋ʣͷมߋʹෳ਺ͷΞχϝʔγϣϯΛඥ͚͍ͮͨͱ͖ʹ࢖͏

Slide 13

Slide 13 text

VQEBUF5SBOTJUJPO w ঢ়ଶʢ஋ʣͷมߋʹෳ਺ͷΞχϝʔγϣϯΛඥ͚͍ͮͨͱ͖ʹ࢖͏ var item by remember { mutableStateOf(Item.A) } val itemTransition = updateTransition(targetState = item, label = "item") ঢ়ଶ FOVNDMBTT*UFN\" #^ 5SBOTJUJPOΠϯελϯε͕ฦΔ UBSHFU4UBUFʹ4UBUFͷ஋Λ౉͢

Slide 14

Slide 14 text

VQEBUF5SBOTJUJPO w ঢ়ଶʢ஋ʣͷมߋʹෳ਺ͷΞχϝʔγϣϯΛඥ͚͍ͮͨͱ͖ʹ࢖͏ var item by remember { mutableStateOf(Item.A) } val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { when (it) { Item.A -> 100.dp Item.B -> 200.dp } } val color by itemTransition.animateColor(label = "color") { when (it) { Item.A -> Color.Red Item.B -> Color.Blue } } 5SBOTJUJPOBOJNBUF ͰΞχϝʔγϣϯͷ4UBUF5Λऔಘ͢Δ

Slide 15

Slide 15 text

var item by remember { mutableStateOf(Item.A) } val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { when (it) { Item.A -> 100.dp Item.B -> 200.dp } } val color by itemTransition.animateColor(label = "color") { when (it) { Item.A -> Color.Red Item.B -> Color.Blue } } Spacer( modifier = Modifier .size(size) .background(color) ) JUFN͕มΘΔͱTJ[Fͱ CBDLHSPVOE྆ํΞχϝʔγϣϯ͢Δ

Slide 16

Slide 16 text

var item by remember { mutableStateOf(Item.A) } val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { when (it) { Item.A -> 100.dp Item.B -> 200.dp } } val color by itemTransition.animateColor(label = "color") { when (it) { Item.A -> Color.Red Item.B -> Color.Blue } } Spacer( modifier = Modifier .size(size) .background(color) )

Slide 17

Slide 17 text

5SBOTJUJPOͷ"OJNBUJPO w BOJNBUF99 w "OJNBUFE$POUFOU w "OJNBUFE7JTJCJMJUZ w $SPTTGBEF

Slide 18

Slide 18 text

ը໘͕දࣔ͞Εͨͱ͖΋Ξχϝʔγϣϯ͍ͨ͠ #VUUPOΛλοϓͯ͠ը໘͕දࣔ͞Εͨ ͱ͖ʢDPNQPTF࣌ʣ͸Ξχϝʔγϣϯ ͳ͠Ͱ੺࢛͕֯දࣔ͞Ε͍ͯΔ

Slide 19

Slide 19 text

VQEBUF5SBOTJUJPO ͷத਎ΛΈΔͱʜ @Composable fun updateTransition( targetState: T, label: String? = null ): Transition { val transition = remember { Transition(targetState, label = label) } transition.animateTo(targetState) DisposableEffect(transition) { … } return transition } 5SBOTJUJPOΛੜ੒

Slide 20

Slide 20 text

.VUBCMF5SBOTJUJPO4UBUFΛอ࣋ @Composable fun updateTransition( targetState: T, label: String? = null ): Transition { val transition = remember { Transition(targetState, label = label) } transition.animateTo(targetState) DisposableEffect(transition) { … } return transition } @Stable class Transition @PublishedApi internal constructor( private val transitionState: MutableTransitionState, val label: String? = null ) { internal constructor( initialState: S, label: String? ) : this(MutableTransitionState(initialState), label) … } 5SBOTJUJPOΛੜ੒

Slide 21

Slide 21 text

@Stable class Transition @PublishedApi internal constructor( private val transitionState: MutableTransitionState, val label: String? = null ) { internal constructor( initialState: S, label: String? ) : this(MutableTransitionState(initialState), label) … } JOJUJBM4UBUFͰ.VUBCMF5SBOTJUJPO4UBUFΛੜ੒ @Composable fun updateTransition( targetState: T, label: String? = null ): Transition { val transition = remember { Transition(targetState, label = label) } transition.animateTo(targetState) DisposableEffect(transition) { … } return transition }

Slide 22

Slide 22 text

@Stable class Transition @PublishedApi internal constructor( private val transitionState: MutableTransitionState, val label: String? = null ) { internal constructor( initialState: S, label: String? ) : this(MutableTransitionState(initialState), label) … } @Composable fun updateTransition( targetState: T, label: String? = null ): Transition { val transition = remember { Transition(targetState, label = label) } transition.animateTo(targetState) DisposableEffect(transition) { … } return transition } ͬͪ͜ͷίϯετϥΫλΛ࢖͏VQEBUF5SBOTJUJPO ΋͋Δʁ

Slide 23

Slide 23 text

@Stable class Transition @PublishedApi internal constructor( private val transitionState: MutableTransitionState, val label: String? = null ) { internal constructor( initialState: S, label: String? ) : this(MutableTransitionState(initialState), label) … } @Composable fun updateTransition( targetState: T, label: String? = null ): Transition { val transition = remember { Transition(targetState, label = label) } transition.animateTo(targetState) DisposableEffect(transition) { … } return transition } ͬͪ͜ͷίϯετϥΫλΛ࢖͏VQEBUF5SBOTJUJPO ΋͋Δʁ ͋Γ·͢

Slide 24

Slide 24 text

@Stable class Transition @PublishedApi internal constructor( private val transitionState: MutableTransitionState, val label: String? = null ) { internal constructor( initialState: S, label: String? ) : this(MutableTransitionState(initialState), label) … } @Composable fun updateTransition( transitionState: MutableTransitionState, label: String? = null ): Transition { val transition = remember(transitionState) { Transition(transitionState = transitionState, label) } transition.animateTo(transitionState.targetState) DisposableEffect(transition) { … } return transition } .VUBCMF5SBOTJUJPO4UBUFΛͱΔVQEBUF5SBOTBDUJPO

Slide 25

Slide 25 text

.VUBCMF5SBOTJUJPO4UBUF͕มΘͬͨΒ5SBOTJUJPO͸ ੜ੒͠௚͞ΕΔ .VUBCMF5SBOTJUJPO4UBUFͷUBSHFU4UBUFΛ BOJNBUF5P ʹ౉͢ @Composable fun updateTransition( transitionState: MutableTransitionState, label: String? = null ): Transition { val transition = remember(transitionState) { Transition(transitionState = transitionState, label) } transition.animateTo(transitionState.targetState) DisposableEffect(transition) { … } return transition }

Slide 26

Slide 26 text

.VUBCMF5SBOTJUJPO4UBUF class MutableTransitionState(initialState: S) { var currentState: S by mutableStateOf(initialState) internal set var targetState: S by mutableStateOf(initialState) val isIdle: Boolean get() = (currentState == targetState) && !isRunning internal var isRunning: Boolean by mutableStateOf(false) } 5SBOTJUJPO͔Βߋ৽͞ΕΔ ͜ΕΛมߋ͢Δͱ5SBOTJUJPOUBSHFU4UBUF͕ ߋ৽͞ΕͯΞχϝʔγϣϯ͕։࢝͞ΕΔ ʢΞχϝʔγϣϯऴྃ࣌ͳͲʣ5SBOTJUJPO͕৽͍͠ ঢ়ଶʹͳͬͨͱ͖ʹ5SBOTJUJPO͔Βߋ৽͞ΕΔ

Slide 27

Slide 27 text

.VUBCMF5SBOTJUJPO4UBUF Λ࢖͏

Slide 28

Slide 28 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(item) } transitionState.targetState = item val itemTransition = updateTransition(transitionState = transitionState, label = "item") val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { … } val color by itemTransition.animateColor(label = "color") { … } Spacer( modifier = Modifier .size(size) .background(color) )

Slide 29

Slide 29 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(item) } transitionState.targetState = item val itemTransition = updateTransition(transitionState = transitionState, label = "item") val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { … } val color by itemTransition.animateColor(label = "color") { … } Spacer( modifier = Modifier .size(size) .background(color) ) .VUBCMF5SBOTJUJPO4UBUF͸SFNFNCFS͢Δ

Slide 30

Slide 30 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(item) } transitionState.targetState = item val itemTransition = updateTransition(transitionState = transitionState, label = "item") val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { … } val color by itemTransition.animateColor(label = "color") { … } Spacer( modifier = Modifier .size(size) .background(color) ) .VUBCMF5SBOTJUJPO4UBUFͷUBSHFU4UBUFΛߋ৽͢Δ

Slide 31

Slide 31 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(item) } transitionState.targetState = item val itemTransition = updateTransition(transitionState = transitionState, label = "item") val itemTransition = updateTransition(targetState = item, label = "item") val size by itemTransition.animateDp(label = "size") { … } val color by itemTransition.animateColor(label = "color") { … } Spacer( modifier = Modifier .size(size) .background(color) ) VQEBUF5SBOTJUJPO ʹ.VUBCMF5SBOTJUJPO4UBUFΛ౉͢

Slide 32

Slide 32 text

.VUBCMF5SBOTJUJPO4UBUFͳΒͰ͖Δ͜ͱ w ࠷ॳͷUBSHFU4UBUFͱ͸ผͷॳظঢ়ଶΛͱΕΔ w DPNQPTJUJPOʹೖͬͨͱ͖ʹΞχϝʔγϣϯͤ͞Δ͜ͱ͕Ͱ͖Δ var visible by remember { mutableStateOf(true) } val transitionState = remember { MutableTransitionState(false) } transitionState.targetState = visible val itemTransition = updateTransition(transitionState = transitionState, label = "item") DPNQPTJUJPO࣌ʹ ॳظঢ়ଶ͸GBMTFɺ UBSHFU4UBUF͸USVFͳͷͰ Ξχϝʔγϣϯ͕૸Δ

Slide 33

Slide 33 text

.VUBCMF5SBOTJUJPO4UBUFͳΒͰ͖Δ͜ͱ w ࠷ॳͷUBSHFU4UBUFͱ͸ผͷॳظঢ়ଶΛͱΕΔ w DPNQPTJUJPOʹೖͬͨͱ͖ʹΞχϝʔγϣϯͤ͞Δ͜ͱ͕Ͱ͖Δ w .VUBCMF5SBOTJUJPO4UBUFΛ࠶ੜ੒͢Δ͜ͱͰɺΞχϝʔγϣϯͷϦελʔτ ΛτϦΨʔͰ͖Δ val transitionState = remember(trigger) { MutableTransitionState(false) } val itemTransition = updateTransition(transitionState = transitionState, label = "item") USJHHFS͕มΘΔͱ.VUBCMF5SBOTJUJPO4UBUF͕࡞Γ௚͞ΕΔͷͰ 5SBOTJUJPO΋࡞Γ௚͞ΕΔ

Slide 34

Slide 34 text

.VUBCMF5SBOTJUJPO4UBUF Λ࢖ͬͯDPNQPTF࣌ʹ΋ Ξχϝʔγϣϯͤ͞Δ

Slide 35

Slide 35 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(item) } transitionState.targetState = item val itemTransition = updateTransition( transitionState = transitionState, label = "item" ) itemTransition.AnimatedContent( transitionSpec = { … } ) { … } VQEBUF5SBOTJUJPO Λ࢖͏ 5SBOTJUJPOͷ"OJNBUFE$POUFOUΛ࢖͏

Slide 36

Slide 36 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(Item.B) } transitionState.targetState = item val itemTransition = updateTransition( transitionState = transitionState, label = "item" ) … μϝͳ৔߹ DPNQPTJUJPO࣌ͷΞχϝʔγϣϯͰ #ͷͱ͖ͷ੨͍࢛͕֯Ұॠදࣔ͞Εͯ͠·͏

Slide 37

Slide 37 text

var item by remember { mutableStateOf(Item.A) } val transitionState = remember { MutableTransitionState(null) } transitionState.targetState = item val itemTransition = updateTransition( transitionState = transitionState, label = "item" ) itemTransition.AnimatedContent( transitionSpec = { … } ) { Box(…) { if (it != null) { Spacer(…) } } } ॳظঢ়ଶΛOVMMʹ͢Δ DPNQPTJUJPO࣌ʹ͸ OVMMˠ*UFN" ͷΞχϝʔγϣϯ͕૸Δ

Slide 38

Slide 38 text

"OJNBUFE7JTJCJMJUZ4DPQFͷ 5SBOTJUJPO

Slide 39

Slide 39 text

@ExperimentalAnimationApi @Composable fun Transition.AnimatedContent( modifier: Modifier = Modifier, transitionSpec: AnimatedContentScope.() -> ContentTransform = { fadeIn(animationSpec = tween(220, delayMillis = 90)) + scaleIn(initialScale = 0.92f, animationSpec = tween(220, delayMillis = 90)) with fadeOut(animationSpec = tween(90)) }, contentAlignment: Alignment = Alignment.TopStart, contentKey: (targetState: S) -> Any? = { it }, content: @Composable() AnimatedVisibilityScope.(targetState: S) -> Unit ) {

Slide 40

Slide 40 text

interface AnimatedVisibilityScope { /** * [transition] allows custom enter/exit animations to be specified. It will run simultaneously * with the built-in enter/exit transitions specified in [AnimatedVisibility]. */ @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") @get:ExperimentalAnimationApi @ExperimentalAnimationApi val transition: Transition … }

Slide 41

Slide 41 text

itemTransition.AnimatedContent( … ) { val rotationY by transition.animateFloat( label = "rotationY", transitionSpec = { tween(durationMillis = 1000, delayMillis = 150) } ) { state -> when (state) { EnterExitState.PreEnter -> when (it) { Item.A -> 45f Item.B, null -> -45f } EnterExitState.Visible -> 0f EnterExitState.PostExit -> 0f } } Box(…) { if (it != null) { Spacer( modifier = Modifier .size(200.dp) .graphicsLayer { this.rotationY = rotationY this.cameraDistance = 40f } …

Slide 42

Slide 42 text

itemTransition.AnimatedContent( … ) { val rotationY by transition.animateFloat( label = "rotationY", transitionSpec = { tween(durationMillis = 1000, delayMillis = 150) } ) { state -> when (state) { EnterExitState.PreEnter -> when (it) { Item.A -> 45f Item.B, null -> -45f } EnterExitState.Visible -> 0f EnterExitState.PostExit -> 0f } } Box(…) { if (it != null) { Spacer( modifier = Modifier .size(200.dp) .graphicsLayer { this.rotationY = rotationY this.cameraDistance = 40f } … "OJNBUFE7JTJCJMJUZ4DPQFͷUSBOTJUJPOͰ BOJNBUF99Λ࢖͏

Slide 43

Slide 43 text

itemTransition.AnimatedContent( … ) { val rotationY by transition.animateFloat( label = "rotationY", transitionSpec = { tween(durationMillis = 1000, delayMillis = 150) } ) { state -> when (state) { EnterExitState.PreEnter -> when (it) { Item.A -> 45f Item.B, null -> -45f } EnterExitState.Visible -> 0f EnterExitState.PostExit -> 0f } } Box(…) { if (it != null) { Spacer( modifier = Modifier .size(200.dp) .graphicsLayer { this.rotationY = rotationY this.cameraDistance = 40f } … FOUFS࣌ͷॳظ஋ FOUFS࣌ͷUBSHFU஋FYJU࣌ͷॳظ஋ FYJU࣌ͷUBSHFU஋

Slide 44

Slide 44 text

itemTransition.AnimatedContent( … ) { val rotationY by transition.animateFloat( label = "rotationY", transitionSpec = { tween(durationMillis = 1000, delayMillis = 150) } ) { state -> when (state) { EnterExitState.PreEnter -> when (it) { Item.A -> 45f Item.B, null -> -45f } EnterExitState.Visible -> 0f EnterExitState.PostExit -> 0f } } Box(…) { if (it != null) { Spacer( modifier = Modifier .size(200.dp) .graphicsLayer { this.rotationY = rotationY this.cameraDistance = 40f } … SPUBUJPO:ΛΞχϝʔγϣϯ

Slide 45

Slide 45 text

·ͱΊ w "OJNBUFE$POUFOU͸಺෦ͰVQEBUF5SBOTJUJPO Λ࢖͍ͬͯΔ w .VUBCMF5SBOTJUJPO4UBUFΛ࢖͏ͱ$PNQPTJUJPO࣌ʹ΋Ξχϝʔγϣϯͤ͞ Δ͜ͱ͕Ͱ͖Δ w "OJNBUFE7JTJCJMJUZ4DPQFͷ5SBOTJUJPOΛ࢖͏ͱFOUFSFYJUʹಉظͨ͠ ݸผͷΞχϝʔγϣϯΛ௥ՃͰ͖Δ