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