• 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 = 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}