简介
本项目是适配OpenHarmony环境的一款banner库,常用于广告图片轮播场景,基于Swiper进行封装,能力如下:
- 支持自动轮播。
- 支持无限轮播。
- 支持垂直轮播。
- 支持自定义指示器。
- 支持定制的翻页动画效果,目前动画只支持8种动效,无法做到不同动效叠加。
Swiper组件能力和Banner组件能力对比:
| 能力列表 | Swiper组件 | Banner组件 |
|---|
| 自动轮播 | 支持 | 支持 |
| 无限轮播 | 支持 | 支持 |
| 垂直轮播 | 支持 | 支持 |
| 自定义指示器 | 部分支持 | 支持 |
| 指示器和banner分离 | 不支持 | 支持 |
| 定制翻页动画效果 | 不支持 | 支持 |

ohpm install @ohos/banner
使用说明
1.提供了自定义轮播组件Banner以及自定义指示器CircleIndicator、PixelMapIndicator、RectFIndicator、RoundLinesIndicator组件。
2.以自定义轮播组件Banner和自定义指示器CircleIndicator举例:
import { Banner,BannerOptions,AnimatedEnum,IndicatorConfig, CircleIndicator,SwiperIndicator,IData,BannerMargin,AnimatedConfig } from '@ohos/banner'
export class Data implements IData{
str:string = '';
}
@Entry
@ComponentV2
struct BannerSamplePage {
private swiperController: SwiperController = new SwiperController()
private touTiaoSwiperController: SwiperController = new SwiperController()
@Local data: IData[] = []
@Local indicatorConfig: IndicatorConfig = new IndicatorConfig(10, 0, '#5CB85C', '#FFFFFF')
@Local bannerSize:number = 10;
@Local autoPlay?:boolean = true
@Local indicator?:SwiperIndicator = { bool:false }
@Local loop?:boolean = true
@Local vertical?:boolean = false
@Local interval?:number = 3000
@Local duration?:number = 800
@Local bannerMargin:BannerMargin = {left:40, right:40};
@Local animatedEnum?:AnimatedEnum = AnimatedEnum.MZScaleIn
animatedSelect:number | number[] = 0
animatedSupports:AnimatedEnum[] = [
AnimatedEnum.NonePage,
AnimatedEnum.AlphaPage,
AnimatedEnum.DepthPage,
AnimatedEnum.MZScaleIn ,
AnimatedEnum.RotateDownPage ,
AnimatedEnum.RotateUpPage,
AnimatedEnum.RotateY ,
AnimatedEnum.ScaleIn ,
AnimatedEnum.ZoomOutPage
]
animatedTypes:string[] = [
'NonePage',
'AlphaPage',
'DepthPage',
'MZScaleIn' ,
'RotateDownPage' ,
'RotateUpPage',
'RotateY' ,
'ScaleIn' ,
'ZoomOutPage'
]
@Local currentPos1:number = 0
@Local curve?:Curve = Curve.Linear
@Local bannerOptions:BannerOptions = {
swiperController: this.swiperController,
autoPlay:this.autoPlay, // 自定播放
interval:this.interval, // 当前item停滞时间
indicator:this.indicator, // 系统的指示器配置 不启用设置false
loop:this.loop, // 是否开启循环
duration:this.duration, // 子组件切换动画时长
vertical:this.vertical, // 是否纵向滑动
curve:Curve.Linear, // 动画曲率
bannerMargin: {left:this.bannerMargin.left, right:this.bannerMargin.right},
animatedEnum: AnimatedEnum.ZoomOutPage,// 动画效果
onChange: (index:number)=>{
console.log('dodo BannerConfigPage onChange 当前页面index='+index)
this.indicatorConfig.setCurrentPosition(index)
this.itemIndex = index;
},
onGestureSwipe:(index: number, extraInfo: SwiperAnimationEvent)=>{
console.log('dodo BannerConfigPage onGestureSwipe 当前页面index='+index + ' extraInfo='+JSON.stringify(extraInfo))
},
onAnimationStart:(index: number, targetIndex: number, extraInfo: SwiperAnimationEvent)=>{
console.log('dodo BannerConfigPage onAnimationStart 当前页面index='+index + ' targetIndex='+targetIndex + ' extraInfo='+JSON.stringify(extraInfo))
},
onAnimationEnd:(index: number, extraInfo: SwiperAnimationEvent)=>{
console.log('dodo BannerConfigPage onAnimationStart 当前页面index='+index + ' extraInfo='+JSON.stringify(extraInfo))
}
}
aboutToDisappear() {
}
@Local itemIndex: number = 0
aboutToAppear(): void {
this.createNewDataList();
}
createNewDataList(){
let list = new Array<IData>()
for (let i = 1; i <= this.bannerSize; i++) {
let data = new Data();
data.str = '数字'+i.toString()
list.push(data)
}
this.data = list
this.indicatorConfig.setIndicatorSize(this.data.length)
}
createNewBannerConfig(){
this.bannerOptions = {
swiperController: this.swiperController,
autoPlay:this.autoPlay, // 自定播放
interval:this.interval, // 当前item停滞时间
indicator:this.indicator, // 系统的指示器配置 不启用设置false
loop:this.loop, // 是否开启循环
duration:this.duration, // 子组件切换动画时长
vertical:this.vertical, // 是否纵向滑动
curve:Curve.Linear, // 动画曲率
bannerMargin: {left:this.bannerMargin.left, right:this.bannerMargin.right},
animatedEnum: this.animatedSupports[this.animatedSelect as number],// 动画效果
onChange: (index:number)=>{
console.log('dodo BannerConfigPage onChange 当前页面index='+index)
this.indicatorConfig.setCurrentPosition(index)
this.itemIndex = index;
},
onGestureSwipe:(index: number, extraInfo: SwiperAnimationEvent)=>{
console.log('dodo BannerConfigPage onGestureSwipe 当前页面index='+index + ' extraInfo='+JSON.stringify(extraInfo))
},
onAnimationStart:(index: number, targetIndex: number, extraInfo: SwiperAnimationEvent)=>{
console.log('dodo BannerConfigPage onAnimationStart 当前页面index='+index + ' targetIndex='+targetIndex + ' extraInfo='+JSON.stringify(extraInfo))
},
onAnimationEnd:(index: number, extraInfo: SwiperAnimationEvent)=>{
console.log('dodo BannerConfigPage onAnimationStart 当前页面index='+index + ' extraInfo='+JSON.stringify(extraInfo))
}
}
}
BACKGROUND_COLORS = [Color.Red, Color.Orange, Color.Pink, Color.Grey]
IMAGE_RESOURCES = [$r('app.media.jpg1'),$r('app.media.jpg2'),$r('app.media.png3'),$r('app.media.webp5')]
@Builder
bannerContent(data:IData[]|Record<string,Object>[], index:number) {
Stack({ alignContent: Alignment.Center }){
Image(this.IMAGE_RESOURCES[index % this.IMAGE_RESOURCES.length])
.objectFit(ImageFit.Fill)
.width('100%')
.height('100%')
Flex({direction:FlexDirection.Row,justifyContent:FlexAlign.Start, alignItems:ItemAlign.Center}){
Text(`这是第${index}个页面,用户数据为:${(data[index] as Record<string,Object>)['str']}`).fontColor(Color.White)
}
.position({x:0,y:200})
.height(40).width('100%')
.backgroundColor('#44000000')
}
.width('100%')
.height(240)
}
build() {
Scroll(){
Column() {
Text('缩放渐变动效展示+指示器与banner分离').margin({top:20,bottom:20})
Stack() {
Banner({
bannerOptions: this.bannerOptions,
currentPosition: $currentPos1,
data: this.data,
bannerContent: (item, index) => {
this.bannerContent(item, index)
}
}).width('100%')
.height(240)
Flex({direction:FlexDirection.RowReverse,justifyContent:FlexAlign.Start, alignItems:ItemAlign.Center}){
}
.width('100%')
.height(40)
.position({x:0,y:200})
}.width('100%')
.height(240)
Flex({direction:FlexDirection.RowReverse,justifyContent:FlexAlign.Start, alignItems:ItemAlign.Center}){
Text(`${(this.itemIndex+1)}/${this.data.length}`).fontColor(Color.White).margin({left:20,right:40})
CircleIndicator({ indicatorConfig: this.indicatorConfig })
}
.width('100%')
.height(40)
.backgroundColor(Color.Gray)
}.width('100%')
} .width('100%')
.height('100%')
}
DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案)
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......
接口说明
Banner 轮播自定义组件
| 方法名 | 入参 | 接口描述 |
|---|
| Banner({bannerOptions: bannerOptions,data:data,bannerContent: (item, index) => {this.bannerContent(item, index)}} | | 自定义轮播组件Banner构造器 |
CircleIndicator 指示器自定义组件
| 方法名 | 入参 | 接口描述 |
|---|
| CircleIndicator({ indicatorConfig: $indicatorConfig }) | indicatorConfig:IndicatorConfig | 圆角指示器构造器 |
PixelMapIndicator 指示器自定义组件
| 方法名 | 入参 | 接口描述 |
|---|
| PixelMapIndicator({ indicatorConfig: $indicatorConfig }) | indicatorConfig:IndicatorConfig | 图像指示器构造器 |
RectFIndicator 指示器自定义组件
| 方法名 | 入参 | 接口描述 |
|---|
| RectFIndicator({ indicatorConfig: $indicatorConfig }) | indicatorConfig:IndicatorConfig | 矩形指示器构造器 |
RoundLinesIndicator 指示器自定义组件
| 方法名 | 入参 | 接口描述 |
|---|
| RoundLinesIndicator({ indicatorConfig: $indicatorConfig }) | indicatorConfig:IndicatorConfig | 圆角线条指示器构造器 |
IndicatorConfig自定义组件配置
| 使用方法 | 入参 | 接口描述 |
|---|
| getNormalPixelMap() | | 获取普通图像指示器未选中图像 |
| setNormalPixelMap(normal) | normal:PixelMap | 设置普通图像指示器未选中图像 |
| getSelectPixelMap() | | 获取普通图像指示器选中图像 |
| setSelectPixelMap(select) | select:PixelMap | 设置普通图像指示器选中图像 |
| getHeight() | | 获取指示器的高度 |
| setHeight(height) | height: number | 设置指示器的高度 |
| getRadius() | | 获取指示器的圆角 |
| setRadius(radius) | radius: number | 设置指示器的圆角 |
| getSelectedWidth() | | 获取指示器选中宽度 |
| setSelectedWidth(selectedWidth) | selectedWidth: number | 设置指示器选中宽度 |
| getNormalWidth() | | 获取指示器未选中宽度 |
| setNormalWidth(normalWidth) | normalWidth: number | 设置指示器未选中宽度 |
| getCurrentPosition() | | 获取指示器当前位置 |
| setCurrentPosition(currentPosition: number) | currentPosition: number | 设置指示器当前位置 |
| getIndicatorSpace() | | 获取指示器间距 |
| setIndicatorSpace(indicatorSpace: number) | indicatorSpace: number | 设置指示器间距 |
| getSelectedColor() | | 获取指示器选中颜色 |
| setSelectedColor(selectedColor: string) | selectedColor: string | 设置指示器选中颜色 |
| getNormalColor() | | 获取指示器未选中颜色 |
| setNormalColor(normalColor: string) | normalColor: string | 设置指示器未选中颜色 |
| getIndicatorSize() | | 获取指示器总数 |
| setIndicatorSize(indicatorSize: number) | indicatorSize: number | 设置指示器总数 |
AnimatedEnum动画类型支持
| 动画类型 | 展示动画类型描述 |
|---|
| AnimatedEnum.NonePage | 无动画效果 |
| AnimatedEnum.AlphaPage | alpha渐变 |
| AnimatedEnum.DepthPage | 叠层 |
| AnimatedEnum.MZScaleIn | 魅族效果 通常配合画廊 |
| AnimatedEnum.RotateDownPage | 圆形旋转翻页 中心点在下方 |
| AnimatedEnum.RotateUpPage | 圆形旋转翻页 中心点在上方 |
| AnimatedEnum.RotateY | 3D旋转翻页 旋转轴Y |
| AnimatedEnum.ScaleIn | 缩放进入 |
| AnimatedEnum.ZoomOutPage | 缩放alpha进入 |
BannerOptions Banner配置参数
export class BannerOptions{
swiperController:SwiperController = new SwiperController();
autoPlay?:boolean = false
interval?:number = 3000
indicator?:SwiperIndicator = { bool: false}
loop?:boolean = true
duration?:number = 400
vertical?:boolean = false
curve?:Curve = Curve.Linear
disableSwipe?:boolean = false;
bannerMargin?:BannerMargin = {left:0, right:0};
animatedEnum?:AnimatedEnum = AnimatedEnum.NonePage
animatedConfig?:AnimatedConfig = {}
onChange?: (index:number)=>void = undefined;
onGestureSwipe?:(index: number, extraInfo:SwiperAnimationEvent)=>void = undefined
onAnimationStart?:(index: number, targetIndex: number, extraInfo:SwiperAnimationEvent)=>void = undefined
onAnimationEnd?:(index: number, extraInfo:SwiperAnimationEvent)=>void = undefined
}
约束与限制
在下述版本验证通过:
DevEco Studio NEXT Developer Beta3: (5.0.3.530), SDK: API12 (5.0.0.35(SP3))
目录结构
|
| |
|
|
|
|
|
| |
| |
| |
|
|
|
|
|
|
|
|
|
|
|
| |
| |
| |