【鸿蒙实战开发】模态转场、List 组件、AlphabetIndexer
一、模态转场起首,先来讲一讲什么是模态转场吧,简朴来讲就是我们在手机上面看到的分享图标点击以后出来的一个半屏的分享界面,这个过程就叫做模态转场。
概念:就是从页面内弹出一个半屏大概全屏的一个弹框。
1.1、半模态转场
作用:就是给一个半屏的模态转场。
语法结构:
.bindSheet(iSshow/是否表现半模态页面,builder/配置半模态页面内容)
1.2、表现状态双向绑定
在非双向绑定环境下,以拖拽方式关闭半模态页面不会改变isShow参数的值。
为了使isShow参数值与半模态界面的状态同步,发起使用$$双向绑定isShow参数。
https://img-blog.csdnimg.cn/img_convert/96b4070c427fc42ea1ddff2056c8f5b3.webp?x-oss-process=image/format,png
代码演示:
@Entry
@Component
struct zy {
@State isshow: boolean = false
@Builder
binBuilder() {
Column() {
Text('已打开')
.fontSize(50)
.fontColor(Color.Pink)
}
}
build() {
Column() {
Text('打开半模态框')
.fontSize(40)
//点击后打开半模态框
.onClick(() => {
this.isshow = true
})
.bindSheet($this.isshow, //双向绑定半模态页面
this.binBuilder()//模态框内的内容
)
}
.width('100%')
.height('100%')
}
}
图片演示:
https://img-blog.csdnimg.cn/img_convert/6a69f2b4fae855d4b7dae702496fbbf9.webp?x-oss-process=image/format,png
1.3、 可选属性sheetOptions
通过第三个可选参数SheetOptions,可以对半模态的内容举行调整
常用属性:
https://img-blog.csdnimg.cn/img_convert/0530a8c8268d0fa3550d3088965f75e1.webp?x-oss-process=image/format,png
代码演示:
@Entry
@Component
struct zy {
@State isshow: boolean = false
@Builder
binBuilder() {
Column() {
Text('已打开')
.fontSize(50)
.fontColor(Color.Pink)
//自定义的关闭模态框图标
Text('x')
.border({ width: 1, color: Color.Green })
.height(30)
.fontColor(Color.Gray)
.fontSize(20)
.position({ x: 210, y: 6 })
.width(30)
.textAlign(TextAlign.Center)
.borderRadius(15)
.onClick(() => {
this.isshow = false
})
}
}
build() {
Column() {
Text('打开半模态框')
.fontSize(40)//点击后打开半模态框
.onClick(() => {
this.isshow = true
})
.bindSheet($this.isshow, //双向绑定半模态页面
this.binBuilder(), //模态框内的内容
{
height: 400, //模态框高度
showClose: false, //关闭显示关闭图标,默认打开
// detents:,//半模态页面的切换高度档位。
dragBar: false//关闭控制条,默认显示
})
}
.width('100%')
.height('100%')
}
}
效果图:
https://img-blog.csdnimg.cn/img_convert/505e9f136f879df040dce75ad554a54e.webp?x-oss-process=image/format,png
案例-分享弹框
https://img-blog.csdnimg.cn/img_convert/56bb307ed38f2d6d130c375568841457.webp?x-oss-process=image/format,png
代码演示:
@Entry
@Component
struct zy {
@State isshow: boolean = false
//半模态框里面的内容
@Builder
bindBuilder() {
Column({ space: 20 }) {
Row() {
Text('分享给好友')
.fontColor('rgba(0,0,0,0.5)')
.fontWeight(800)
.fontSize(23)
.textAlign(TextAlign.Center)
.layoutWeight(1)
Image($r('app.media.ic_public_cancel'))
.width(30)
.onClick(() => {
this.isshow = false
})
}
.padding(10)
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
Row() {
Column({ space: 5 }) {
Image($r('app.media.ic_share_wechat'))
.width(50)
Text('微信')
}
Column({ space: 5 }) {
Image($r('app.media.ic_share_pyq'))
.width(50)
Text('朋友圈')
}
Column({ space: 5 }) {
Image($r('app.media.ic_share_sina'))
.width(50)
Text('微博')
}
Column({ space: 5 }) {
Image($r('app.media.ic_share_url'))
.width(50)
Text('复制链接')
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
}
.margin({ bottom: 50 })
}
build() {
Column() {
Button('转发')
.onClick(() => {
this.isshow = true
})
.bindSheet($this.isshow, this.bindBuilder(),
{
showClose: false, //关闭显示关闭图标
height: SheetSize.FIT_CONTENT//高度自适应
}
)
}
.width('100%')
.height('100%')
}
}
效果图:
https://img-blog.csdnimg.cn/img_convert/5a0f5b890f93a6c82851dd9299dcf98f.webp?x-oss-process=image/format,png
1.4、全屏模态
概念:顾名思义就是全屏的模态页面。
https://img-blog.csdnimg.cn/img_convert/c859a2bf0f5d887fe598277cd2ec3307.webp?x-oss-process=image/format,png
二、List组件
接着我们来讲一下今天List组件的小扩展,有些时候我们必要用List组件做一些相对有点复杂的效果,比如通讯录界面效果,那就必要ListItemGroup 分组容器和一些List组件的属性及事件来完成了。
2.1、分组展示
焦点用法:
[*]List作为顶级容器
[*]ListItemGroup 作为分组容器
[*]ListItem作为 List 大概ListItemGroup的子组件
https://img-blog.csdnimg.cn/img_convert/100331819993da84f7162512fc6a307a.webp?x-oss-process=image/format,png
ListItemGroup组件参数,以对象形式传入
ListItemGroup(参数){}.属性()
参数:
https://img-blog.csdnimg.cn/img_convert/7ff1a80d22dcd8d6d96a572a70a3e90e.webp?x-oss-process=image/format,png
属性:和List的属性是一样的
https://img-blog.csdnimg.cn/img_convert/d18ba5171da0799a3e3b2b275a3be2f0.webp?x-oss-process=image/format,png
代码演示:
@Entry
@Component
struct ListItemGroup_01 {
@Builder
headerBuilder() {
Text('我是头部')
}
@Builder
footerBuilder() {
Text('我是底部')
}
build() {
List() {
ListItemGroup({
header: this.headerBuilder(),
footer: this.footerBuilder(),
space: 20
}) {
ListItem() {
Text('我是内容')
.backgroundColor(Color.Orange)
}
ListItem() {
Text('我是内容')
.backgroundColor(Color.Orange)
}
}
.divider({ strokeWidth: 1, color: Color.Orange,startMargin:40 })
}
}
}
效果图:
https://img-blog.csdnimg.cn/img_convert/a16658219b77e9c1c3b328bbc039938e.webp?x-oss-process=image/format,png
小案例
https://img-blog.csdnimg.cn/img_convert/a2873c636150c0f42136f3e5f5f4a848.webp?x-oss-process=image/format,png
代码演示:
@Entry
@Component
struct ContactsList {
build() {
List() {
//头部参数A
ListItemGroup({ header: this.itemHead('A'), space: 20 }) {
// 循环渲染分组A的ListItem
this.contactBuilder('艾佳')
this.contactBuilder('安安')
this.contactBuilder('艾米丽')
}
//分割线
.divider({
startMargin: 60,
strokeWidth: 1,
color: '#ccc'
})
//头部参数B
ListItemGroup({ header: this.itemHead('B'), space: 20 }) {
// 循环渲染分组B的ListItem
this.contactBuilder('白客')
this.contactBuilder('白夜')
this.contactBuilder('博明')
}
.divider({
startMargin: 60,
strokeWidth: 1,
color: '#ccc'
})
}
}
@Builder
itemHead(text: string) {
// 列表分组的头部组件,对应联系人分组A、B等位置的组件
Text(text)
.fontSize(20)
.backgroundColor('#fff1f3f5')
.width('100%')
.padding(5)
}
@Builder
contactBuilder(name: string) {
//列表分组的内容组件
ListItem() {
Row({ space: 10 }) {
Image($r('app.media.ic_public_lianxiren'))
.width(40)
.fillColor('#e4b99a')
Text(name)
}
}
}
}
效果图片:
https://img-blog.csdnimg.cn/img_convert/e0bb1f58207c814254e4bf58586a8550.webp?x-oss-process=image/format,png
2.2、粘性标题
作用:
配合ListItemGroup组件使用,设置ListItemGroup中header和footer是否要吸顶或吸底。
https://img-blog.csdnimg.cn/img_convert/f04d600f10cbab18d0172a66762ea305.webp?x-oss-process=image/format,png
代码演示:
List(){
}
// .sticky(StickyStyle.None) // 不吸附 默认值
// .sticky(StickyStyle.Header) // 头部吸附
// .sticky(StickyStyle. Footer) //底部吸附,如果有的话
2.3、控制滚动
作用:如果列表很长,必要快速滚动到列表底部或返回列表顶部,就可以使用代码来控制滚动。
关键步骤:
[*]创建控制器(ListScroller)对象
[*]设置给 List 组件
[*]调用控制器对象的方法,实现滚动
代码演示:
// 1\. 创建控制器(ListScroller)对象
listScroller: ListScroller = new ListScroller()
// 2\. 设置给 List 组件
List({ space: 20, scroller: this.listScroller }) {
// ...
}
Button() {
// ...
}
.onClick(() => {
// 3\. 调用控制器对象的方法,实现滚动
this.listScroller.scrollToIndex(0)
})
参数:
https://img-blog.csdnimg.cn/img_convert/26e5309ec8dca7952d677f3ba775ca8e.webp?x-oss-process=image/format,png
2.4、事件
https://img-blog.csdnimg.cn/img_convert/704e074bca1750b2c37bee8ce01b1fbe.webp?x-oss-process=image/format,png
案例(通讯录)
需求1:数据渲染
数据2:设置随机头像颜色
需求3:头部粘性标题
需求4:通过控制滚动点击通讯录回到顶部
代码演示:
interface ContactContent {
initial: string
nameList: string[]
}
@Entry
@Component
struct ContactsList {
contacts: ContactContent[] = [
{ initial: 'A', nameList: ['阿猫', '阿狗', '阿虎', '阿龙', '阿鹰', '阿狼', '阿豹', '阿狮', '阿象', '阿鲸'] },
{ initial: 'B', nameList: ['白兔', '白鸽', '白鹤', '白鹭', '白狐', '白狼', '白虎', '白鹿', '白蛇', '白马'] },
{ initial: 'C', nameList: ['春花', '春风', '春雨', '春草', '春柳', '春燕', '春莺', '春蝶', '春蓝', '春绿'] },
{ initial: 'D', nameList: ['冬雪', '冬梅', '冬松', '冬竹', '冬云', '冬霜', '冬月', '冬夜', '冬青', '冬红'] },
{ initial: 'E', nameList: ['饿狼', '饿虎', '饿鹰', '饿豹', '饿熊', '饿蛇', '饿鱼', '饿虾', '饿蟹', '饿蚌'] },
{ initial: 'F', nameList: ['飞鸟', '飞鱼', '飞虫', '飞蜂', '飞蝶', '飞蛾', '飞蝉', '飞蝗', '飞鼠', '飞猫'] },
{ initial: 'G', nameList: ['孤狼', '孤鹰', '孤虎', '孤豹', '孤蛇', '孤鲨', '孤鲸', '孤鹿', '孤雁', '孤鸿'] },
{ initial: 'H', nameList: ['海鸥', '海龟', '海豚', '海星', '海马', '海葵', '海参', '海胆', '海螺', '海贝'] },
{ initial: 'I', nameList: ['火焰', '火球', '火箭', '火山', '火车', '火柴', '火把', '火鸟'] },
{ initial: 'J', nameList: ['金鱼', '金狮', '金刚', '金鹿', '金蛇', '金鹰', '金豹', '金虎', '金狐', '金猫'] },
{ initial: 'K', nameList: ['孔雀', '恐龙', '开心', '开怀', '开朗', '开拓', '开口', '开花', '开眼', '开天'] },
{ initial: 'L', nameList: ['老虎', '老鹰', '老鼠', '老狼', '老狗', '老猫', '老熊', '老鹿', '老龟', '老蛇'] },
{ initial: 'M', nameList: ['玫瑰', '牡丹', '梅花', '茉莉', '木兰', '棉花', '蜜蜂', '蚂蚁', '马蜂', '蟒蛇'] },
{ initial: 'N', nameList: ['南山', '南极', '南海', '南京', '南阳', '南风', '南瓜', '南竹', '南花', '南鸟'] },
{
initial: 'O',
nameList: ['熊猫', '欧鹭', '欧洲', '欧阳', '欧文', '欧若拉', '欧米茄', '欧罗巴', '欧菲莉亚', '欧瑞斯']
},
{ initial: 'P', nameList: ['苹果', '葡萄', '琵琶', '枇杷', '菩提', '瓢虫', '瓢泼', '飘零', '飘渺', '飘飘然'] },
{ initial: 'Q', nameList: ['七喜', '强风', '奇迹', '乾坤', '奇才', '晴天', '青竹', '秋水', '轻舞', '清泉'] },
{ initial: 'R', nameList: ['瑞雪', '瑞兽', '瑞光', '瑞云', '瑞彩', '瑞气', '瑞香', '瑞草', '瑞莲', '瑞竹'] },
{ initial: 'S', nameList: ['三羊', '三狗', '三猫', '三鱼', '三角', '三鹿', '三鹰', '三蛇', '三狐', '三豹'] },
{ initial: 'T', nameList: ['太阳', '天空', '田园', '太极', '太湖', '天鹅', '太空', '天使', '坦克', '甜橙'] },
{ initial: 'U', nameList: ['乌鸦', '乌鹊', '乌鱼', '乌龟', '乌云', '乌梅', '乌木', '乌金', '乌黑', '乌青'] },
{ initial: 'V', nameList: ['五虎', '五狼', '五鹰', '五豹', '五熊', '五蛇', '五鲨', '五鲸', '五鹿', '五马'] },
{ initial: 'W', nameList: ['悟空', '微笑', '温暖', '无畏', '温柔', '舞蹈', '问心', '悟道', '未来', '文学'] },
{ initial: 'X', nameList: ['西风', '西洋', '西子', '西施', '西岳', '西湖', '西柚', '西竹', '西花', '西鸟'] },
{ initial: 'Y', nameList: ['夜猫', '夜鹰', '夜莺', '夜空', '夜色', '夜月', '夜影', '夜翼', '夜狐', '夜狼'] },
{ initial: 'Z', nameList: ['珍珠', '紫薇', '紫霞', '紫竹', '紫云', '紫燕', '紫鸢', '紫藤', '紫荆', '紫罗兰'] },
]
//创建控制器(ListScroller)对象
ls: ListScroller = new ListScroller()
//随机颜色
getRandomColor(): ResourceColor {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgba(${r}, ${g}, ${b}, 0.5)`;
}
build() {
Column() {
Stack({ alignContent: Alignment.End }) {
Text('通讯录')
.width('100%')
.textAlign(TextAlign.Center)
.fontSize(20)
//调用控制器对象的方法,实现滚动
.onClick(() => {
this.ls.scrollToIndex(0, true, ScrollAlign.START)
})
Image($r('app.media.ic_public_add'))
.width(20)
}
.width('100%')
.padding(15)
.backgroundColor('#fff1f3f5')
//绑定List 组件
List({ scroller: this.ls }) {
// 顶部
ListItem() {
Row() {
Image($r('app.media.ic_public_search'))
.width(20)
.fillColor(Color.Gray)
Text('搜索')
.fontColor(Color.Gray)
}
.backgroundColor(Color.White)
.width('100%')
.height(40)
.borderRadius(5)
.justifyContent(FlexAlign.Center)
}
.padding(10)
.width('100%')
.backgroundColor('#fff1f3f5')
//循环渲染对象数组
ForEach(this.contacts, (item: ContactContent) => {
ListItemGroup({ header: this.itemHead(item.initial), space: 10 }) {
// 循环渲染分组A的ListItem
ForEach(item.nameList, (name: string) => {
this.contactBuilder(name, this.getRandomColor())
})
}
.divider({
startMargin: 60,
strokeWidth: 1,
color: '#ccc'
})
})
}
.sticky(StickyStyle.Header)//头部粘性标题
}
}
@Builder
itemHead(text: string) {
// 列表分组的头部组件,对应联系人分组A、B等位置的组件
Text(text)
.fontSize(20)
.backgroundColor('#fff1f3f5')
.width('100%')
.padding(5)
}
@Builder
contactBuilder(name: string, color: ResourceColor) {
ListItem() {
Row({ space: 10 }) {
Image($r('app.media.ic_public_lianxiren'))
.width(40)
.fillColor(color)
Text(name)
}
}
}
}
效果图:
https://img-blog.csdnimg.cn/img_convert/8166e61238438b9b70b28e362b04631a.webp?x-oss-process=image/format,png
三、AlphabetIndexer组件
作用:通过 AlphabetIndexer 组件可以与容器组件结合,实现导航联动,以及快速定位的效果。
3.1、焦点用法
AlphabetIndexer不是容器组件,属于功能类的组件,使用时,必要设置如下 2 个参数。
https://img-blog.csdnimg.cn/img_convert/f00781e0feeeefbe0ad346a9e16ebf69.webp?x-oss-process=image/format,png
通过双向绑定变量。可以实现修改变量值,同步更新选中的索引
代码演示:
@Entry
@Component
struct ContactsList {
@State selectedIndex:number = 0
alphabets: string[] = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
build() {
Stack({ alignContent: Alignment.End }) {
// 字母表索引组件
AlphabetIndexer({ arrayValue: this.alphabets, selected: $this.selectedIndex })
}
.width('100%')
.height('100%')
}
}
3.2、外观设置
设置文字外观
如果默认的颜色效果无法满意要求,可以通过如下属性来举行设置。
https://img-blog.csdnimg.cn/img_convert/f54d781e29511be9861c56c1782fb0a9.webp?x-oss-process=image/format,png
代码演示:
.color(Color.Orange)// 文字颜色
.selectedColor(Color.Green)// 选中文字颜色
.selectedBackgroundColor(Color.Black) // 选中背景颜色
弹窗提示
如果默认的文字高亮效果无法满意要求,还可以通过弹框来表现,对应属性如下:
https://img-blog.csdnimg.cn/img_convert/937dcd89499b237ea47515a6ee077950.webp?x-oss-process=image/format,png
.usingPopup(true)//使用弹窗
.popupColor(Color.Orange)// 弹窗文字颜色
.popupTitleBackground(Color.Pink)// 弹窗背景颜色
3.3、事件
代码演示:
@Entry
@Component
struct ContactsList {
@State selectedIndex: number = 0;
alphabets: string[] = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
build() {
Stack({ alignContent: Alignment.End }) {
Text(this.selectedIndex + '')
.width('100%')
// 字母表索引组件
AlphabetIndexer({ arrayValue: this.alphabets, selected: this.selectedIndex })
.usingPopup(true)
.onSelect((index: number) => {
this.selectedIndex = index
})
}
.width('100%')
.height('100%')
}
}
综合案例(通讯录)
结合AlphabetIndexer组件,让字母索引与通讯录索引联动
代码演示:
interface ContactContent {
initial: string
nameList: string[]
}
@Entry
@Component
struct ContactsList {
contacts: ContactContent[] = [
{ initial: 'A', nameList: ['阿猫', '阿狗', '阿虎', '阿龙', '阿鹰', '阿狼', '阿豹', '阿狮', '阿象', '阿鲸'] },
{ initial: 'B', nameList: ['白兔', '白鸽', '白鹤', '白鹭', '白狐', '白狼', '白虎', '白鹿', '白蛇', '白马'] },
{ initial: 'C', nameList: ['春花', '春风', '春雨', '春草', '春柳', '春燕', '春莺', '春蝶', '春蓝', '春绿'] },
{ initial: 'D', nameList: ['冬雪', '冬梅', '冬松', '冬竹', '冬云', '冬霜', '冬月', '冬夜', '冬青', '冬红'] },
{ initial: 'E', nameList: ['饿狼', '饿虎', '饿鹰', '饿豹', '饿熊', '饿蛇', '饿鱼', '饿虾', '饿蟹', '饿蚌'] },
{ initial: 'F', nameList: ['飞鸟', '飞鱼', '飞虫', '飞蜂', '飞蝶', '飞蛾', '飞蝉', '飞蝗', '飞鼠', '飞猫'] },
{ initial: 'G', nameList: ['孤狼', '孤鹰', '孤虎', '孤豹', '孤蛇', '孤鲨', '孤鲸', '孤鹿', '孤雁', '孤鸿'] },
{ initial: 'H', nameList: ['海鸥', '海龟', '海豚', '海星', '海马', '海葵', '海参', '海胆', '海螺', '海贝'] },
{ initial: 'I', nameList: ['火焰', '火球', '火箭', '火山', '火车', '火柴', '火把', '火鸟'] },
{ initial: 'J', nameList: ['金鱼', '金狮', '金刚', '金鹿', '金蛇', '金鹰', '金豹', '金虎', '金狐', '金猫'] },
{ initial: 'K', nameList: ['孔雀', '恐龙', '开心', '开怀', '开朗', '开拓', '开口', '开花', '开眼', '开天'] },
{ initial: 'L', nameList: ['老虎', '老鹰', '老鼠', '老狼', '老狗', '老猫', '老熊', '老鹿', '老龟', '老蛇'] },
{ initial: 'M', nameList: ['玫瑰', '牡丹', '梅花', '茉莉', '木兰', '棉花', '蜜蜂', '蚂蚁', '马蜂', '蟒蛇'] },
{ initial: 'N', nameList: ['南山', '南极', '南海', '南京', '南阳', '南风', '南瓜', '南竹', '南花', '南鸟'] },
{
initial: 'O',
nameList: ['熊猫', '欧鹭', '欧洲', '欧阳', '欧文', '欧若拉', '欧米茄', '欧罗巴', '欧菲莉亚', '欧瑞斯']
},
{ initial: 'P', nameList: ['苹果', '葡萄', '琵琶', '枇杷', '菩提', '瓢虫', '瓢泼', '飘零', '飘渺', '飘飘然'] },
{ initial: 'Q', nameList: ['七喜', '强风', '奇迹', '乾坤', '奇才', '晴天', '青竹', '秋水', '轻舞', '清泉'] },
{ initial: 'R', nameList: ['瑞雪', '瑞兽', '瑞光', '瑞云', '瑞彩', '瑞气', '瑞香', '瑞草', '瑞莲', '瑞竹'] },
{ initial: 'S', nameList: ['三羊', '三狗', '三猫', '三鱼', '三角', '三鹿', '三鹰', '三蛇', '三狐', '三豹'] },
{ initial: 'T', nameList: ['太阳', '天空', '田园', '太极', '太湖', '天鹅', '太空', '天使', '坦克', '甜橙'] },
{ initial: 'U', nameList: ['乌鸦', '乌鹊', '乌鱼', '乌龟', '乌云', '乌梅', '乌木', '乌金', '乌黑', '乌青'] },
{ initial: 'V', nameList: ['五虎', '五狼', '五鹰', '五豹', '五熊', '五蛇', '五鲨', '五鲸', '五鹿', '五马'] },
{ initial: 'W', nameList: ['悟空', '微笑', '温暖', '无畏', '温柔', '舞蹈', '问心', '悟道', '未来', '文学'] },
{ initial: 'X', nameList: ['西风', '西洋', '西子', '西施', '西岳', '西湖', '西柚', '西竹', '西花', '西鸟'] },
{ initial: 'Y', nameList: ['夜猫', '夜鹰', '夜莺', '夜空', '夜色', '夜月', '夜影', '夜翼', '夜狐', '夜狼'] },
{ initial: 'Z', nameList: ['珍珠', '紫薇', '紫霞', '紫竹', '紫云', '紫燕', '紫鸢', '紫藤', '紫荆', '紫罗兰'] },
]
//取0-255的随机数来通过rgba做随机颜色
colors() {
let r = Math.floor(Math.random() * 256)
let g = Math.floor(Math.random() * 256)
let b = Math.floor(Math.random() * 256)
return `rgba(${r},${g},${b},0.5)`
}
i: ListScroller = new ListScroller()
@State index1: number = 0
alphabets: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
build() {
Column() {
Stack({ alignContent: Alignment.End }) {
Text('通讯录')
.width('100%')
.textAlign(TextAlign.Center)
.fontSize(20)
Image($r('app.media.ic_public_add'))
.width(20)
}
.width('100%')
.padding(15)
.backgroundColor('#fff1f3f5')
// 顶部
Row() {
Image($r('app.media.ic_public_search'))
.width(20)
.fillColor(Color.Gray)
Text('搜索')
.fontColor(Color.Gray)
}
.backgroundColor(Color.White)
.width('100%')
.height(40)
.borderRadius(5)
.justifyContent(FlexAlign.Center)
Stack({ alignContent: Alignment.End }) {
List({ scroller: this.i }) {
ForEach(this.contacts, (item: ContactContent) => {
ListItemGroup({ header: this.itemHead(item.initial), space: 10 }) {
// 循环渲染分组A的ListItem
ForEach(item.nameList, (name: string) => {
this.contactBuilder(name, this.colors())
})
}
.divider({
startMargin: 60,
strokeWidth: 1,
color: '#ccc'
})
})
}
.sticky(StickyStyle.Header)
.onScrollIndex((index: number) => {
console.log(index.toString())
this.index1 = index
})
.scrollBar(BarState.Off)
AlphabetIndexer({ arrayValue: this.alphabets, selected: this.index1 })
.onSelect((index: number) => {
this.i.scrollToIndex(index)
})
.usingPopup(true)
.itemSize(22)
.popupColor(Color.Pink)
.popupPosition({ x: 20, y: 0 })
}
}
}
@Builder
itemHead(text: string) {
// 列表分组的头部组件,对应联系人分组A、B等位置的组件
Text(text)
.fontSize(20)
.backgroundColor('#fff1f3f5')
.width('100%')
.padding(5)
}
@Builder
contactBuilder(name: string, color: ResourceColor) {
ListItem() {
Row({ space: 10 }) {
Image($r('app.media.ic_public_lianxiren'))
.width(40)
.fillColor(color)
Text(name)
}
}
}
}
写在最后
●如果你觉得这篇内容对你还蛮有资助,我想邀请你帮我两个小忙:
●点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
●关注小编,同时可以等待后续文章ing
页:
[1]