img

一、案例介绍

本案例将展示如何通过样式定制和主题切换功能,实现一个具有美观交互效果的Radio组件应用。我们将创建一个主题设置面板,展示Radio组件的高度可定制性。

二、代码实现

1. 主题设置面板

@Entry
@Component
struct ThemeSettingsPanel {
  @State currentTheme: string = 'light'
  @State accentColor: string = 'blue'
  @State fontSize: string = 'medium'

  @State themeColors: {
    background: string,
    text: string,
    primary: string
  } = {
    background: '#FFFFFF',
    text: '#333333',
    primary: '#2196F3'
  }

  build() {
    Column({ space: 20 }) {
      Text('主题设置')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.themeColors.text)

      // 主题模式选择
      Column({ space: 15 }) {
        Text('主题模式:')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor(this.themeColors.text)

        Row({ space: 30 }) {
          this.ThemeOption('light', '浅色模式')
          this.ThemeOption('dark', '深色模式')
          this.ThemeOption('auto', '跟随系统')
        }
      }

      // 主题色选择
      Column({ space: 15 }) {
        Text('主题色:')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor(this.themeColors.text)

        Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.Start }) {
          this.ColorOption('blue', '#2196F3')
          this.ColorOption('green', '#4CAF50')
          this.ColorOption('purple', '#9C27B0')
          this.ColorOption('orange', '#FF9800')
          this.ColorOption('red', '#F44336')
        }
      }

      // 字体大小选择
      Column({ space: 15 }) {
        Text('字体大小:')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor(this.themeColors.text)

        Row({ space: 30 }) {
          this.FontSizeOption('small', '小')
          this.FontSizeOption('medium', '中')
          this.FontSizeOption('large', '大')
        }
      }

      // 预览区域
      Column({ space: 10 }) {
        Text('预览效果')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor(this.themeColors.text)

        Column({ space: 15 }) {
          this.PreviewItem('标题文本', 20)
          this.PreviewItem('正文内容', 16)
          this.PreviewItem('辅助信息', 14)
        }
        .padding(15)
        .borderRadius(10)
        .backgroundColor(this.themeColors.background)
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor(this.currentTheme === 'dark' ? '#121212' : '#F5F5F5')
  }

  @Builder
  ThemeOption(value: string, label: string) {
    Row({ space: 10 }) {
      Radio({ value: value, group: 'theme' })
        .checked(this.currentTheme === value)
        .width(20)
        .height(20)
        .color(this.themeColors.primary)
        .onChange((checked: boolean) => {
          if (checked) {
            this.currentTheme = value
            this.updateThemeColors()
          }
        })
      Text(label)
        .fontSize(14)
        .fontColor(this.themeColors.text)
    }
  }

  @Builder
  ColorOption(value: string, color: string) {
    Row({ space: 10 }) {
      Radio({ value: value, group: 'color' })
        .checked(this.accentColor === value)
        .width(20)
        .height(20)
        .color(color)
        .onChange((checked: boolean) => {
          if (checked) {
            this.accentColor = value
            this.themeColors.primary = color
          }
        })
      Text(value)
        .fontSize(14)
        .fontColor(this.themeColors.text)
    }
    .margin({ right: 20, bottom: 10 })
  }

  @Builder
  FontSizeOption(value: string, label: string) {
    Row({ space: 10 }) {
      Radio({ value: value, group: 'fontSize' })
        .checked(this.fontSize === value)
        .width(20)
        .height(20)
        .color(this.themeColors.primary)
        .onChange((checked: boolean) => {
          if (checked) {
            this.fontSize = value
          }
        })
      Text(label)
        .fontSize(14)
        .fontColor(this.themeColors.text)
    }
  }

  @Builder
  PreviewItem(text: string, size: number) {
    Text(text)
      .fontSize(this.getFontSize(size))
      .fontColor(this.themeColors.text)
      .opacity(size === 14 ? 0.6 : 1)
  }

  getFontSize(baseSize: number): number {
    switch (this.fontSize) {
      case 'small':
        return baseSize - 2
      case 'large':
        return baseSize + 2
      default:
        return baseSize
    }
  }

  updateThemeColors() {
    if (this.currentTheme === 'dark') {
      this.themeColors = {
        background: '#1E1E1E',
        text: '#FFFFFF',
        primary: this.themeColors.primary
      }
    } else {
      this.themeColors = {
        background: '#FFFFFF',
        text: '#333333',
        primary: this.themeColors.primary
      }
    }
  }
}

三、总结

本案例通过一个主题设置面板,展示了 Radio 组件的样式定制和主题切换功能。通过为 Radio 组件设置不同的样式属性(如颜色、大小等),实现了浅色模式、深色模式和跟随系统模式的主题切换,并提供了多种主题色和字体大小的选项。同时,通过动态更新样式和数据绑定,实现了预览区域的实时效果展示。这种高度可定制性不仅提升了界面的美观度,还增强了用户体验,开发者可以参考此案例,灵活运用 Radio 组件的样式定制功能,满足不同场景下的设计需求。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐