1# Rating 2 3The **Rating** component provides a rating bar. 4 5> **NOTE** 6> 7> This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version. 8 9 10## Child Components 11 12Not supported 13 14 15## APIs 16 17Rating(options?: RatingOptions) 18 19**Widget capability**: This API can be used in ArkTS widgets since API version 9. 20 21**Atomic service API**: This API can be used in atomic services since API version 11. 22 23**System capability**: SystemCapability.ArkUI.ArkUI.Full 24 25**Parameters** 26 27| Name| Type | Mandatory| Description | 28| ------ | ----------------------------------------- | ---- | -------------- | 29| rating | [RatingOptions](#ratingoptions13) | No | Rating bar options.| 30 31## Attributes 32 33### stars 34 35stars(value: number) 36 37Sets the total number of ratings (stars). If the value set is less than or equal to 0, the default value is used. 38 39**Widget capability**: This API can be used in ArkTS widgets since API version 9. 40 41**Atomic service API**: This API can be used in atomic services since API version 11. 42 43**System capability**: SystemCapability.ArkUI.ArkUI.Full 44 45**Parameters** 46 47| Name| Type | Mandatory| Description | 48| ------ | ------ | ---- | ---------------------------- | 49| value | number | Yes | Total number of ratings.<br>Default value: **5**| 50 51### stepSize 52 53stepSize(value: number) 54 55Sets the step for rating. A value less than 0.1 evaluates to the default value. 56 57**Widget capability**: This API can be used in ArkTS widgets since API version 9. 58 59**Atomic service API**: This API can be used in atomic services since API version 11. 60 61**System capability**: SystemCapability.ArkUI.ArkUI.Full 62 63**Parameters** 64 65| Name| Type | Mandatory| Description | 66| ------ | ------ | ---- | ----------------------------------------------------------- | 67| value | number | Yes | Step for rating.<br>Default value: **0.5**<br>Value range: [0.1, stars]| 68 69### starStyle 70 71starStyle(options: StarStyleOptions) 72 73Sets the star style. For details about the supported image types, see [Image](ts-basic-components-image.md). 74 75Local and online images are supported, but not **PixelMap** and **Resource** objects. 76 77By default, the image is loaded in asynchronous mode. Synchronous loading is not supported. 78 79**Widget capability**: This API can be used in ArkTS widgets since API version 9. 80 81**Atomic service API**: This API can be used in atomic services since API version 11. 82 83**System capability**: SystemCapability.ArkUI.ArkUI.Full 84 85**Parameters** 86 87| Name | Type | Mandatory| Description | 88| ------- | ----------------------------------------------- | ---- | ------------------------------------------------------------ | 89| options | [StarStyleOptions](#starstyleoptions13) | Yes | Star style.<br>**NOTE**<br>If the path specified for **backgroundUri**, **foregroundUri**, or **secondaryUri** is incorrect, no image is displayed.<br>If **backgroundUri** or **foregroundUri** is set to **undefined** or an empty string, the **Rating** component loads the default star image source.<br>If **secondaryUri** is set to **undefined** or an empty string or is not set, **backgroundUri** is prioritized, which is equivalent to where only **foregroundUri** and **backgroundUri** are set.| 90 91> **NOTE** 92> 93> The drawing area of each rating image is [width/stars, height], wherein **width** and **height** indicate the width and height of the **Rating** component, respectively. 94> 95> To specify the drawing area as a square, you are advised to customize the width and height in this format: [height * stars, height], width = height * stars. 96 97### contentModifier<sup>12+</sup> 98 99contentModifier(modifier: ContentModifier\<RatingConfiguration>) 100 101Creates a content modifier. 102 103**Atomic service API**: This API can be used in atomic services since API version 12. 104 105**System capability**: SystemCapability.ArkUI.ArkUI.Full 106 107**Parameters** 108 109| Name| Type | Mandatory| Description | 110| ------ | --------------------------------------------- | ---- | ------------------------------------------------ | 111| modifier | [ContentModifier\<RatingConfiguration>](#ratingconfiguration12) | Yes | Content modifier to apply to the current component.<br>**modifier**: content modifier. You need a custom class to implement the **ContentModifier** API.| 112 113 114## Events 115 116### onChange 117 118onChange(callback:(value: number) => void) 119 120Triggered when the rating value changes. 121 122**Widget capability**: This API can be used in ArkTS widgets since API version 9. 123 124**Atomic service API**: This API can be used in atomic services since API version 11. 125 126**System capability**: SystemCapability.ArkUI.ArkUI.Full 127 128**Parameters** 129 130| Name| Type | Mandatory| Description | 131| ------ | ------ | ---- | -------------- | 132| value | number | Yes | Rating value.| 133 134## Sequential Keyboard Navigation Specifications 135| Key | Description | 136|------------|-----------------------------| 137| Tab | Switch the focus between components. | 138| Left and right arrow keys | Increase or decrease the rating on preview at the specified step, without changing the actual rating.| 139| Home | Move the focus to the first star, without changing the actual rating. | 140| End | Move the focus to the last star, without changing the actual rating. | 141| Space/Enter | Submit the rating result based on the current rating. | 142 143## RatingConfiguration<sup>12+</sup> 144 145You need a custom class to implement the **ContentModifier** API. 146 147**Atomic service API**: This API can be used in atomic services since API version 12. 148 149**System capability**: SystemCapability.ArkUI.ArkUI.Full 150 151| Name | Type | Read Only | Optional | Description | 152| ------ | ------ | ------ |-------------------------------- |-------------------------------- | 153| rating | number | No| No|Value to rate.<br>Default value: **0**| 154| indicator | boolean | No| No| Whether the component is used only as an indicator.<br>Default value: **false**| 155| stars | number | No| No|Total number of ratings.<br>Default value: **5**| 156| stepSize | number | No| No|Step of an operation.<br>Default value: **0.5**| 157| triggerChange | Callback\<number> | No| No|Callback triggered when the rating value changes.| 158 159## RatingOptions<sup>13+</sup> 160 161**Widget capability**: This API can be used in ArkTS widgets since API version 13. 162 163**Atomic service API**: This API can be used in atomic services since API version 13. 164 165**System capability**: SystemCapability.ArkUI.ArkUI.Full 166 167| Name | Type | Mandatory| Description | 168| --------- | ------- | ---- | ------------------------------------------------------------ | 169| rating | number | Yes | Value to rate.<br>Default value: **0**<br>Value range: [0, stars]<br>Values less than 0 are treated as **0**, and values greater than the value of **stars** are treated as the value of **stars**.<br>This parameter supports two-way binding through [$$](../../../quick-start/arkts-two-way-sync.md).| 170| indicator | boolean | No | Whether the component is used only as an indicator.<br>Default value: **false**<br>**NOTE**<br>When **indicator** is set to **true**, the default component height is 12.0 vp, and the component width is calculated as follows: Height x Value of **stars**.<br>When **indicator** is set to **false**, the default component height is 28.0 vp, and the component width is calculated as follows: Height x Value of **stars**.| 171 172## StarStyleOptions<sup>13+</sup> 173 174**Widget capability**: This API can be used in ArkTS widgets since API version 13. 175 176**Atomic service API**: This API can be used in atomic services since API version 13. 177 178**System capability**: SystemCapability.ArkUI.ArkUI.Full 179 180| Name | Type | Mandatory| Description | 181| ------------- | ------ | ---- | ------------------------------------------------------------ | 182| backgroundUri | string | Yes | Image path for the unselected star. You can use the default system image or a custom image. | 183| foregroundUri | string | Yes | Image path for the selected star. You can use the default system image or a custom image. | 184| secondaryUri | string | No | Image path for the partially selected star. You can use the default system image or a custom image.| 185 186## Example 187 188### Example 1 189 190```ts 191// xxx.ets 192@Entry 193@Component 194struct RatingExample { 195 @State rating: number = 3.5 196 197 build() { 198 Column() { 199 Column() { 200 Rating({ rating: this.rating, indicator: false }) 201 .stars(5) 202 .stepSize(0.5) 203 .margin({ top: 24 }) 204 .onChange((value: number) => { 205 this.rating = value 206 }) 207 Text('current score is ' + this.rating) 208 .fontSize(16) 209 .fontColor('rgba(24,36,49,0.60)') 210 .margin({ top: 16 }) 211 }.width(360).height(113).backgroundColor('#FFFFFF').margin({ top: 68 }) 212 213 Row() { 214 Image('common/testImage.jpg') 215 .width(40) 216 .height(40) 217 .borderRadius(20) 218 .margin({ left: 24 }) 219 Column() { 220 Text('Yue') 221 .fontSize(16) 222 .fontColor('#182431') 223 .fontWeight(500) 224 Row() { 225 Rating({ rating: 3.5, indicator: false }).margin({ top: 1, right: 8 }) 226 Text('2021/06/02') 227 .fontSize(10) 228 .fontColor('#182431') 229 } 230 }.margin({ left: 12 }).alignItems(HorizontalAlign.Start) 231 232 Text('1st Floor') 233 .fontSize(10) 234 .fontColor('#182431') 235 .position({ x: 295, y: 8 }) 236 }.width(360).height(56).backgroundColor('#FFFFFF').margin({ top: 64 }) 237 }.width('100%').height('100%').backgroundColor('#F1F3F5') 238 } 239} 240``` 241 242 243 244### Example 2 245 246```ts 247// xxx.ets 248@Entry 249@Component 250struct RatingExample { 251 @State rating: number = 3.5 252 253 build() { 254 Column() { 255 Rating({ rating: this.rating, indicator: false }) 256 .stars(5) 257 .stepSize(0.5) 258 .starStyle({ 259 backgroundUri: '/common/imag1.png', // The common folder is at the same level as pages. 260 foregroundUri: '/common/imag2.png', 261 secondaryUri: '/common/imag3.png' 262 }) 263 .margin({ top: 24 }) 264 .onChange((value: number) => { 265 this.rating = value 266 }) 267 Text('current score is ' + this.rating) 268 .fontSize(16) 269 .fontColor('rgba(24,36,49,0.60)') 270 .margin({ top: 16 }) 271 }.width('100%').height('100%').backgroundColor('#F1F3F5') 272 } 273} 274``` 275 276 277 278### Example 3 279This example implements a custom rating bar, with each circle representing 0.5 point. If **ratingIndicator** is set to **true**, the rating bar is used only as an indicator, and the rating cannot be changed. 280if it is set to **false**, the rating can be changed. **ratingStars** sets the rating value. **ratingStepsize** sets the step for rating. 281 282```ts 283// xxx.ets 284class MyRatingStyle implements ContentModifier<RatingConfiguration> { 285 name: string = "" 286 style: number = 0 287 constructor(value1: string, value2: number) { 288 this.name = value1 289 this.style = value2 290 } 291 applyContent() : WrappedBuilder<[RatingConfiguration]> { 292 return wrapBuilder(buildRating) 293 } 294} 295 296@Builder function buildRating(config: RatingConfiguration) { 297 Column() { 298 Row() { 299 Circle({ width: 25, height: 25 }) 300 .fill(config.rating >= 0.4 ? Color.Black : Color.Red) 301 .onClick((event: ClickEvent) => { 302 if (!config.indicator) { 303 if (config.stepSize = 0.5) { 304 config.triggerChange(0.5); 305 return 306 } 307 if (config.stepSize = 1) { 308 config.triggerChange(1); 309 return 310 } 311 } 312 }).visibility(config.stars >= 1 ? Visibility.Visible : Visibility.Hidden) 313 Circle({ width: 25, height: 25 }) 314 .fill(config.rating >= 0.9 ? Color.Black : Color.Red) 315 .onClick((event: ClickEvent) => { 316 if (!config.indicator) { 317 config.triggerChange(1); 318 } 319 }).visibility(config.stars >= 1 ? Visibility.Visible : Visibility.Hidden) 320 Circle({ width: 25, height: 25 }) 321 .fill(config.rating >= 1.4 ? Color.Black : Color.Red) 322 .onClick((event: ClickEvent) => { 323 if (!config.indicator) { 324 if (config.stepSize = 0.5) { 325 config.triggerChange(1.5); 326 return 327 } 328 if (config.stepSize = 1) { 329 config.triggerChange(2); 330 return 331 } 332 } 333 }).visibility(config.stars >= 2 ? Visibility.Visible : Visibility.Hidden).margin({left:10}) 334 Circle({ width: 25, height: 25 }) 335 .fill(config.rating >= 1.9 ? Color.Black : Color.Red) 336 .onClick((event: ClickEvent) => { 337 if (!config.indicator) { 338 config.triggerChange(2); 339 } 340 }).visibility(config.stars >= 2 ? Visibility.Visible : Visibility.Hidden) 341 Circle({ width: 25, height: 25 }) 342 .fill(config.rating >= 2.4 ? Color.Black : Color.Red) 343 .onClick((event: ClickEvent) => { 344 if (!config.indicator) { 345 if (config.stepSize = 0.5) { 346 config.triggerChange(2.5); 347 return 348 } 349 if (config.stepSize = 1) { 350 config.triggerChange(3); 351 return 352 } 353 } 354 }).visibility(config.stars >= 3 ? Visibility.Visible : Visibility.Hidden).margin({left:10}) 355 Circle({ width: 25, height: 25 }) 356 .fill(config.rating >= 2.9 ? Color.Black : Color.Red) 357 .onClick((event: ClickEvent) => { 358 if (!config.indicator) { 359 config.triggerChange(3); 360 } 361 }).visibility(config.stars >= 3 ? Visibility.Visible : Visibility.Hidden) 362 Circle({ width: 25, height: 25 }) 363 .fill(config.rating >= 3.4 ? Color.Black : Color.Red) 364 .onClick((event: ClickEvent) => { 365 if (!config.indicator) { 366 if (config.stepSize = 0.5) { 367 config.triggerChange(3.5); 368 return 369 } 370 if (config.stepSize = 1) { 371 config.triggerChange(4); 372 return 373 } 374 } 375 }).visibility(config.stars >= 4 ? Visibility.Visible : Visibility.Hidden).margin({left:10}) 376 Circle({ width: 25, height: 25 }) 377 .fill(config.rating >= 3.9 ? Color.Black : Color.Red) 378 .onClick((event: ClickEvent) => { 379 if (!config.indicator) { 380 config.triggerChange(4); 381 } 382 }).visibility(config.stars >= 4 ? Visibility.Visible : Visibility.Hidden) 383 Circle({ width: 25, height: 25 }) 384 .fill(config.rating >= 4.4 ? Color.Black : Color.Red) 385 .onClick((event: ClickEvent) => { 386 if (!config.indicator) { 387 if (config.stepSize = 0.5) { 388 config.triggerChange(4.5); 389 return 390 } 391 if (config.stepSize = 1) { 392 config.triggerChange(5); 393 return 394 } 395 } 396 }).visibility(config.stars >= 5 ? Visibility.Visible : Visibility.Hidden).margin({left:10}) 397 Circle({ width: 25, height: 25 }) 398 .fill(config.rating >= 4.9 ? Color.Black : Color.Red) 399 .onClick((event: ClickEvent) => { 400 if (!config.indicator) { 401 config.triggerChange(5); 402 } 403 }).visibility(config.stars >= 5 ? Visibility.Visible : Visibility.Hidden) 404 } 405 Text("Rating: "+ config.rating) 406 } 407} 408 409@Entry 410@Component 411struct ratingExample { 412 @State rating: number = 0; 413 @State ratingIndicator: boolean = true; 414 @State ratingStars: number = 0; 415 @State ratingStepsize: number = 0.5; 416 @State ratingEnabled: boolean = true; 417 build() { 418 Row() { 419 Column() { 420 Rating({ 421 rating: 0, 422 indicator: this.ratingIndicator 423 }) 424 .stepSize(this.ratingStepsize) 425 .stars(this.ratingStars) 426 .backgroundColor(Color.Transparent) 427 .width('100%') 428 .height(50) 429 .onChange((value: number) => { 430 console.info('Rating change is'+ value); 431 this.rating = value 432 }) 433 .contentModifier(new MyRatingStyle("hello", 3)) 434 Button(this.ratingIndicator ? "ratingIndicator : true" : "ratingIndicator : false") 435 .onClick((event) => { 436 if (this.ratingIndicator) { 437 this.ratingIndicator = false 438 } else { 439 this.ratingIndicator = true 440 } 441 }).margin({top : 5}) 442 443 Button(this.ratingStars < 5 ? "ratingStars + 1, ratingStars = " + this.ratingStars : "Maximum value of ratingStars: 5") 444 .onClick((event) => { 445 if (this.ratingStars < 5) { 446 this.ratingStars += 1 447 } 448 }).margin({top : 5}) 449 450 Button(this.ratingStars > 0 ? "ratingStars - 1, ratingStars = " + this.ratingStars : "Values less than or equal to 0 are handled as 5") 451 .onClick((event) => { 452 if (this.ratingStars > 0) { 453 this.ratingStars -= 1 454 } 455 }).margin({top : 5}) 456 457 Button(this.ratingStepsize == 0.5 ? "ratingStepsize : 0.5" : "ratingStepsize : 1") 458 .onClick((event) => { 459 if (this.ratingStepsize == 0.5) { 460 this.ratingStepsize = 1 461 } else { 462 this.ratingStepsize = 0.5 463 } 464 }).margin({top : 5}) 465 } 466 .width('100%') 467 .height('100%') 468 .justifyContent(FlexAlign.Center) 469 } 470 .height('100%') 471 } 472} 473``` 474 475 476