1# Layout Update Animation 2 3 4[Attribute animation](../reference/arkui-ts/ts-animatorproperty.md) (animation) and [explicit animation](../reference/arkui-ts/ts-explicit-animation.md) (animateTo) are the most basic and common animation features provided by ArkUI. When the layout attributes (such as the [size](../reference/arkui-ts/ts-universal-attributes-size.md) and [position](../reference/arkui-ts/ts-universal-attributes-location.md)) attributes change, you can use the attribute animation or explicit animation to transit to the new layout parameter status based on the animation parameters. 5 6 7| Animation Type| Description | Application Scenario | 8| ---- | ---------------------------------------- | -------- | 9| Attribute animation| The animation setting is simple. The animation is automatically triggered when the attribute changes. | Simple animation scenario| 10| Explicit animation| Changes in a closure trigger animations, including component addition and deletion caused by data changes and component attribute changes. Complex animations can be performed.| Complex animation scenarios| 11 12 13## Using Explicit Animation to Generate Layout Update Animation 14 15The API for explicit animation is as follows: 16 17 18```ts 19animateTo(value: AnimateParam, event: () => void): void 20``` 21 22The first parameter specifies the animation parameter, and the second parameter is the closure function of the animation. 23 24The following is an example of using explicit animation to produce a layout update animation. In the example, after the alignItems attribute of the Column component is changed, the layout of its child components changes. As long as the attribute is modified in the closure function of **animateTo**, all changes caused by the attribute are performed to the end value according to the animation parameter of animateTo. 25 26 27```ts 28@Entry 29@Component 30struct LayoutChange { 31 // Used to control the alignItems attribute of a column. 32 @State itemAlign: HorizontalAlign = HorizontalAlign.Start; 33 allAlign: HorizontalAlign[] = [HorizontalAlign.Start, HorizontalAlign.Center, HorizontalAlign.End]; 34 alignIndex: number = 0; 35 36 build() { 37 Column() { 38 Column({ space: 10 }) { 39 Button("1").width(100).height(50) 40 Button("2").width(100).height(50) 41 Button("3").width(100).height(50) 42 } 43 .margin(20) 44 .alignItems(this.itemAlign) 45 .borderWidth(2) 46 .width("90%") 47 .height(200) 48 49 Button("click").onClick(() => { 50 // The animation duration is 1000 ms, and the curve is EaseInOut. 51 animateTo({ duration: 1000, curve: Curve.EaseInOut }, () => { 52 this.alignIndex = (this.alignIndex + 1) % this.allAlign.length; 53 // Modify the this.itemAlign parameter in the closure function to change the layout of children in the Column container. Use an animation to transition to the new position. 54 this.itemAlign = this.allAlign[this.alignIndex]; 55 }); 56 }) 57 } 58 .width("100%") 59 .height("100%") 60 } 61} 62``` 63 64 65![layoutChange1](figures/layoutChange1.gif) 66 67 68In addition to directly changing the layout mode, you can also directly change the width, height, and position of a component. 69 70 71 72```ts 73@Entry 74@Component 75struct LayoutChange2 { 76 @State myWidth: number = 100; 77 @State myHeight: number = 50; 78 // Flag. true and false correspond to a group of myWidth and myHeight values respectively. 79 @State flag: boolean = false; 80 81 build() { 82 Column({ space: 10 }) { 83 Button("text") 84 .type(ButtonType.Normal) 85 .width(this.myWidth) 86 .height(this.myHeight) 87 .margin(20) 88 Button("area: click me") 89 .fontSize(12) 90 .margin(20) 91 .onClick(() => { 92 animateTo({ duration: 1000, curve: Curve.Ease }, () => { 93 // In the animation closure, the state variable that controls the width and height of the first button is changed based on the flag bit so that the width and height of the first button are animated. 94 if (this.flag) { 95 this.myWidth = 100; 96 this.myHeight = 50; 97 } else { 98 this.myWidth = 200; 99 this.myHeight = 100; 100 } 101 this.flag = !this.flag; 102 }); 103 }) 104 } 105 .width("100%") 106 .height("100%") 107 } 108} 109``` 110 111 112In the click event of the second button, the **animateTo** API is used to modify the **this.myWidth** and **this.myHeight** state variables in the closure. The two state variables are the width and height attribute values of the first button. Therefore, the width and height animation is performed for the first button. The display effect is shown below. 113 114 115![layoutChange2_animateTo](figures/layoutChange2_animateTo.gif) 116 117 118At the same time, the second button also produces a position animation. After the width and height of the first button are changed, the layout of other components in the column is also changed. The layout of the second button is also changed because the width and height of the first button are changed in the closure. 119 120 121If you do not want the second button to have an animation effect, you can use either of the following methods: 1. Add a container outside the first button so that the sizes before and after the animation are within the range of the container. In this way, the position of the second button is not affected by the position of the first button. The modified key code is as follows: 122 123 124 125```ts 126Column({ space: 10 }) { 127 Column() { 128 // The button is placed in a container that is large enough so that it does not affect the position of the outer component. 129 Button("text") 130 .type(ButtonType.Normal) 131 .width(this.myWidth) 132 .height(this.myHeight) 133 } 134 .margin(20) 135 .width(200) 136 .height(100) 137 138 Button("area: click me") 139 .fontSize(12) 140 .onClick(() => { 141 animateTo({ duration: 1000, curve: Curve.Ease }, () => { 142 // In the animation closure, the state variable that controls the width and height of the first button is changed based on the flag bit so that the width and height of the first button are animated. 143 if (this.flag) { 144 this.myWidth = 100; 145 this.myHeight = 50; 146 } else { 147 this.myWidth = 200; 148 this.myHeight = 100; 149 } 150 this.flag = !this.flag; 151 }); 152 }) 153} 154.width("100%") 155.height("100%") 156``` 157 158 159![layoutChange2_animateTo_change](figures/layoutChange2_animateTo_change.gif) 160 161 1622. Add layout constraints to the second button, for example, position constraints, so that the position of the second button is not affected by the width and height of the first button. Sample code: 163 164 165 166```ts 167Column({ space: 10 }) { 168 Button("text") 169 .type(ButtonType.Normal) 170 .width(this.myWidth) 171 .height(this.myHeight) 172 .margin(20) 173 174 Button("area: click me") 175 .fontSize(12) 176 // Set the position attribute to a fixed value so that the layout position is not affected by the width and height of the first button. 177 .position({ x: "30%", y: 200 }) 178 .onClick(() => { 179 animateTo({ duration: 1000, curve: Curve.Ease }, () => { 180 // In the animation closure, the state variable that controls the width and height of the first button is changed based on the flag bit so that the width and height of the first button are animated. 181 if (this.flag) { 182 this.myWidth = 100; 183 this.myHeight = 50; 184 } else { 185 this.myWidth = 200; 186 this.myHeight = 100; 187 } 188 this.flag = !this.flag; 189 }); 190 }) 191} 192.width("100%") 193.height("100%") 194``` 195 196 197## Using Attribute Animation to Generate Layout Update Animation 198 199The explicit animation places the modification of the attribute of the animation to be executed in the closure function to trigger the animation. The attribute animation does not need to use the closure. You only need to add the animation attribute to the end of the attribute of the component to be executed. 200 201The API of the attribute animation is as follows: 202 203 204```ts 205animation(value: AnimateParam) 206``` 207 208The input parameter is an animation parameter. If you want the component to generate an animation with the change of an attribute value, you need to add this attribute before the animation attribute. Some attribute changes do not want to generate attribute animations through animations. Therefore, attribute animations can be placed after animations. The example of explicit animation above is easily changed to be implemented with property animation. Sample code: 209 210 211 212```ts 213@Entry 214@Component 215struct LayoutChange2 { 216 @State myWidth: number = 100; 217 @State myHeight: number = 50; 218 @State flag: boolean = false; 219 @State myColor: Color = Color.Blue; 220 221 build() { 222 Column({ space: 10 }) { 223 Button("text") 224 .type(ButtonType.Normal) 225 .width(this.myWidth) 226 .height(this.myHeight) 227 // Animation takes effect only for the type, width, and height attributes. The duration is 1000 ms, and the curve is Ease. 228 .animation({ duration: 1000, curve: Curve.Ease }) 229 .backgroundColor(this.myColor) 230 .margin(20) 231 // Animation does not take effect for the backgroundColor and margin attributes. 232 233 Button("area: click me") 234 .fontSize(12) 235 .onClick(() => { 236 // Change the attribute value. Animation transition is performed for attributes configured with attribute animation. 237 if (this.flag) { 238 this.myWidth = 100; 239 this.myHeight = 50; 240 this.myColor = Color.Blue; 241 } else { 242 this.myWidth = 200; 243 this.myHeight = 100; 244 this.myColor = Color.Pink; 245 } 246 this.flag = !this.flag; 247 }) 248 } 249 } 250} 251``` 252 253 254In the preceding example, the animation attribute of the first button takes effect only for the type, width, and height attributes written before the animation, but does not take effect for the backgroundColor and margin attributes written after the animation. In the running result, the width and height attributes execute the animation based on the animation parameters. However, the backgroundColor directly jumps and no animation is generated. The display effect is shown below. 255 256 257 258 259 260 261![size-change-animation](figures/size-change-animation.gif) 262 263 264>**NOTE** 265> 266> 1. When the attribute animation is used, the animation is executed according to the specified attribute animation parameters. Each component can configure attribute animations with different parameters for its own attributes. 267> 268> 2. Explicit animations are executed on all GUI differences caused before and after animation closures, and the same animation parameters are used. Therefore, explicit animations are applicable to scenarios where animations are executed in a unified manner. In addition, explicit animations can also be used for animations caused by non-attribute variables, such as if/else conditions and deletion of array elements used by Forach. 269> 270> 3. If an attribute animation is configured for an attribute and the attribute value is changed in the explicit animation closure, the attribute animation takes effect first and the animation parameters of the attribute animation are used. 271