轻松学会如何用List实现左右两边一起滑动
在手机应用当中我们经常看到这样的界面:
这样的界面通常是一起滑动的,比如说左边的List列表滑到了B,那么右边的字母表B也会高亮,点击字母表的字母右边的列表也会跳转到相应的位置。
下面是具体步骤
1.静态布局
我们需要用到List组件、Stack组件和AlphabetIndexer功能组件
List用来实现左边列表、AlphabetIndexer实现右边字母表、Stack把他们放在一起
代码:
hotCitys: string[] =
['北京', '上海', '广州', '深圳', '天津', '杭州', '南京', '苏州', '成都', '武汉', '重庆', '西安', '香港', '澳门',
'台北']
historyCitys: string[] = ['北京', '上海', '广州', '深圳', '重庆']
cityContentList: BKCityContent[] = [
{
initial: 'A',
cityNameList: ['阿拉善', '鞍山', '安庆', '安阳', '阿坝', '安顺']
},
{
initial: 'B',
cityNameList: ['北京', '保定', '包头', '巴彦淖尔', '本溪', '白山']
},
{
initial: 'C',
cityNameList: ['成都', '重庆', '长春', '长沙', '承德', '沧州']
},
{
initial: 'D',
cityNameList: ['大连', '东莞', '大同', '丹东', '大庆', '大兴安岭']
},
{
initial: 'E',
cityNameList: ['鄂尔多斯', '鄂州', '恩施', '额尔古纳市', '二连浩特市', '恩施市']
},
{
initial: 'F',
cityNameList: ['福州', '佛山', '抚顺', '阜新', '阜阳', '抚州']
},
{
initial: 'G',
cityNameList: ['广州', '贵阳', '赣州', '桂林', '贵港', '广元']
},
{
initial: 'H',
cityNameList: ['杭州', '海口', '哈尔滨', '合肥', '呼和浩特', '邯郸']
},
{
initial: 'J',
cityNameList: ['济南', '晋城', '晋中', '锦州', '吉林', '鸡西']
},
{
initial: 'K',
cityNameList: ['昆明', '开封', '康定市', '昆山', '康保县', '宽城满族自治县']
},
{
initial: 'L',
cityNameList: ['兰州', '廊坊', '临汾', '吕梁', '辽阳', '辽源']
},
{
initial: 'M',
cityNameList: ['牡丹江', '马鞍山', '茂名', '梅州', '绵阳', '眉山']
},
{
initial: 'N',
cityNameList: ['南京', '宁波', '南昌', '南宁', '南通', '南平']
},
{
initial: 'P',
cityNameList: ['盘锦', '莆田', '萍乡', '平顶山', '濮阳', '攀枝花']
},
{
initial: 'Q',
cityNameList: ['青岛', '秦皇岛', '齐齐哈尔', '七台河', '衢州', '泉州']
},
{
initial: 'R',
cityNameList: ['日照', '日喀则', '饶阳县', '任丘市', '任泽区', '饶河县']
},
{
initial: 'S',
cityNameList: ['上海', '苏州', '深圳', '沈阳', '石家庄', '朔州']
},
{
initial: 'T',
cityNameList: ['天津', '太原', '唐山', '通辽', '铁岭', '通化']
},
{
initial: 'W',
cityNameList: ['无锡', '武汉', '乌海', '乌兰察布', '温州', '芜湖']
},
{
initial: 'X',
cityNameList: ['厦门', '西安', '西宁', '邢台', '忻州', '兴安盟']
},
{
initial: 'Y',
cityNameList: ['扬州', '阳泉', '运城', '营口', '延边', '伊春']
},
{
initial: 'Z',
cityNameList: ['郑州', '珠海', '张家口', '镇江', '舟山', '漳州']
}
]
alphabets: string[] =
['#', '热', "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "W", "X", "Y",
"Z"]
//自定义的字体组件
@Builder
myCity(item: string) {
Text(item)
.width("33%")
.textAlign(TextAlign.Center)
.padding(15)
}
//Stack布局,所有内容都在Stack里
Stack({ alignContent: Alignment.End }) {
// 1城市
List({ scroller: this.scroller }) {
ListItemGroup({ header: this.header("历史"), space: 10 }) {
ListItem() {
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.historyCitys, (item: string) => {
this.myCity(item)
})
}
}
}
// 热门城市
ListItemGroup({ header: this.header("热门") }) {
ListItem() {
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.hotCitys, (item: string) => {
this.myCity(item)
})
}
}
}
ForEach(this.cityContentList, (item1: BKCityContent) => {
ListItemGroup({ header: this.header(item1.initial) }) {
ForEach(item1.cityNameList, (item2: string) => {
ListItem() {
this.myCity(item2)
}
})
}
})
}
.divider({ strokeWidth: 1, startMargin: 20, color: Color.Pink })
.width("100%")
// 2字母表
AlphabetIndexer({ arrayValue: this.alphabets, selected: this.currentSelect })
//设置外观
.itemSize(30)
.selectedFont({ size: 20 })
.font({ size: 20 })
}
最后的效果:
2.数据渲染、
先创建一个控制器
设置给List
1、scroller:ListScroller=new ListScroller()
2、List(this.scroller)
我们通过onScrollIndex获取当前ListItemGroup的索引
.onScrollIndex((start: number) => {
//this.currentSelect是创建字母表时定义的响应变量
this.currentSelect = start
})
//这样左右两边的索引就同步了,也就是右边跟随左边滑动高亮
要实现点击跳转需要用到AlphabetIndexer的onSelect事件,以及调用控制器方法
.onSelect((index: number) => {
index 为点击字母索引,这里currSelect更新,字母表对应高亮
this.currentSelect = index
//调用控制器方法,左边列表跳转到点击字母对应的索引
this.scroller.scrollToIndex(this.currentSelect)
})
完整代码:
@Entry
@Component
struct Index {
hotCitys: string[] =
['北京', '上海', '广州', '深圳', '天津', '杭州', '南京', '苏州', '成都', '武汉', '重庆', '西安', '香港', '澳门',
'台北']
historyCitys: string[] = ['北京', '上海', '广州', '深圳', '重庆']
cityContentList: BKCityContent[] = [
{
initial: 'A',
cityNameList: ['阿拉善', '鞍山', '安庆', '安阳', '阿坝', '安顺']
},
{
initial: 'B',
cityNameList: ['北京', '保定', '包头', '巴彦淖尔', '本溪', '白山']
},
{
initial: 'C',
cityNameList: ['成都', '重庆', '长春', '长沙', '承德', '沧州']
},
{
initial: 'D',
cityNameList: ['大连', '东莞', '大同', '丹东', '大庆', '大兴安岭']
},
{
initial: 'E',
cityNameList: ['鄂尔多斯', '鄂州', '恩施', '额尔古纳市', '二连浩特市', '恩施市']
},
{
initial: 'F',
cityNameList: ['福州', '佛山', '抚顺', '阜新', '阜阳', '抚州']
},
{
initial: 'G',
cityNameList: ['广州', '贵阳', '赣州', '桂林', '贵港', '广元']
},
{
initial: 'H',
cityNameList: ['杭州', '海口', '哈尔滨', '合肥', '呼和浩特', '邯郸']
},
{
initial: 'J',
cityNameList: ['济南', '晋城', '晋中', '锦州', '吉林', '鸡西']
},
{
initial: 'K',
cityNameList: ['昆明', '开封', '康定市', '昆山', '康保县', '宽城满族自治县']
},
{
initial: 'L',
cityNameList: ['兰州', '廊坊', '临汾', '吕梁', '辽阳', '辽源']
},
{
initial: 'M',
cityNameList: ['牡丹江', '马鞍山', '茂名', '梅州', '绵阳', '眉山']
},
{
initial: 'N',
cityNameList: ['南京', '宁波', '南昌', '南宁', '南通', '南平']
},
{
initial: 'P',
cityNameList: ['盘锦', '莆田', '萍乡', '平顶山', '濮阳', '攀枝花']
},
{
initial: 'Q',
cityNameList: ['青岛', '秦皇岛', '齐齐哈尔', '七台河', '衢州', '泉州']
},
{
initial: 'R',
cityNameList: ['日照', '日喀则', '饶阳县', '任丘市', '任泽区', '饶河县']
},
{
initial: 'S',
cityNameList: ['上海', '苏州', '深圳', '沈阳', '石家庄', '朔州']
},
{
initial: 'T',
cityNameList: ['天津', '太原', '唐山', '通辽', '铁岭', '通化']
},
{
initial: 'W',
cityNameList: ['无锡', '武汉', '乌海', '乌兰察布', '温州', '芜湖']
},
{
initial: 'X',
cityNameList: ['厦门', '西安', '西宁', '邢台', '忻州', '兴安盟']
},
{
initial: 'Y',
cityNameList: ['扬州', '阳泉', '运城', '营口', '延边', '伊春']
},
{
initial: 'Z',
cityNameList: ['郑州', '珠海', '张家口', '镇江', '舟山', '漳州']
}
]
alphabets: string[] =
['#', '热', "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "W", "X", "Y",
"Z"]
@State currentSelect: number = 0
@Builder
header(title: string) {
Text(title)
.fontSize(20)
}
// 创建控制器
scroller: ListScroller = new ListScroller()
//自定义组件
@Builder
myCity(item: string) {
Text(item)
.width("33%")
.textAlign(TextAlign.Center)
.padding(15)
}
build() {
Column() {
Stack({ alignContent: Alignment.End }) {
// 1城市
List({ scroller: this.scroller }) {
ListItemGroup({ header: this.header("历史"), space: 10 }) {
ListItem() {
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.historyCitys, (item: string) => {
this.myCity(item)
})
}
}
}
// 热门城市
ListItemGroup({ header: this.header("热门") }) {
ListItem() {
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.hotCitys, (item: string) => {
this.myCity(item)
})
}
}
}
ForEach(this.cityContentList, (item1: BKCityContent) => {
ListItemGroup({ header: this.header(item1.initial) }) {
ForEach(item1.cityNameList, (item2: string) => {
ListItem() {
this.myCity(item2)
}
})
}
})
}
.divider({ strokeWidth: 1, startMargin: 20, color: Color.Pink })
.width("100%")
// 同步索引,高亮
.onScrollIndex((start: number) => {
this.currentSelect = start
})
// 2字母表
AlphabetIndexer({ arrayValue: this.alphabets, selected: this.currentSelect })
.itemSize(30)
.selectedFont({ size: 20 })
.font({ size: 20 })// 点击字母表发生的事件
.onSelect((index: number) => {
this.currentSelect = index
this.scroller.scrollToIndex(this.currentSelect)
})// 显示弹窗
.usingPopup(true)
}
.backgroundColor(Color.White)
}
}
//定义接口
interface BKCityContent {
initial: string
cityNameList: string[]
}