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

滑块验证组件,常见于安全验证,它主要用于拦截自动化脚本的非真人操作,区分人类用户和机器程序,从而保护程序安全,那么这样的一个滑块验证组件,我们该如何实现呢?这篇问答,就带着大家着手来实现一下。
更多关于HarmonyOS鸿蒙Next中如何实现一个简单的滑块验证组件的实战教程也可以访问 https://www.itying.com/category-93-b0.html
防黑产一直是互联网坚持在做的安全事项,为了防止程序攻击,可以说大部分应用都存在一定的安全验证,比如验证码、指纹验证,图形码识别,拖动滑块验证等等,其目的也显而易见,就是建立一道“人机防火墙”,通过要求用户完成一个对人类简单、对机器困难的交互,来有效识别和拦截自动化程序,从而守护程序安全,今天就给大家带来其中的一个简单的验证场景,那就是拖动滑块验证。
拖动滑块验证,可以说,简单便捷,也是常见安全验证中最经典、最常用的一种交互形式,它主要用于拦截自动化脚本的非真人操作,区分人类用户和机器程序,从而保护程序安全,当然了,任何一个程序,都不是百分之百的安全,前几天的快手事件就是一个特例,所以滑块验证只能作为前端的一种简单的拦截方式。
实现效果

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

那么,这样的一个从左滑动到右边的拖动滑块验证,如何实现呢?其实实现起来也是非常的简单,通过绑定手势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组件和手势事件。通过Slider的onChange回调监听滑块移动,使用Column和Stack布局容器组合滑块轨道与背景。验证逻辑在onChange中判断滑块位置是否到达阈值,并触发验证结果。
在HarmonyOS Next中实现滑块验证组件,可以基于ArkUI框架的拖拽手势和自定义组件能力来构建。以下是核心实现思路和关键代码示例:
1. 组件结构设计
使用Column或Stack布局,包含:
- 背景轨道(带缺口的图片或色块)
- 可拖动的滑块按钮
- 提示文本或图标
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())
}
}
}
关键点:
- 使用
@State管理滑块位置实现响应式更新 - 通过
PanGesture实现精确拖拽控制 - 验证阈值建议设为缺口宽度的1/3
- 可配合Canvas绘制自定义轨道样式
这种实现方式完全基于HarmonyOS原生能力,无需第三方库,性能优化良好且符合系统设计规范。

