HarmonyOS鸿蒙Next中如何实现一个简单的滑块验证组件

HarmonyOS鸿蒙Next中如何实现一个简单的滑块验证组件

![图片](https://alliance-communityfile-drcn.dbankcdn.com/FileServer/getFile/cmtybbs/449/320/254/2850086000449320254.20251226153514.12833749634118822772863168787094:50001231000000:2800:6336D0A091498125953686386A4D380EF14D3757EECDF782141335709449E450.gif)

滑块验证组件,常见于安全验证,它主要用于拦截自动化脚本的非真人操作,区分人类用户和机器程序,从而保护程序安全,那么这样的一个滑块验证组件,我们该如何实现呢?这篇问答,就带着大家着手来实现一下。


更多关于HarmonyOS鸿蒙Next中如何实现一个简单的滑块验证组件的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

防黑产一直是互联网坚持在做的安全事项,为了防止程序攻击,可以说大部分应用都存在一定的安全验证,比如验证码、指纹验证,图形码识别,拖动滑块验证等等,其目的也显而易见,就是建立一道“人机防火墙”,通过要求用户完成一个对人类简单、对机器困难的交互,来有效识别和拦截自动化程序,从而守护程序安全,今天就给大家带来其中的一个简单的验证场景,那就是拖动滑块验证。

拖动滑块验证,可以说,简单便捷,也是常见安全验证中最经典、最常用的一种交互形式,它主要用于拦截自动化脚本的非真人操作,区分人类用户和机器程序,从而保护程序安全,当然了,任何一个程序,都不是百分之百的安全,前几天的快手事件就是一个特例,所以滑块验证只能作为前端的一种简单的拦截方式。

实现效果

当然了,可以自定义定义样式,如下所示:

那么,这样的一个从左滑动到右边的拖动滑块验证,如何实现呢?其实实现起来也是非常的简单,通过绑定手势gesture,便可以轻松实现。

如何实现

实现方式有多种,无非就是两层视图,底部的默认视图,和顶部的滑动视图,我们需要注意的是,顶部的滑动视图,如果,你要采用的是偏移量的方式,也就是先让滑块平移到屏幕外,然后滑动时慢慢的展示,需要注意组件的宽度设置。

以上的方式并不是不推荐,如果是组件和屏幕宽度一致,这时是没有问题的,但是实际当中的组件,是任意位置摆放的,如果还按照偏移量的方式,就会让滑块提前展示,显然是不允许的,所以这一点,需要注意。

一开始,我也是采用的上面的方式,确实实现了效果,但是,固定宽度之后,还需要处理滑块的展示位置,于是,就改成了另一种实现方式,那就是,滑块的宽度默认为0,然后随着手势移动,逐渐增加滑块的宽度,这种方式,就不会存在滑块展示的问题。

//中间的滑层
Column() {
  if (this.sliderView != undefined) {
    this.sliderView()
  } else {
    Column() {

    }.width("100%")
      .height(this.sHeight)
      .border(this.sliderAttribute?.sliderViewAttr?.border)
      .backgroundColor(this.sliderAttribute?.sliderViewAttr?.backgroundColor != undefined ?
                       this.sliderAttribute?.sliderViewAttr?.backgroundColor : "#5abc3c")
  }
}
.width(this._privateOffsetWidth)
  .height(this.sHeight)
  .alignItems(HorizontalAlign.Start)
  .animation({ duration: this._privateDuration })

解决完滑块的问题之后,还有一个需要解决,那就是文字颜色的改变,我们可以发现,在滑动的时候,文字颜色是灰色的,慢慢滑动之后,滑过的文字就会变成白色,而未滑过的文字还是灰色,这是如何实现的呢?

很简单,采用的是两个Text组件,底部的灰色Text,我们不需要改变,主要是顶部的滑块Text文字颜色,这里处理的方式是逐字加载,使用Span组件,根据滑动的距离,分别来更改文字颜色。

ForEach(this.sTextArray, (t: string, index: number) => {
  Span(t)
    .fontColor(this._privateChangeTextColorArray[index])
    .fontSize(14)
    .fontStyle(this.sliderAttribute?.completeTextAttr?.fontStyle)
    .fontWeight(this.sliderAttribute?.completeTextAttr?.fontWeight)
})

滑动逻辑

滑动上没什么好说的,只监听左右滑动即可,随着手势滑动,不断的改变顶部滑动视图的宽度,如果松手未到右边,就还原初始值,如果到最右边,就回调完成,更改滑块状态。

.gesture(
  PanGesture({ distance: 1, direction: PanDirection.Left | PanDirection.Right })
  .onActionStart(() => {
    this._privateDuration = 0
  })
  .onActionUpdate((event: GestureEvent) => {
    //赋值滑块偏移量,必须大于0
    if (event.offsetX > 0) {
      if (event.offsetX > (this._privateWindowWidth - Number(this.thumbWidth))) {
        this._privateThumbOffsetX = this._privateWindowWidth - Number(this.thumbWidth)
        //状态完成时回调
        if (this.onComplete != undefined && !this._privateIsScrollComplete) {
          this._privateIsScrollComplete = true
          this._privateOffsetWidth = this._privateThumbOffsetX
          this.onComplete()
        }
      } else {
        this._privateIsScrollComplete = false
        this._privateOffsetWidth = event.offsetX
        this._privateThumbOffsetX = event.offsetX

      }
    } else {
      this._privateThumbOffsetX = 0
      this._privateOffsetWidth = 0
    }
    //改变文字颜色
    this.changeTextColor(event.offsetX)


  })
  .onActionEnd(() => {
    //滑动结束
    this.changeCompleteStatus()
  })
)

快速使用

为了方便大家使用,目前已经封装好了组件,上传到了中心仓库,大家有需要可以直接使用。

中心仓库地址:

https://ohpm.openharmony.cn/#/cn/detail/@abner%2Fslider

快速依赖

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

建议:在使用的模块路径下进行执行命令。

ohpm install [@abner](/user/abner)/slider

方式二:在需要的模块中的oh-package.json5中设置三方包依赖,配置示例如下:

"dependencies": { "[@abner](/user/abner)/slider": "^1.0.0"}

代码使用

目前默认的是常规的绿色验证样式,如果符合需求,可以直接使用。

SliderDragView({
  onComplete: () => {
    //滑动完成
    console.log("=======滑动完成")
  }
})

自定义组件形式

目前支持所有的样式自定义,需要自己来逐一实现自己需要的UI。

SliderDragView({
  sText: "拖动滑块滑动",
  sCompleteText: "完成验证",
  defaultView: () => {
    //自定义默认视图
    this.defaultView()
  },
  sliderView: () => {
    //自定义滑动视图
    this.sliderView()
  },
  thumbSlidingView: () => {
    //自定义滑块滑动中视图
    this.thumbSlidingView()
  },
  thumbCompleteView: () => {
    //自定义滑块完成视图
    this.thumbCompleteView()
  },
  onComplete: () => {
    //滑动完成
    console.log("=======滑动完成")
  }
}).margin({ top: 20 })

完整案例

import { SliderControl, SliderDragView } from '[@abner](/user/abner)/slider'

@Entry
  @Component
  struct SliderPage {
    sliderControl: SliderControl = new SliderControl()
    sliderControl2: SliderControl = new SliderControl()

    @Builder
    defaultView() {
      Column() {
        Text("拖动滑块滑动")
          .fontSize(14)
      }
      .width("100%")
        .height("100%")
        .justifyContent(FlexAlign.Center)
        .backgroundColor(Color.Pink)
        .borderRadius(10)
    }

    @Builder
    sliderView() {
      Column() {

      }.width("100%")
        .height("100%")
        .backgroundColor(Color.Red)
        .borderRadius({ topLeft: 10, bottomLeft: 10 })
    }

    @Builder
    thumbSlidingView() {
      Text("-->")
        .width("100%")
        .height("100%")
        .backgroundColor(Color.White)
        .textAlign(TextAlign.Center)
        .borderRadius({ topRight: 10, bottomRight: 10 })
        .border({ width: 1, color: "#e8e8e8" })
    }

    @Builder
    thumbCompleteView() {
      Column() {
        SymbolGlyph($r('sys.symbol.checkmark_circle_fill'))
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .renderingStrategy(SymbolRenderingStrategy.SINGLE)
          .fontColor([Color.Red])
      }
      .width("100%")
        .height("100%")
        .backgroundColor(Color.White)
        .justifyContent(FlexAlign.Center)
        .borderRadius({ topRight: 10, bottomRight: 10 })
        .border({ width: 1, color: "#e8e8e8" })
    }

    build() {
      Column() {
        SliderDragView({
          sliderControl: this.sliderControl,
          onComplete: () => {
            //滑动完成
            console.log("=======滑动完成")
          }
        })

        //全部自定义

        SliderDragView({
          sText: "拖动滑块滑动",
          sCompleteText: "完成验证",
          sliderControl: this.sliderControl2,
          defaultView: () => {
            //自定义默认视图
            this.defaultView()
          },
          sliderView: () => {
            //自定义滑动视图
            this.sliderView()
          },
          thumbSlidingView: () => {
            //自定义滑块滑动中视图
            this.thumbSlidingView()
          },
          thumbCompleteView: () => {
            //自定义滑块完成视图
            this.thumbCompleteView()
          },
          onComplete: () => {
            //滑动完成
            console.log("=======滑动完成")
          }
        }).margin({ top: 20 })

        Button("重置")
          .margin({ top: 20 })
          .onClick(() => {
            this.sliderControl.reset()
            this.sliderControl2.reset()
          })
      }
      .height('100%')
        .width('100%')
        .padding({ left: 20, right: 20 })
        .justifyContent(FlexAlign.Center)
    }
  }

相关属性

属性 类型 概述
sWidth Length 整体组件的宽度
sHeight Length 整体组件的高度
thumbWidth Length 滑块的宽度
thumbHeight Length 滑块的高度
defaultView @BuilderParam 自定义传递的默认视图
sliderView @BuilderParam 自定义传递的拖动视图
thumbSlidingView @BuilderParam 拖动的滑块-滑动中视图
thumbCompleteView @BuilderParam 拖动的滑块-滑动完成
sDuration number 手指结束时的动画时间,默认100毫秒
onComplete () => void 滑动完成状态回调
sText string 提示内容, 默认为:按住滑块拖动
sCompleteText string 滑动完成提示内容,默认为:完成验证
sliderControl SliderControl 重置控制器,可还原滑动状态
sliderAttribute SliderDragAttribute 默认滑动视图属性,如果自己定义组件,则不需要

SliderDragAttribute

滑动视图默认属性,如果是使用的自定义组件形式,此属性配置无效。

属性 类型 概述
defaultViewAttr DefaultViewAttribute 默认的视图属性
sliderViewAttr SliderViewAttribute 滑动的视图属性
completeTextAttr CompleteTextAttribute 完成文字属性
thumbCompleteAttr ThumbCompleteAttribute 滑块完成属性
thumbSlidingAttr ThumbCompleteAttribute 滑块滑动属性

相关总结

一个很常见的滑块验证组件,本身并不难,如果有需要,大家可以直接使用,希望可以帮助到你,还是那句话,滑块验证只能作为一个简单的安全验证,它不是绝对安全的,这一点,大家需要知道。

更多关于HarmonyOS鸿蒙Next中如何实现一个简单的滑块验证组件的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,实现滑块验证组件主要使用@Component自定义组件,结合Slider组件和手势事件。通过SlideronChange回调监听滑块移动,使用ColumnStack布局容器组合滑块轨道与背景。验证逻辑在onChange中判断滑块位置是否到达阈值,并触发验证结果。

在HarmonyOS Next中实现滑块验证组件,可以基于ArkUI框架的拖拽手势和自定义组件能力来构建。以下是核心实现思路和关键代码示例:

1. 组件结构设计 使用ColumnStack布局,包含:

  • 背景轨道(带缺口的图片或色块)
  • 可拖动的滑块按钮
  • 提示文本或图标

2. 拖拽逻辑实现

// 使用PanGesture拖拽手势
@State sliderX: number = 0
...
PanGesture(this.sliderArea)
  .onActionUpdate((event: GestureEvent) => {
    // 限制滑动范围在轨道内
    this.sliderX = Math.max(0, Math.min(event.offsetX, maxWidth))
  })
  .onActionEnd(() => {
    // 验证是否对齐到缺口位置
    if (Math.abs(this.sliderX - targetPosition) < tolerance) {
      // 验证成功
    }
  })

3. 验证机制

  • 在组件初始化时随机生成缺口位置
  • 拖拽结束时判断滑块中心与缺口中心的距离
  • 可添加辅助动画(成功回弹/失败震动)

4. 安全增强

  • 服务端二次验证:将滑动轨迹数据发送到服务端分析行为模式
  • 添加随机干扰元素:生成伪缺口或轨道纹理
  • 轨迹分析:记录移动速度和加速度曲线

5. 完整示例框架

@Component
struct SliderVerification {
  @State private offsetX: number = 0
  private targetPosition: number = 0
  
  aboutToAppear() {
    // 随机生成目标位置
    this.targetPosition = Math.random() * 250 + 50
  }
  
  build() {
    Stack({ alignContent: Alignment.Start }) {
      // 背景轨道
      Image($r('app.media.track'))
        .overlay(this.buildGap(), { align: Alignment.Start })
      
      // 可拖动滑块
      Image($r('app.media.slider'))
        .position({ x: this.offsetX })
        .gesture(this.createPanGesture())
    }
  }
}

关键点:

  1. 使用@State管理滑块位置实现响应式更新
  2. 通过PanGesture实现精确拖拽控制
  3. 验证阈值建议设为缺口宽度的1/3
  4. 可配合Canvas绘制自定义轨道样式

这种实现方式完全基于HarmonyOS原生能力,无需第三方库,性能优化良好且符合系统设计规范。

回到顶部