• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2024 Huawei Device Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7*     http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16/**
17 * 功能描述:
18 * 1. 在搜索框中可以根据城市拼音模糊搜索出相近的城市,例如输入"a",会出现"阿尔山"、"阿勒泰地区"、"安庆"、"安阳"。
19 * 2. 下方城市列表通过AlphabetIndexer组件实现拼音索引条,通过滑动选择城市首拼,快速定位相关首拼城市。
20 *
21 * 实现原理:
22 * 1. 当用户滑动List组件,list组件onScrollIndex监听到firstIndex的改变,绑定赋值给AlphabetIndexer的selected属性,从而定位到字母索引。
23 * 2. 当点击AlphabetIndexer的字母索引时,通过scrollToIndex触发list组件滑动并指定firstIndex,从而实现List列表与AlphabetIndexer组件首字母联动吸顶展示。
24 *
25 * @param hotSelectList - 热门选择列表
26 * @param alphabetSelectList - 字母选择数据列表
27 * @param hotSelectListTitle - 热门选择列表标题
28 * @param hotSelectHandle - 点击热门选择列表项处理逻辑
29 * @param alphabetSelectHandle - 点击字母列表项处理逻辑
30 *
31 */
32import { AlphabetListItemView, HotListItemView } from '../model/DetailData';
33import { CommonConstants } from '../common/CommonConstants';
34
35@Component
36export struct AlphabetListView {
37  // -------------------对外暴露变量-----------------------
38  // 热门选择列表
39  hotSelectList: HotListItemView[] = [];
40  // 字母选择数据列表
41  alphabetSelectList: AlphabetListItemView[] = [];
42  // 热门列表标题
43  hotSelectListTitle: ResourceStr = '';
44  // 点击热门选择列表项处理逻辑
45  hotSelectHandle: (hotSelectValue: string) => void = (hotSelectValue: string = CommonConstants.INIT_VALUE) => {
46  };
47  // 点击字母列表项处理逻辑
48  alphabetSelectHandle: (alphabetSelectValue: string ) => void = (alphabetSelectValue: string =
49  CommonConstants.INIT_VALUE) => {
50  };
51  // --------------------私有属性----------------------------
52  // 初始化列表index
53  @State stabIndex: number = 0;
54  // 字母索引数据
55  @State alphabetIndexer: string[] = [];
56  // 滑动控制器
57  private scroller: Scroller = new Scroller();
58  // 搜索控制器
59  controller: SearchController = new SearchController();
60
61  build() {
62    Stack({ alignContent: Alignment.End }) {
63      Column() {
64        Text(this.hotSelectListTitle)
65          .fontSize($r('app.integer.citysearch_text_font'))
66          .fontColor($r('app.color.citysearch_text_font_color'))
67          .opacity(CommonConstants.OPACITY)
68          .margin({
69            left: $r('app.integer.citysearch_txt_margin_left'),
70            bottom: $r('app.integer.citysearch_row_margin_bottom')
71          })
72
73        Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center, wrap: FlexWrap.Wrap }) {
74          ForEach(this.hotSelectList, (hotCityItem: HotListItemView) => {
75            // 这里规定每行占四个城市
76            Column() {
77              hotCityItem.contentBuilder.builder(hotCityItem.hotListItem)
78            }.onClick(() => {
79              this.hotSelectHandle(hotCityItem.hotListItem);
80            })
81          })
82        }
83        .width(CommonConstants.VIEW_FULL)
84
85        List({
86          space: CommonConstants.LIST_SPACE,
87          initialIndex: CommonConstants.INITIAL_INDEX,
88          scroller: this.scroller
89        }) {
90          ForEach(this.alphabetSelectList, (alphabetListItem: AlphabetListItemView) => {
91            ListItem() {
92              Column() {
93                Text(`${alphabetListItem.alphabetListItem.name}`)
94                  .height($r('app.integer.citysearch_list_item_height'))
95                  .fontSize($r('app.integer.citysearch_font_size'))
96                  .fontColor($r('app.color.citysearch_text_font_color'))
97                  .width(CommonConstants.VIEW_FULL)
98                ForEach(alphabetListItem.alphabetListItem.dataList, (item: string) => {
99                  Column() {
100                    alphabetListItem.contentBuilder.builder(item)
101                  }.onClick(() => {
102                    this.alphabetSelectHandle(item);
103                  })
104                })
105              }
106            }
107          })
108        }
109        .width(CommonConstants.VIEW_FULL)
110        .margin({
111          left: $r('app.integer.citysearch_txt_margin_left'),
112          bottom: $r('app.integer.citysearch_txt_margin_bottom')
113        })
114        .layoutWeight(1)
115        .edgeEffect(EdgeEffect.None)
116        .divider({
117          strokeWidth: $r('app.integer.citysearch_divider_strokeWidth'),
118          color: $r('app.color.citysearch_divider_color'),
119          startMargin: $r('app.integer.citysearch_divider_start'),
120          endMargin: $r('app.integer.citysearch_divider_end')
121        })
122        .listDirection(Axis.Vertical)
123        .scrollBar(BarState.Off)
124        .onScrollIndex((firstIndex: number, lastIndex: number) => {
125          this.stabIndex = firstIndex;
126        })
127      }
128      .alignItems(HorizontalAlign.Start)
129
130      /* TODO:知识点:可以与容器组件联动用于按逻辑结构快速定位容器显示区域的组件,arrayValue为字母索引字符串数组,selected为初始选中项索引值。
131       * 1. 当用户滑动List组件,list组件onScrollIndex监听到firstIndex的改变,绑定赋值给AlphabetIndexer的selected属性,从而定位到字母索引。
132       * 2. 当点击AlphabetIndexer的字母索引时,通过scrollToIndex触发list组件滑动并指定firstIndex,从而实现List列表与AlphabetIndexer组件
133       * 首字母联动吸顶展示。
134       */
135      AlphabetIndexer({ arrayValue: this.alphabetIndexer, selected: this.stabIndex })
136        .height(CommonConstants.VIEW_FULL)
137        .selectedColor($r('app.color.citysearch_alphabet_select_color'))// 选中项文本颜色
138        .popupColor($r('app.color.citysearch_alphabet_pop_color'))// 弹出框文本颜色
139        .selectedBackgroundColor($r('app.color.citysearch_alphabet_selected_bgc'))// 选中项背景颜色
140        .popupBackground($r('app.color.citysearch_alphabet_pop_bgc'))// 弹出框背景颜色
141        .popupPosition({
142          x: $r('app.integer.citysearch_pop_position_x'),
143          y: $r('app.integer.citysearch_pop_position_y')
144        })
145        .usingPopup(true) // 是否显示弹出框
146        .selectedFont({ size: $r('app.integer.citysearch_select_font'), weight: FontWeight.Bolder })// 选中项字体样式
147        .popupFont({ size: $r('app.integer.citysearch_pop_font'), weight: FontWeight.Bolder })// 弹出框内容的字体样式
148        .alignStyle(IndexerAlign.Right)// 弹出框在索引条左侧弹出
149        .itemSize(CommonConstants.ALPHABET_SIZE)// 每一项的尺寸大小
150        .margin({ right: CommonConstants.ALPHABET_MARGIN_RIGHT_SIZE })
151        .onSelect((tabIndex: number) => {
152          this.scroller.scrollToIndex(tabIndex);
153        })
154    }
155    .flexShrink(1)
156    .flexGrow(1)
157    .padding({ bottom: $r('app.integer.citysearch_padding_bottom') })
158  }
159
160  aboutToAppear(): void {
161    if (this.alphabetSelectList.length) {
162      this.alphabetSelectList.forEach((item: AlphabetListItemView) => {
163        this.alphabetIndexer.push(item.alphabetListItem.name);
164      })
165    }
166  }
167}