AlphabetIndexer 组件与容器组件结合,实现导航联动,以及快速定位的效果

105 阅读2分钟

AlphabetIndexer 组件与容器组件结合,实现导航联动,以及快速定位的效果

静态布局效果

image.png

代码:

interface BKCityContent {
  initial: string
  cityNameList: string[]
}

@Entry
@Component
struct ListPageBK {
  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"]

  build() {
    Column() {
      this.PageBuilder()
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#f8f8f8')
  }

  @Builder
  PageBuilder() {
    Stack({ alignContent: Alignment.End }) {
      Column() {
        // 顶部
        this.TopBuilder();
        // 列表
        this.ListBuilder();
      }
      .backgroundColor(Color.White)

      // 导航 写这里
      this.AlphabetBuilder()
    }
  }

  @Builder
  AlphabetBuilder() {
    Text()
      .width(20)
      .height(400)
      .backgroundColor(Color.Orange)
  }

  @Builder
  ListBuilder() {
    List({ space: 30 }) {
      // 历史
      this.LocationListItemBuilder()
      // 热门
      this.HotListItemBuilder()

      // A-B的区域
      this.LetterListItemBuilder()
    }
    .divider({
      startMargin: 20,
      endMargin: 20,
      color: '#f3f3f3',
      strokeWidth: 2
    })
    .width('100%')
    .layoutWeight(1)
    .sticky(StickyStyle.Header)

  }

  @Builder
  LetterListItemBuilder() {
    // A-B的区域
    ListItemGroup({ header: this.ListItemGroupHeaderBuilder('A') }) {
      ListItem() {
        Text('阿拉善')
          .width('100%')
          .padding({ left: 20 })
      }
      .width('100%')
      .height(50)
      .backgroundColor(Color.White)
    }
    .padding({ bottom: 20 })
    .divider({
      startMargin: 20,
      endMargin: 20,
      color: '#f3f3f3',
      strokeWidth: 2
    })
  }

  @Builder
  ListItemGroupHeaderBuilder(title: string) {
    Text(title)
      .padding({ left: 20, bottom: 15, top: 20 })
      .fontSize(14)
      .fontColor(Color.Gray)
      .backgroundColor('#f8f8f8')
      .width('100%')
  }

  @Builder
  HotListItemBuilder() {
    // 热门
    ListItem() {
      Column({ space: 10 }) {
        Text('热门城市')
          .alignSelf(ItemAlign.Start)
          .fontColor(Color.Gray)
          .fontSize(14)
        Flex({ wrap: FlexWrap.Wrap }) {
          Text('北京')
            .height(25)
            .backgroundColor(Color.White)
            .width('25%')
            .margin({ bottom: 10 })
        }
        .padding({ left: 20, right: 20 })
      }
      .width('100%')
      .padding({ left: 20, right: 20, bottom: 10 })
    }
  }

  @Builder
  LocationListItemBuilder() {
    ListItem() {
      Column({ space: 15 }) {
        // 定位地址
        Row() {
          Text('北京')
          Text() {
            ImageSpan($r('app.media.ic_public_location_fill_blue'))
              .width(20)
            Span('开启定位')
          }
        }
        .width('100%')
        .padding({
          top: 10,
          bottom: 10,
          right: 20,
          left: 20
        })
        .justifyContent(FlexAlign.SpaceBetween)
        .backgroundColor(Color.White)

        // 历史
        Column({ space: 10 }) {
          Text('历史')
            .fontColor(Color.Gray)
            .alignSelf(ItemAlign.Start)
            .fontSize(14)
          Flex({ wrap: FlexWrap.Wrap }) {
            Text('北京')
              .height(25)
              .backgroundColor(Color.White)
              .width('25%')
              .margin({ bottom: 10 })
          }
          .padding({ left: 20, right: 20 })
        }
        .width('100%')
        .padding({ left: 20, right: 20 })
      }
    }
    .padding({ top: 20 })
  }

  @Builder
  TopBuilder() {
    Column() {
      // X + 输入框
      Row({ space: 20 }) {
        Image($r('app.media.ic_public_cancel'))
          .width(30)
          .fillColor(Color.Gray)

        Row({ space: 5 }) {
          Image($r('app.media.ic_public_search'))
            .width(18)
          Text('请输入城市名称')
            .layoutWeight(1)
        }
        .height(50)
        .border({ width: .5, color: Color.Gray, radius: 5 })
        .padding({ left: 5 })
        .layoutWeight(1)
        .shadow({
          radius: 20,
          color: '#f6f6f7'
        })
      }
      .padding({
        left: 15,
        right: 15,
        top: 15
      })

      // 国内城市
      Column() {
        Text('国内城市')
          .fontSize(15)
          .fontWeight(800)
          .padding(5)
        Row()
          .width(20)
          .height(2)
          .backgroundColor('#0094ff')
          .borderRadius(2)
      }

    }
    .width('100%')
    .backgroundColor(Color.White)
    .height(100)
    .border({
      width: { bottom: 4 },
      color: '#f6f6f7',
    })
  }
}

渲染历史和热门城市

历史城市

Column({ space: 10 }) {
  Text('历史')
    .fontColor(Color.Gray)
    .alignSelf(ItemAlign.Start)
    .fontSize(14)
  Flex({ wrap: FlexWrap.Wrap }) {
    ForEach(this.historyCitys,(item:string)=>{
      Text(item)
        .height(25)
        .backgroundColor(Color.White)
        .width('25%')
        .margin({ bottom: 10 })
    })
  }
  .padding({ left: 20, right: 20 })
}
.width('100%')
.padding({ left: 20, right: 20 })

image.png

热门城市

Column({ space: 10 }) {
  Text('热门城市')
    .alignSelf(ItemAlign.Start)
    .fontColor(Color.Gray)
    .fontSize(14)
  Flex({ wrap: FlexWrap.Wrap }) {
    ForEach(this.hotCitys,(item:string)=>{
      Text(item)
        .height(25)
        .backgroundColor(Color.White)
        .width('25%')
        .margin({ bottom: 10 })
    })
  }
  .padding({ left: 20, right: 20 })
}
.width('100%')
.padding({ left: 20, right: 20, bottom: 10 })

image.png

渲染城市列表

@Builder
LetterListItemBuilder() {
  // A-B的区域
  ForEach(this.cityContentList,(item:BKCityContent)=>{
    ListItemGroup({ header: this.ListItemGroupHeaderBuilder(item.initial) }) {
      ForEach(item.cityNameList,(city:string)=>{
        ListItem() {
          Text(city)
            .width('100%')
            .padding({ left: 20 })
        }
        .width('100%')
        .height(50)
        .backgroundColor(Color.White)
      })
    }
    .padding({ bottom: 20 })
    .divider({
      startMargin: 20,
      endMargin: 20,
      color: '#f3f3f3',
      strokeWidth: 2
    })
  })
}

@Builder
ListItemGroupHeaderBuilder(title: string) {
  Text(title)
    .padding({ left: 20, bottom: 15, top: 20 })
    .fontSize(14)
    .fontColor(Color.Gray)
    .backgroundColor('#f8f8f8')
    .width('100%')
}

image.png

渲染侧边导航

image.png

@Builder
AlphabetBuilder() {
  AlphabetIndexer({
    arrayValue:this.alphabets,
    selected:this.currentindex
  })
}

城市及导航的联动效果

image.png

@Builder
AlphabetBuilder() {
  AlphabetIndexer({ arrayValue: this.alphabets, selected: $$this.selectedIndex })
    .width(20)
    .onSelect((index) => {
      this.listScroller.scrollToIndex(index)
    })
}
@Builder
ListBuilder() {
  List({ space: 30, scroller: this.listScroller }) {
  ······
  }
  ······
  .onScrollIndex((index: number) => {
    this.selectedIndex = index
  })
}