DEV Community

HarmonyOS
HarmonyOS

Posted on

Add Text to the Circular Slider of a Toggle

Read the original article:Add Text to the Circular Slider of a Toggle

Requirement Description

The goal is to add text (such as "On" / "Off") directly on the circular slider of a Toggle component.

Background Knowledge

When a Toggle is set to a switch style, it supports configuring properties such as the circular slider radius and color through switchStyle. For more advanced customization, the contentModifier can be used to define the Toggle’s content area.
In addition, when general properties of the component change, property animations can be applied to achieve smooth transitions.

Implementation Steps

  1. Recognize that switchStyle only supports radius and color adjustments, not content like text.
  2. Create a custom contentModifier to override the Toggle content and place text inside the circular slider.
  3. Implement property animations (animation) to mimic Toggle’s native behavior with smooth slider position changes and background color transitions.
  4. Define customizable parameters such as colors, radius, labels, and font size.
  5. Apply the custom modifier to the Toggle and handle state changes (onChange).

Code Snippet / Configuration

interface SwitchParam {
  circleRadius: number,
  borderRadius: number,
  selectedCircleColor: ResourceColor,
  unselectedCircleColor: ResourceColor,
  selectedColor: ResourceColor,
  unselectedColor: ResourceColor,
  selectedLabel?: string,
  unselectedLabel?: string,
  labelColor?: ResourceColor,
  labelSize?: number
}

class MySwitchStyle implements ContentModifier<ToggleConfiguration> {
  switchStyle: SwitchParam;

  constructor(switchStyle: SwitchParam) {
    this.switchStyle = switchStyle;
  }

  applyContent(): WrappedBuilder<[ToggleConfiguration]> {
    return wrapBuilder(buildSwitch);
  }
}

@Builder
function buildSwitch(config: ToggleConfiguration) {
  Column() {
    Button(config.isOn
      ? (config.contentModifier as MySwitchStyle).switchStyle.selectedLabel ?? ''
      : (config.contentModifier as MySwitchStyle).switchStyle.unselectedLabel ?? '',
      { type: ButtonType.Circle })
      .fontColor((config.contentModifier as MySwitchStyle).switchStyle.labelColor)
      .fontSize((config.contentModifier as MySwitchStyle).switchStyle.labelSize)
      .height((config.contentModifier as MySwitchStyle).switchStyle.circleRadius * 2)
      .width((config.contentModifier as MySwitchStyle).switchStyle.circleRadius * 2)
      .padding(0)
      .onClick(() => {
        config.isOn ? config.triggerChange(false) : config.triggerChange(true)
      })
      .backgroundColor(config.isOn
        ? (config.contentModifier as MySwitchStyle).switchStyle.selectedCircleColor
        : (config.contentModifier as MySwitchStyle).switchStyle.unselectedCircleColor)
      .animation({
        duration: 200,
        curve: Curve.Ease,
        playMode: PlayMode.Normal
      })
  }
  .padding((config.contentModifier as MySwitchStyle).switchStyle.borderRadius - (config.contentModifier as MySwitchStyle).switchStyle.circleRadius)
  .alignItems(config.isOn ? HorizontalAlign.Start : HorizontalAlign.End)
  .justifyContent(FlexAlign.Center)
  .backgroundColor(config.isOn
    ? (config.contentModifier as MySwitchStyle).switchStyle.selectedColor
    : (config.contentModifier as MySwitchStyle).switchStyle.unselectedColor)
  .borderRadius((config.contentModifier as MySwitchStyle).switchStyle.borderRadius)
  .height((config.contentModifier as MySwitchStyle).switchStyle.borderRadius * 2)
  .width((config.contentModifier as MySwitchStyle).switchStyle.borderRadius * 4 + 2)
  .animation({
    duration: 200,
    curve: Curve.Ease,
    playMode: PlayMode.Normal
  })
}

@Entry
@Component
struct Index {
  build() {
    Column() {
      Toggle({ type: ToggleType.Switch })
        .enabled(true)
        .contentModifier(new MySwitchStyle({
          circleRadius: 9,
          borderRadius: 10,
          selectedCircleColor: Color.White,
          unselectedCircleColor: Color.White,
          selectedColor: '#ff5d7ef5',
          unselectedColor: '#e4a0b4e7',
          selectedLabel: 'On',
          unselectedLabel: 'Off',
          labelColor: Color.Black,
          labelSize: 12
        }))
        .onChange((isOn: boolean) => {
          console.info(`Switch Log: ${isOn}`);
        })
    }.height('100%').width('100%').justifyContent(FlexAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

Test Results

  • Verified that the text "On" and "Off" appears on the circular slider depending on the Toggle state.
  • Animations for slider movement and background color transition work smoothly.
  • Labels update correctly when switching states.

Limitations or Considerations

  • The native switchStyle does not support labels; customization must be done through contentModifier.
  • Additional styling (fonts, colors) needs to be defined manually in the custom implementation.

Related Documents or Links

Written by Hasan Kaya

Top comments (0)