目录
1、Swiper轮播组件
1.1 Swiper基本用法
1.2 Swiper的常见属性
1.3 Swiper的样式自定义
1.3.1 基本语法
1.3.2 案例小米有品
2、样式&结构重用
2.1 @Extend:扩展组件(样式、事件)
2.2 @Styles:抽取通用属性、事件
2.3 @Builder:自定义构建函数(结构、样式、事件)
3、滚动容器Scroll
3.1 Scroll 的核心用法
3.2 Scroll 的常见属性
3.3 Scroll 的控制器
3.4 Scroll 的事件
3.5 案例:京东案例实战
4、容器组件Tabs
4.1 Tabs 基本用法
4.2 Tabs 常用属性
4.3 滚动导航栏
4.4 自定义TabBar
4.4.1 基础结构
4.4.2 高亮切换
4.5 案例:小米有品底部Tabs
前言:组件化开发-样式结构重用&常见组件
1、Swiper轮播组件
1.1 Swiper基本用法
import window from '@ohos.window';
@Entry
@Component
struct Index {
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column(){
Swiper(){
Text('1')
.backgroundColor(Color.Yellow)
Text('2')
.backgroundColor(Color.Orange)
Text('3')
.backgroundColor(Color.Brown)
}
.width('100%').height(100)
.margin({bottom: 5})
Swiper(){
Image($r('app.media.ic_swiper_xmyp01'))
Image($r('app.media.ic_swiper_xmyp02'))
Image($r('app.media.ic_swiper_xmyp03'))
Image($r('app.media.ic_swiper_xmyp04'))
}
.width('100%').height(150)
}
}
}
1.2 Swiper的常见属性
import window from '@ohos.window';
@Entry
@Component
struct Index {
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column(){
Swiper(){
Image($r('app.media.ic_swiper_xmyp01'))
Image($r('app.media.ic_swiper_xmyp02'))
Image($r('app.media.ic_swiper_xmyp03'))
Image($r('app.media.ic_swiper_xmyp04'))
}
.loop(false) //是否开启循环 默认true,flase无法左滑到末页
.autoPlay(true) // 自动播放 默认是false自动播放
.invert(4000) // 播放间隔 默认3000
.vertical(false) //纵向滑动轮播默认flase,true就是纵向
.width('100%').height(150)
}
}
}
1.3 Swiper的样式自定义
1.3.1 基本语法
import window from '@ohos.window';
import { InterstitialDialogAction } from '@ohos.atomicservice.InterstitialDialogAction';
@Entry
@Component
struct Index {
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column(){
Swiper(){
Text('1')
.backgroundColor(Color.Yellow)
Text('2')
.backgroundColor(Color.Orange)
Text('3')
.backgroundColor(Color.Brown)
}
.width('100%').height(200)
.margin({bottom: 5})
// .indicator(true) //定制小圆点。默认false
.indicator(
Indicator.dot()
.itemWidth(20)
.itemHeight(20)
.color(Color.Black)
.selectedItemWidth(25)
.selectedItemHeight(25)
.selectedColor(Color.White)
)
Swiper(){
Image($r('app.media.ic_swiper_xmyp01'))
Image($r('app.media.ic_swiper_xmyp02'))
Image($r('app.media.ic_swiper_xmyp03'))
Image($r('app.media.ic_swiper_xmyp04'))
}
.loop(false) //是否开启循环 默认true,flase无法左滑到末页
.autoPlay(true) // 自动播放 默认是false自动播放
.invert(4000) // 播放间隔 默认3000
.vertical(false) //纵向滑动轮播默认flase,true就是纵向
.width('100%').height(150)
}
}
}
1.3.2 案例小米有品
import window from '@ohos.window';
import { InterstitialDialogAction } from '@ohos.atomicservice.InterstitialDialogAction';
@Entry
@Component
struct Index {
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column(){
Swiper(){
Image($r('app.media.ic_swiper_xmyp01'))
Image($r('app.media.ic_swiper_xmyp02'))
Image($r('app.media.ic_swiper_xmyp03'))
Image($r('app.media.ic_swiper_xmyp04'))
}
.width('100%').aspectRatio(2.4) // 宽高比
.autoPlay(true) // 自动播放 默认是false自动播放
.invert(4000) // 播放间隔 默认3000
.indicator(
Indicator.dot()
.itemWidth(10)
.selectedItemWidth(30)
.selectedColor(Color.Black)
)
}
}
}
2、样式&结构重用
2.1 @Extend:扩展组件(样式、事件)
import window from '@ohos.window';
@Extend(Text)
function textFn(){
.fontSize(20)
.fontWeight(FontWeight.Bold)
}
@Extend(Text)
function bannerExtend(bgColor: ResourceColor, msg: string){
.textAlign(TextAlign.Center)
.backgroundColor(bgColor)
.fontColor(Color.White)
.fontSize(30)
.onClick(() => {
AlertDialog.show({
message: msg
})
})
}
@Entry
@Component
struct Index {
@State message: string = '@Extend-扩展组件(样式,事件)';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column() {
Text(this.message)
.textFn()
Swiper() {
Text('1')
.bannerExtend(Color.Orange, '轮播图1号')
Text('2')
.bannerExtend(Color.Brown, '轮播图2号')
Text('3')
.bannerExtend(Color.Green, '轮播图3号')
}
.width('100%')
.height(160)
}
.width('100%')
.height('100%')
}
}
2.2 @Styles:抽取通用属性、事件
下图有Text、Button、Column是无法使用Extend实现,那么需要学习Styles,Styles可以全局定义、可以在组件里面定义,但是不支持传参
import window from '@ohos.window';
// 1 全局定义
@Styles function commonStyles (){
.width(100)
.height(100)
}
@Entry
@Component
struct Index {
@State message: string = '@styles';
@State bgColor: ResourceColor = Color.Gray
// 2、 组件内定义
@Styles SetBg (){
.backgroundColor(this.bgColor)
.onClick(() => {
this.bgColor = Color.Orange
})
}
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column({ space: 10 }) {
Text(this.message)
.fontColor(Color.White)
.commonStyles()
.SetBg()
Column() {}
.commonStyles()
.SetBg()
Button('按钮')
.commonStyles()
.SetBg()
Button('重置')
.commonStyles()
.onClick( () => {
this.bgColor = Color.Gray
})
}
.width('100%')
.height('100%')
}
}
2.3 @Builder:自定义构建函数(结构、样式、事件)
注意全局与局部区别(this.xxx)
import window from '@ohos.window';
// 1 全局定义
@Builder
function navItem (icon: ResourceStr, txt: string){
Column({ space: 10 }) {
Image(icon)
.width('80%')
Text(txt)
}
.width('25%')
.onClick(() => {
AlertDialog.show({
message: `点了 ${txt}`
})
})
}
@Entry
@Component
struct Index {
@State message: string = '@Builder';
// 2 局部定义
@Builder
navItem (icon: ResourceStr, txt: string){
Column({ space: 10 }) {
Image(icon)
.width('80%')
Text(txt)
}
.width('25%')
.onClick(() => {
AlertDialog.show({
message: `点了 ${txt}`+ this.message
})
})
}
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column({ space: 20 }) {
Text(this.message)
.fontSize(30)
Row() {
Row() {
navItem($r('app.media.ic_reuse_01'), '阿里拍卖')
navItem($r('app.media.ic_reuse_02'), '菜鸟')
this.navItem($r('app.media.ic_reuse_03'), '芭芭农场')
this.navItem($r('app.media.ic_reuse_04'), '医药')
}
}
}
.width('100%')
.height('100%')
}
}
3、滚动容器Scroll
3.1 Scroll 的核心用法
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column() {
// 如果需要滚动,外层
Scroll(){
Column({ space: 10 }) {
ForEach(Array.from({ length: 10 }), (item: string, index) => {
Text('测试文本' + (index + 1))
.width('100%')
.height(100)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.fontSize(20)
.fontColor(Color.White)
.borderRadius(10)
})
}
.padding(10)
.width('100%')
}
.width('100%').height(400)
.scrollable(ScrollDirection.Vertical) // .scrollable(ScrollDirection.Horizontal) //横向
}
}
}
3.2 Scroll 的常见属性
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Column() {
// 如果希望内容溢出, 能够滚动
Scroll() {
Column({ space: 10 }) {
ForEach(Array.from({ length: 10 }), (item: string, index) => {
Text('测试文本' + (index + 1))
.width('100%')
.height(100)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.fontSize(20)
.fontColor(Color.White)
.borderRadius(10)
})
}
.padding(10)
.width('100%')
}
.width('100%')
.height(400)
.scrollable(ScrollDirection.Vertical) // 设置滚动方向
.scrollBar(BarState.Auto) // On一直显示 Off一直隐藏 Auto滑动显示
.scrollBarColor(Color.Blue) // 滚动条颜色
.scrollBarWidth(5) // 滚动条宽度
.edgeEffect(EdgeEffect.Spring) // 滑动效果
}
}
}
3.3 Scroll 的控制器
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
// 1. 创建 Scroller 对象 (实例化)
myScroll: Scroller = new Scroller()
build() {
Column() {
// 如果希望内容溢出, 能够滚动
// 2. 绑定给 Scroll 组件
Scroll(this.myScroll) {
Column({ space: 10 }) {
ForEach(Array.from({ length: 10 }), (item: string, index) => {
Text('测试文本' + (index + 1))
.width('100%')
.height(100)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.fontSize(20)
.fontColor(Color.White)
.borderRadius(10)
})
}
.padding(10)
.width('100%')
}
.width('100%')
.height(400)
.scrollable(ScrollDirection.Vertical) // 设置滚动方向
.scrollBar(BarState.Auto) // On一直显示 Off一直隐藏 Auto滑动显示
.scrollBarColor(Color.Blue) // 滚动条颜色
.scrollBarWidth(5) // 滚动条宽度
.edgeEffect(EdgeEffect.Spring) // 滑动效果
Button('控制滚动条位置').margin(20)
.onClick(() => {
this.myScroll.scrollEdge(Edge.End)
})
Button('获取已经滚动的距离')
.onClick(() => {
const x = this.myScroll.currentOffset().xOffset
const y = this.myScroll.currentOffset().yOffset
AlertDialog.show({
message: `x: ${x} y: ${y}`
})
})
}
}
}
3.4 Scroll 的事件
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
// 1. 创建 Scroller 对象 (实例化)
myScroll: Scroller = new Scroller()
build() {
Column() {
// 如果希望内容溢出, 能够滚动
// 2. 绑定给 Scroll 组件
Scroll(this.myScroll) {
Column({ space: 10 }) {
ForEach(Array.from({ length: 10 }), (item: string, index) => {
Text('测试文本' + (index + 1))
.width('100%')
.height(100)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.fontSize(20)
.fontColor(Color.White)
.borderRadius(10)
})
}
.padding(10)
.width('100%')
}
.width('100%')
.height(400)
.scrollable(ScrollDirection.Vertical) // 设置滚动方向
.scrollBar(BarState.Auto) // On一直显示 Off一直隐藏 Auto滑动显示
.scrollBarColor(Color.Blue) // 滚动条颜色
.scrollBarWidth(5) // 滚动条宽度
.edgeEffect(EdgeEffect.Spring) // 滑动效果
.onScroll((x, y) => {
console.log('已经滑动的距离:', this.myScroll.currentOffset().yOffset)
})
Button('控制滚动条位置').margin(20)
.onClick(() => {
this.myScroll.scrollEdge(Edge.End)
})
Button('获取已经滚动的距离')
.onClick(() => {
const y = this.myScroll.currentOffset().yOffset
AlertDialog.show({
message: `y: ${y}`
})
})
}
}
}
3.5 案例:京东案例实战
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
// 1、 创建scroll实例对象
myScroll: Scroller = new Scroller()
@State yOffset: number = 0
build() {
Column() {
Stack({ alignContent: Alignment.BottomEnd }) {
// 顶部滚动区域
// 2 和Scroll容器绑定
Scroll(this.myScroll) {
Column() {
Image($r('app.media.ic_jd_scroll_01'))
Image($r('app.media.ic_jd_scroll_02'))
Image($r('app.media.ic_jd_scroll_03'))
}
}
.scrollBar(BarState.Off)
.width('100%')
.backgroundColor(Color.Orange)
.onScroll( () => {
this.yOffset = this.myScroll.currentOffset().yOffset
})
// 有时显示 有时隐藏-》条件渲染
if( this.yOffset > 400){ Image($r('app.media.ic_jd_rocket'))
.width(40)
.backgroundColor(Color.White)
.borderRadius(20)
.padding(5)// .margin({right:20,bottom:20})
.offset({ x: -20, y: -20 })
// 3 添加事件
.onClick( () => {
this.myScroll.scrollEdge(Edge.Top)
})
}
}
.layoutWeight(1)
// 底部 tabbar 图片(后面会学)
Image($r('app.media.ic_jd_tab'))
.width('100%')
}
}
}
4、容器组件Tabs
4.1 Tabs 基本用法
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Tabs(){
TabContent(){
Text('首页内容') // 只能有一个子组件
}
.tabBar('首页')
TabContent(){
Text('推荐内容')
}
.tabBar('推荐')
TabContent(){
Text('发现内容')
}
.tabBar('发现')
TabContent(){
Text('我的')
}
.tabBar('我的')
}
}
}
4.2 Tabs 常用属性
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
build() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Text('首页内容') // 有且只能一个子组件
}
.tabBar('首页') // 配置导航
TabContent() {
Text('推荐内容') // 有且只能一个子组件
}
.tabBar('推荐')
TabContent() {
Text('发现内容') // 有且只能一个子组件
}
.tabBar('发现')
TabContent() {
Text('我的内容') // 有且只能一个子组件
}
.tabBar('我的')
}
.vertical(false) // 调整导航水平或垂直
.scrollable(false) // 是否开启手势滑动
.animationDuration(0) // 点击滑动的动画时间
}
}
4.3 滚动导航栏
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
titles: string[] = [
'首页','关注','热门','军事','体育',
'八卦','数码','财经','美食','旅行'
]
build() {
// 生成10个面板 → 10个小导航
Tabs() {
ForEach(this.titles, (item: string, index) => {
TabContent() {
Text(`${item}内容`)
}
.tabBar(item)
})
}
// barMode属性, 可以实现滚动导航栏
.barMode(BarMode.Scrollable)
}
}
4.4 自定义TabBar
4.4.1 基础结构
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
@Builder
myBuilder (title: string, img: ResourceStr) {
Column() {
Image(img)
.width(30)
Text(title)
}
}
build() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Text('购物车内容')
}
.tabBar(this.myBuilder('购物车', $r('app.media.ic_tabbar_icon_2')))
TabContent() {
Text('我的内容')
}
.tabBar(this.myBuilder('我的', $r('app.media.ic_tabbar_icon_3')))
}
}
}
4.4.2 高亮切换
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
// 准备状态, 存储激活的索引
@State selectedIndex: number = 0
@Builder
myBuilder (itemIndex: number, title: string, img: ResourceStr, selImg: ResourceStr) {
// 如果激活的是自己, 图片/文本 都需要调整样式 → 需要区分不同的 tabBar
Column() {
Image(itemIndex == this.selectedIndex ? selImg : img)
.width(30)
Text(title)
.fontColor(itemIndex == this.selectedIndex ? Color.Red : Color.Black)
}
}
build() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Text('购物车内容')
}
.tabBar(this.myBuilder(0, '购物车', $r('app.media.ic_tabbar_icon_2'), $r('app.media.ic_tabbar_icon_2_selected')))
TabContent() {
Text('我的内容')
}
.tabBar(this.myBuilder(1, '我的', $r('app.media.ic_tabbar_icon_3'), $r('app.media.ic_tabbar_icon_3_selected')))
}
.onChange((index: number) => {
// console.log('激活的索引', index)
this.selectedIndex = index
})
.animationDuration(0)
.scrollable(false)
}
}
4.5 案例:小米有品底部Tabs
import window from '@ohos.window';
@Entry
@Component
struct Index {
@State message: string = '@春天的菠菜';
onPageShow(): void {
window.getLastWindow(AppStorage.get("context"), (err, data) => {
if (err.code) {
console.error('Failed to get last window. Cause:' + JSON.stringify(err));
return;
}
data.setFullScreen(true)
});
}
// 准备状态, 存储激活的索引
@State selectedIndex: number = 0
@Builder
myBuilder (itemIndex: number, title: string, img: ResourceStr, selImg: ResourceStr) {
// 如果激活的是自己, 图片/文本 都需要调整样式 → 需要区分不同的 tabBar
Column() {
Image(itemIndex == this.selectedIndex ? selImg : img)
.width(30)
Text(title)
.fontColor(itemIndex == this.selectedIndex ? Color.Red : Color.Black)
}
}
@Builder
centerBuilder () {
Image($r('app.media.ic_reuse_02'))
.width(40)
.margin({ bottom: 10 })
}
build() {
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
Text('首页内容')
}
.tabBar(this.myBuilder(0, '首页', $r('app.media.ic_tabbar_icon_0'), $r('app.media.ic_tabbar_icon_0_selected')))
TabContent() {
Text('分类内容')
}
.tabBar(this.myBuilder(1, '分类', $r('app.media.ic_tabbar_icon_1'), $r('app.media.ic_tabbar_icon_1_selected')))
// 特殊形状的Tab
TabContent() {
Text('活动内容')
}
.tabBar(this.centerBuilder())
TabContent() {
Text('购物车内容')
}
.tabBar(this.myBuilder(3, '购物车', $r('app.media.ic_tabbar_icon_2'), $r('app.media.ic_tabbar_icon_2_selected')))
TabContent() {
Text('我的内容')
}
.tabBar(this.myBuilder(4, '我的', $r('app.media.ic_tabbar_icon_3'), $r('app.media.ic_tabbar_icon_3_selected')))
}
.onChange((index: number) => {
// console.log('激活的索引', index)
this.selectedIndex = index
})
.animationDuration(0)
.scrollable(false)
}
}