1/* 2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16export enum IconType { 17 BADGE = 1, 18 NORMAL_ICON, 19 SYSTEM_ICON, 20 HEAD_SCULPTURE, 21 APP_ICON, 22 PREVIEW, 23 LONGITUDINAL, 24 VERTICAL 25} 26 27enum ItemHeight { 28 FIRST_HEIGHT = 48, 29 SECOND_HEIGHT = 56, 30 THIRD_HEIGHT = 64, 31 FOURTH_HEIGHT = 72, 32 FIFTH_HEIGHT = 96 33} 34 35export type OperateItem = { 36 icon?: OperateIcon, 37 subIcon ?: OperateIcon, 38 button?: OperateButton; 39 switch?: OperateCheck; 40 checkbox?: OperateCheck; 41 radio?: OperateCheck; 42 image?: ResourceStr; 43 text?: ResourceStr; 44 arrow?: OperateIcon; 45} 46 47export type ContentItem = { 48 iconStyle?: IconType; 49 icon?: ResourceStr; 50 primaryText?: ResourceStr; 51 secondaryText?: ResourceStr; 52 description?: ResourceStr; 53} 54 55export declare type OperateIcon = { 56 value: ResourceStr, 57 action?: () => void 58} 59 60export type OperateButton = { 61 text?: string 62} 63 64export declare type OperateCheck = { 65 isCheck?: boolean, 66 onChange?: (value: boolean) => void 67} 68 69const TEXT_MAX_LINE = 1; 70const ITEM_BORDER_SHOWN = 2; 71const TEXT_COLUMN_SPACE = 4; 72const TEXT_SAFE_MARGIN = 12; 73const LISTITEM_PADDING = 12; 74const BADGE_SIZE = 8; 75const SMALL_ICON_SIZE = 16; 76const SYSTEM_ICON_SIZE = 24; 77const TEXT_ARROW_HEIGHT = 32; 78const SAFE_LIST_PADDING = 32; 79const HEADSCULPTURE_SIZE = 40; 80const BUTTON_SIZE = 28; 81const APP_ICON_SIZE = 64; 82const PREVIEW_SIZE = 96; 83const LONGITUDINAL_SIZE = 96; 84const VERTICAL_SIZE = 96; 85const NORMAL_ITEM_ROW_SPACE = 16; 86const SPECIAL_ITEM_ROW_SPACE = 0; 87const SPECIAL_ICON_SIZE = 0; 88const DEFAULT_ROW_SPACE = 0; 89const SPECICAL_ROW_SPACE = 4; 90const OPERATEITEM_ICONLIKE_SIZE = 24; 91const OPERATEITEM_ARROW_WIDTH = 12 92const OPERATEITEM_ICON_CLICKABLE_SIZE = 48; 93const OPERATEITEM_IMAGE_SIZE = 48; 94const HOVERING_COLOR = '#0d000000'; 95const TOUCH_DOWN_COLOR = '#1a000000'; 96const ACTIVED_COLOR = '#1a0a59f7'; 97const ICON_SIZE_MAP: Map<number, number> = new Map([ 98 [IconType.BADGE, BADGE_SIZE], 99 [IconType.NORMAL_ICON, SMALL_ICON_SIZE], 100 [IconType.SYSTEM_ICON, SYSTEM_ICON_SIZE], 101 [IconType.HEAD_SCULPTURE, HEADSCULPTURE_SIZE], 102 [IconType.APP_ICON, APP_ICON_SIZE], 103 [IconType.PREVIEW, PREVIEW_SIZE], 104 [IconType.LONGITUDINAL, LONGITUDINAL_SIZE], 105 [IconType.VERTICAL, VERTICAL_SIZE] 106]) 107 108@Component 109struct ContentItemStruct { 110 iconStyle: IconType = null 111 icon: Resource = null 112 primaryText: string = null 113 secondaryText: string = null 114 description: string = null 115 private itemRowSpace: number = NORMAL_ITEM_ROW_SPACE 116 117 aboutToAppear() { 118 if (this.icon == null && this.iconStyle == null) { 119 this.itemRowSpace = SPECIAL_ITEM_ROW_SPACE 120 } 121 } 122 123 @Builder 124 createIcon() { 125 if (this.icon != null && this.iconStyle != null) { 126 if (this.iconStyle <= IconType.PREVIEW) { 127 Image(this.icon) 128 .objectFit(ImageFit.Contain) 129 .width(ICON_SIZE_MAP.get(this.iconStyle)) 130 .height(ICON_SIZE_MAP.get(this.iconStyle)) 131 .borderRadius($r('sys.float.ohos_id_corner_radius_default_m')) 132 .focusable(true) 133 .draggable(false) 134 } 135 else { 136 Image(this.icon) 137 .objectFit(ImageFit.Contain) 138 .constraintSize({ 139 minWidth: SPECIAL_ICON_SIZE, 140 maxWidth: ICON_SIZE_MAP.get(this.iconStyle), 141 minHeight: SPECIAL_ICON_SIZE, 142 maxHeight: ICON_SIZE_MAP.get(this.iconStyle) 143 }) 144 .borderRadius($r('sys.float.ohos_id_corner_radius_default_m')) 145 .focusable(true) 146 .draggable(false) 147 } 148 } 149 } 150 151 @Builder 152 createText() { 153 Column({ space: TEXT_COLUMN_SPACE }) { 154 Text(this.primaryText) 155 .fontSize($r('sys.float.ohos_id_text_size_body1')) 156 .fontColor($r('sys.color.ohos_id_color_text_primary')) 157 .maxLines(TEXT_MAX_LINE) 158 .textOverflow({ overflow: TextOverflow.Ellipsis }) 159 .fontWeight(FontWeight.Medium) 160 .focusable(true) 161 .draggable(false) 162 if (this.secondaryText != null) { 163 Text(this.secondaryText) 164 .fontSize($r('sys.float.ohos_id_text_size_body2')) 165 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 166 .maxLines(TEXT_MAX_LINE) 167 .textOverflow({ overflow: TextOverflow.Ellipsis }) 168 .focusable(true) 169 .draggable(false) 170 } 171 if (this.description != null) { 172 Text(this.description) 173 .fontSize($r('sys.float.ohos_id_text_size_body2')) 174 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 175 .maxLines(TEXT_MAX_LINE) 176 .textOverflow({ overflow: TextOverflow.Ellipsis }) 177 .focusable(true) 178 .draggable(false) 179 } 180 } 181 .flexShrink(1) 182 .margin({ 183 top: TEXT_SAFE_MARGIN, 184 bottom: TEXT_SAFE_MARGIN 185 }) 186 .alignItems(HorizontalAlign.Start) 187 } 188 189 build() { 190 Row({ space: this.itemRowSpace }) { 191 this.createIcon() 192 this.createText() 193 } 194 .margin({ right: 16 }) 195 .padding({ left: LISTITEM_PADDING }) 196 .width("calc(66% - 16vp)") 197 .flexShrink(1) 198 } 199} 200 201@Component 202struct OperateItemStruct { 203 arrow: OperateIcon = null 204 icon: OperateIcon = null 205 subIcon: OperateIcon = null 206 button: OperateButton = null 207 switch: OperateCheck = null 208 checkBox: OperateCheck = null 209 radio: OperateCheck = null 210 image: Resource = null 211 text: string = null 212 @State switchState: boolean = false 213 @State radioState: boolean = false 214 @State checkBoxState: boolean = false 215 @Link parentCanFocus: boolean 216 @Link parentCanTouch: boolean 217 @Link parentIsHover: boolean 218 @Link parentCanHover: boolean 219 @Link parentIsActive: boolean 220 @Link parentFrontColor: string 221 private rowSpace: number = DEFAULT_ROW_SPACE 222 223 aboutToAppear() { 224 if (this.switch != null) { 225 this.switchState = this.switch.isCheck 226 } 227 if (this.radio != null) { 228 this.radioState = this.radio.isCheck 229 } 230 if (this.checkBox != null) { 231 this.checkBoxState = this.checkBox.isCheck 232 } 233 234 if ((this.button == null && this.image == null && this.icon != null && this.text != null) || 235 (this.button == null && this.image == null && this.icon == null && this.arrow != null && this.text != null)) { 236 this.rowSpace = SPECICAL_ROW_SPACE 237 } 238 } 239 240 @Builder 241 createButton(text: string) { 242 Button() { 243 Row() { 244 Text(text) 245 .focusable(true) 246 } 247 .padding({ 248 left: TEXT_SAFE_MARGIN, 249 right: TEXT_SAFE_MARGIN 250 }) 251 } 252 .margin({ right: LISTITEM_PADDING }) 253 .hitTestBehavior(HitTestMode.Block) 254 .fontSize($r('sys.float.ohos_id_text_size_button3')) 255 .fontColor($r('sys.color.ohos_id_color_text_primary_activated_transparent')) 256 .height(BUTTON_SIZE) 257 .backgroundColor($r('sys.color.ohos_id_color_button_normal')) 258 .labelStyle({ 259 maxLines: TEXT_MAX_LINE 260 }) 261 .onFocus(() => { 262 this.parentCanFocus = false 263 }) 264 .onTouch((event: TouchEvent) => { 265 if (event.type == TouchType.Down) { 266 this.parentCanTouch = false 267 } 268 if (event.type == TouchType.Up) { 269 this.parentCanTouch = true 270 } 271 }) 272 .onHover((isHover: boolean) => { 273 this.parentCanHover = false 274 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 275 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 276 } 277 if (!isHover) { 278 this.parentCanHover = true 279 if (this.parentIsHover) { 280 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 281 } 282 } 283 }) 284 } 285 286 @Builder 287 createIcon(icon: OperateIcon) { 288 Button({ type: ButtonType.Normal }) { 289 Image(icon.value) 290 .height(OPERATEITEM_ICONLIKE_SIZE) 291 .width(OPERATEITEM_ICONLIKE_SIZE) 292 .focusable(true) 293 .fillColor($r('sys.color.ohos_id_color_primary')) 294 .draggable(false) 295 } 296 .hitTestBehavior(HitTestMode.Block) 297 .backgroundColor(Color.Transparent) 298 .height(OPERATEITEM_ICON_CLICKABLE_SIZE) 299 .width(OPERATEITEM_ICON_CLICKABLE_SIZE) 300 .borderRadius($r('sys.float.ohos_id_corner_radius_clicked')) 301 .onFocus(() => { 302 this.parentCanFocus = false 303 }) 304 .onTouch((event: TouchEvent) => { 305 if (event.type == TouchType.Down) { 306 this.parentCanTouch = false 307 } 308 if (event.type == TouchType.Up) { 309 this.parentCanTouch = true 310 } 311 }) 312 .onHover((isHover: boolean) => { 313 this.parentCanHover = false 314 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 315 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 316 } 317 if (!isHover) { 318 this.parentCanHover = true 319 if (this.parentIsHover) { 320 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 321 } 322 } 323 }) 324 .onClick((icon.action)) 325 } 326 327 @Builder 328 createImage(image: Resource) { 329 Image(image) 330 .height(OPERATEITEM_IMAGE_SIZE) 331 .width(OPERATEITEM_IMAGE_SIZE) 332 .draggable(false) 333 .margin({ right: LISTITEM_PADDING }) 334 } 335 336 @Builder 337 createText(text: string) { 338 Text(text) 339 .fontSize($r('sys.float.ohos_id_text_size_body2')) 340 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 341 .focusable(true) 342 .draggable(false) 343 .flexShrink(1) 344 } 345 346 @Builder 347 createArrow(icon: OperateIcon) { 348 Button({ type: ButtonType.Normal }) { 349 Image(icon.value) 350 .height(OPERATEITEM_ICONLIKE_SIZE) 351 .width(OPERATEITEM_ARROW_WIDTH) 352 .focusable(true) 353 .fillColor($r('sys.color.ohos_id_color_fourth')) 354 .draggable(false) 355 } 356 .margin({ right: LISTITEM_PADDING }) 357 .hitTestBehavior(HitTestMode.Block) 358 .backgroundColor(Color.Transparent) 359 .height(OPERATEITEM_ICONLIKE_SIZE) 360 .width(OPERATEITEM_ARROW_WIDTH) 361 .onFocus(() => { 362 this.parentCanFocus = false 363 }) 364 .onTouch((event: TouchEvent) => { 365 if (event.type == TouchType.Down) { 366 this.parentCanTouch = false 367 } 368 if (event.type == TouchType.Up) { 369 this.parentCanTouch = true 370 } 371 }) 372 .onHover((isHover: boolean) => { 373 this.parentCanHover = false 374 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 375 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 376 } 377 if (!isHover) { 378 this.parentCanHover = true 379 if (this.parentIsHover) { 380 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 381 } 382 } 383 }) 384 .onClick(icon.action) 385 } 386 387 @Builder 388 createRadio(radio: OperateCheck) { 389 Radio({ value: null, group: null }) 390 .margin({ right: LISTITEM_PADDING }) 391 .checked(this.radioState) 392 .onChange(radio.onChange) 393 .height(OPERATEITEM_ICONLIKE_SIZE) 394 .width(OPERATEITEM_ICONLIKE_SIZE) 395 .onFocus(() => { 396 this.parentCanFocus = false 397 }) 398 .hitTestBehavior(HitTestMode.Block) 399 .onTouch((event: TouchEvent) => { 400 if (event.type == TouchType.Down) { 401 this.parentCanTouch = false 402 } 403 if (event.type == TouchType.Up) { 404 this.parentCanTouch = true 405 } 406 }) 407 .onHover((isHover: boolean) => { 408 this.parentCanHover = false 409 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 410 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 411 } 412 if (!isHover) { 413 this.parentCanHover = true 414 if (this.parentIsHover) { 415 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 416 } 417 } 418 }) 419 } 420 421 @Builder 422 createCheckBox(checkBox: OperateCheck) { 423 Checkbox() 424 .margin({ right: LISTITEM_PADDING }) 425 .select(this.checkBoxState) 426 .onChange(checkBox.onChange) 427 .height(OPERATEITEM_ICONLIKE_SIZE) 428 .height(OPERATEITEM_ICONLIKE_SIZE) 429 .onFocus(() => { 430 this.parentCanFocus = false 431 }) 432 .hitTestBehavior(HitTestMode.Block) 433 .onTouch((event: TouchEvent) => { 434 if (event.type == TouchType.Down) { 435 this.parentCanTouch = false 436 } 437 if (event.type == TouchType.Up) { 438 this.parentCanTouch = true 439 } 440 }) 441 .onHover((isHover: boolean) => { 442 this.parentCanHover = false 443 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 444 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 445 } 446 if (!isHover) { 447 this.parentCanHover = true 448 if (this.parentIsHover) { 449 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 450 } 451 } 452 }) 453 } 454 455 @Builder 456 createSwitch(toggleParams: OperateCheck) { 457 Row() { 458 Toggle({ type: ToggleType.Switch, isOn: this.switchState }) 459 .onChange(toggleParams.onChange) 460 .onClick(() => { 461 this.switchState = !this.switchState 462 }) 463 .hitTestBehavior(HitTestMode.Block) 464 } 465 .margin({ right: LISTITEM_PADDING / 2 }) 466 .height(OPERATEITEM_ICON_CLICKABLE_SIZE) 467 .width(OPERATEITEM_ICON_CLICKABLE_SIZE) 468 .justifyContent(FlexAlign.Center) 469 .onFocus(() => { 470 this.parentCanFocus = false 471 }) 472 .onTouch((event: TouchEvent) => { 473 if (event.type == TouchType.Down) { 474 this.parentCanTouch = false 475 } 476 if (event.type == TouchType.Up) { 477 this.parentCanTouch = true 478 } 479 }) 480 .onHover((isHover: boolean) => { 481 this.parentCanHover = false 482 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 483 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 484 } 485 if (!isHover) { 486 this.parentCanHover = true 487 if (this.parentIsHover) { 488 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 489 } 490 } 491 }) 492 } 493 494 @Builder 495 createTextArrow(text: string, icon: OperateIcon) { 496 Button({ type: ButtonType.Normal }) { 497 Row({ space: SPECICAL_ROW_SPACE }) { 498 Text(text) 499 .fontSize($r('sys.float.ohos_id_text_size_body2')) 500 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 501 .focusable(true) 502 .draggable(false) 503 .constraintSize({ 504 maxWidth: `calc(100% - ${ OPERATEITEM_ARROW_WIDTH + TEXT_SAFE_MARGIN }vp)` 505 }) 506 Image(icon.value) 507 .height(OPERATEITEM_ICONLIKE_SIZE) 508 .width(OPERATEITEM_ARROW_WIDTH) 509 .fillColor($r('sys.color.ohos_id_color_fourth')) 510 .focusable(true) 511 .draggable(false) 512 } 513 .padding({ 514 left: TEXT_SAFE_MARGIN, 515 right: TEXT_SAFE_MARGIN 516 }) 517 } 518 .hitTestBehavior(HitTestMode.Block) 519 .labelStyle({ 520 maxLines: TEXT_MAX_LINE 521 }) 522 .backgroundColor(Color.Transparent) 523 .height(TEXT_ARROW_HEIGHT) 524 .borderRadius($r('sys.float.ohos_id_corner_radius_clicked')) 525 .onFocus(() => { 526 this.parentCanFocus = false 527 }) 528 .onTouch((event: TouchEvent) => { 529 if (event.type == TouchType.Down) { 530 this.parentCanTouch = false 531 } 532 if (event.type == TouchType.Up) { 533 this.parentCanTouch = true 534 } 535 }) 536 .onHover((isHover: boolean) => { 537 this.parentCanHover = false 538 if (isHover && this.parentFrontColor == HOVERING_COLOR) { 539 this.parentFrontColor = this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString() 540 } 541 if (!isHover) { 542 this.parentCanHover = true 543 if (this.parentIsHover) { 544 this.parentFrontColor = this.parentIsHover ? HOVERING_COLOR : (this.parentIsActive ? ACTIVED_COLOR : Color.Transparent.toString()) 545 } 546 } 547 }) 548 .onClick(icon.action) 549 } 550 551 build() { 552 Row({ 553 space: this.rowSpace 554 }) { 555 if (this.button != null) { 556 this.createButton(this.button.text) 557 } 558 559 else if (this.image != null) { 560 this.createImage(this.image) 561 } 562 else if (this.icon != null && this.text != null) { 563 this.createText(this.text) 564 this.createIcon(this.icon) 565 } 566 else if (this.arrow != null && this.text == null) { 567 this.createArrow(this.arrow) 568 } 569 else if (this.arrow != null && this.text != null) { 570 this.createTextArrow(this.text, this.arrow) 571 } 572 else if (this.text != null) { 573 this.createText(this.text) 574 } 575 else if (this.radio != null) { 576 this.createRadio(this.radio) 577 } 578 else if (this.checkBox != null) { 579 this.createCheckBox(this.checkBox) 580 } 581 else if (this.switch != null) { 582 this.createSwitch(this.switch) 583 } 584 else if (this.icon != null) { 585 this.createIcon(this.icon) 586 if (this.subIcon != null) { 587 this.createIcon(this.subIcon) 588 } 589 } 590 } 591 .width("34%") 592 .flexShrink(1) 593 .justifyContent(FlexAlign.End) 594 } 595} 596 597@Component 598export struct ComposeListItem { 599 @Prop contentItem: ContentItem = null; 600 @Prop operateItem: OperateItem = null; 601 @State frontColor: string = Color.Transparent.toString() 602 @State borderSize: number = 0; 603 @State canFocus: boolean = false 604 @State canTouch: boolean = true 605 @State canHover: boolean = true 606 @State isHover: boolean = true 607 @State itemHeight: number = ItemHeight.FIRST_HEIGHT; 608 @State isActive: boolean = false 609 610 aboutToAppear() { 611 if (this.contentItem === undefined) { 612 if (this.operateItem.image !== undefined || this.operateItem.icon !== undefined || this.operateItem.subIcon !== undefined) { 613 this.itemHeight = OPERATEITEM_IMAGE_SIZE + SAFE_LIST_PADDING 614 } 615 return 616 } 617 618 if (this.contentItem.secondaryText === undefined && this.contentItem.description === undefined) { 619 if (this.contentItem.icon === undefined) { 620 this.itemHeight = ItemHeight.FIRST_HEIGHT 621 } 622 else { 623 this.itemHeight = this.contentItem.iconStyle <= IconType.HEAD_SCULPTURE ? ItemHeight.SECOND_HEIGHT : ItemHeight.THIRD_HEIGHT 624 } 625 } 626 else if (this.contentItem.description === undefined) { 627 if (this.contentItem.icon === undefined || (this.contentItem.icon !== undefined && this.contentItem.iconStyle <= IconType.SYSTEM_ICON)) { 628 this.itemHeight = ItemHeight.THIRD_HEIGHT 629 } 630 else { 631 this.itemHeight = ItemHeight.FOURTH_HEIGHT 632 } 633 } 634 else { 635 this.itemHeight = ItemHeight.FIFTH_HEIGHT 636 } 637 638 if (ICON_SIZE_MAP.get(this.contentItem.iconStyle) >= this.itemHeight) { 639 this.itemHeight = ICON_SIZE_MAP.get(this.contentItem.iconStyle) + SAFE_LIST_PADDING; 640 } 641 } 642 643 build() { 644 Stack() { 645 Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 646 if (this.contentItem === null) { 647 ContentItemStruct({}) 648 } 649 if (this.contentItem !== null) { 650 ContentItemStruct({ 651 icon: typeof this.contentItem.icon === 'string' ? null : this.contentItem.icon, 652 iconStyle: this.contentItem.iconStyle, 653 primaryText: typeof this.contentItem.primaryText === 'string' ? this.contentItem.primaryText : null, 654 secondaryText: typeof this.contentItem.secondaryText === 'string' ? this.contentItem.secondaryText : null, 655 description: typeof this.contentItem.description === 'string' ? this.contentItem.description : null 656 }) 657 } 658 if (this.operateItem !== null) { 659 OperateItemStruct({ 660 icon: this.operateItem.icon, 661 subIcon: this.operateItem.subIcon, 662 button: this.operateItem.button, 663 switch: this.operateItem.switch, 664 checkBox: this.operateItem.checkbox, 665 radio: this.operateItem.radio, 666 image: typeof this.operateItem.image === 'string' ? null : this.operateItem.image, 667 text: typeof this.operateItem.text === 'string' ? this.operateItem.text : null, 668 arrow: typeof this.operateItem.arrow === 'string' ? null : this.operateItem.arrow, 669 parentCanFocus: this.canFocus, 670 parentCanTouch: this.canTouch, 671 parentIsHover: this.isHover, 672 parentFrontColor: this.frontColor, 673 parentIsActive: this.isActive, 674 parentCanHover: this.canHover 675 }) 676 .onFocus(() => { 677 this.canFocus = false 678 }) 679 .onBlur(() => { 680 this.canFocus = true 681 }) 682 } 683 } 684 .height(this.itemHeight) 685 .focusable(true) 686 .borderRadius($r('sys.float.ohos_id_corner_radius_default_m')) 687 .backgroundColor(this.frontColor) 688 .onFocus(() => { 689 this.canFocus = true 690 }) 691 .onBlur(() => { 692 this.canFocus = false 693 }) 694 .onHover((isHover: boolean) => { 695 this.isHover = isHover 696 if (this.canHover) { 697 this.frontColor = isHover ? HOVERING_COLOR : (this.isActive ? ACTIVED_COLOR : Color.Transparent.toString()) 698 } 699 }) 700 .onTouch((event: TouchEvent) => { 701 if (event.type == TouchType.Down && this.canTouch) { 702 this.frontColor = TOUCH_DOWN_COLOR 703 } 704 if (event.type == TouchType.Up) { 705 this.frontColor = this.isActive ? ACTIVED_COLOR : Color.Transparent.toString() 706 } 707 }) 708 709 if (this.canFocus) { 710 Row() 711 .height(this.itemHeight) 712 .width('100%') 713 .hitTestBehavior(HitTestMode.None) 714 .border({ 715 width: ITEM_BORDER_SHOWN, 716 color: $r('sys.color.ohos_id_color_focused_outline') 717 }) 718 .borderRadius($r('sys.float.ohos_id_corner_radius_default_m')) 719 } 720 } 721 .padding({ 722 left: $r('sys.float.ohos_id_default_padding_start'), 723 right: $r('sys.float.ohos_id_default_padding_end') 724 }) 725 } 726}