#我的鸿蒙开发手记#鸿蒙实体店铺首页效果 原创 精华

开源武术
发布于 2025-5-6 12:47
浏览
0收藏

一、背景与前提
1.背景
本学习练习基于 HarmonyOS 5.0.0 及以上版本、DevEco Studio 5.0.0 及以上版本等环境进行鸿蒙实体店铺首页效果的开发展开。
对门店首页整体构建布局设计进行了介绍,包括首页模块(Home.ets)的设置以及在 ets 下创建 model 数据层文件和 contants 常量文件等。说明了 TabListItem.ets 和 Constants.ets 的代码实现,分别用于导出底部导航栏选项卡数据模型和配置应用底部导航栏。重点对 products 产品层下的 pages>MainEntry.ets 关键代码实现进行了讲解,展示了如何引入各功能模块组件、创建导航容器以及实现底部导航栏的标签切换等。阐述了首页功能模块与实现流程,首页 UI 由 Banner 轮播图、服务分类栅格、预约参观手势导航等核心组件构成。分别对 Home.ets 文件的创建与实现代码进行了说明,包括首页的生命周期方法、页面构建等。介绍了 Banner 轮播组件、服务分类栅格布局以及附近门店动态加载的开发,分别通过 Banner.ets、SeviceGrids.ets 和 NearbyStores.ets 的代码实现来展示相应的功能。
2.前提
(1)设备类型:华为手机
(2)HarmonyOS版本:HarmonyOS 5.0.0 Release及以上
(3)DevEco Studio版本:DevEco Studio 5.0.0 Release及以上
(4)HarmonyOS SDK版本:HarmonyOS 5.0.0 Release SDK及以上
二、门店首页整体构建布局设计
1.模块设计
首页模块:Home.ets
2.首页UI布局开发
(1)在ets下创建model数据层文件,创建contants常量文件。
#我的鸿蒙开发手记#鸿蒙实体店铺首页效果-鸿蒙开发者社区
(2)TabListItem.ets代码实现:

//导出底部导航栏选项卡数据模型
export interface TabListItem {
  label: string;
  icon: Resource;
  iconChecked: Resource;
}

(3)Constants.ets代码实现:

// 导入底部导航栏选项卡数据模型
import { TabListItem } from '../model/TabListItem';

/**
 * 应用底部导航栏配置常量
 */
export const TAB_LIST: TabListItem[] = [
  {
    label: '首页',  // 选项卡显示文字
    icon: $r('app.media.ic_home'),  // 常规状态图标(鸿蒙资源引用语法)
    iconChecked: $r('app.media.ic_home_checked'),  // 选中状态图标
  },
  {
    label: '门店',
    icon: $r('app.media.ic_stores'),  // 图标资源路径:resources/base/media/ic_stores.svg
    iconChecked: $r('app.media.ic_stores_checked'),  // 激活态图标带指示红点
  },
  {
    label: '活动',
    icon: $r('app.media.ic_activities'),  // 建议图标尺寸:24x24vp
    iconChecked: $r('app.media.ic_activities_checked'),  // 选中态增加缩放动画
  },
  {
    label: '我的',
    icon: $r('app.media.ic_mine'),  // 未登录状态显示轮廓图标
    iconChecked: $r('app.media.ic_mine_checked'),  // 登录后显示头像缩略图
  },
];

/* 使用说明:
1. 在MainEntry.ets中通过Tabs组件绑定该配置
2. 图标状态切换通过currentIndex控制
3. 新增模块时需同步更新:
   - 添加新配置项
   - 在resources目录补充图标资源
   - 更新路由配置
*/

(4)products产品层下的pages>MainEntry.ets关键代码实现:

// 引入各功能模块组件
import { Home } from '@ohos_agcit/postpartum_care_center_home';      // 首页模块
import { Mine } from '@ohos_agcit/postpartum_care_center_mine';      // 我的模块
import { Stores } from '@ohos_agcit/postpartum_care_center_stores';  // 门店模块
import { Activities } from '@ohos_agcit/postpartum_care_center_activities'; // 活动模块
import { TAB_LIST } from '../contants/Constants';                    // 底部导航标签配置数据
import { MainEntryVM } from '@ohos_agcit/postpartum_care_center_uicomponents'; // 主入口视图模型
import { TabListItem } from '../model/TabListItem';                  // 标签项数据模型
import { Logger } from '@ohos_agcit/postpartum_care_center_utils';   // 日志工具类

const TAG: string = '[MainEntry]';  // 日志标签

@Entry                                // 标识为入口组件
@ComponentV2                          // 声明为V2版本组件
struct MainEntry {
  vm: MainEntryVM = MainEntryVM.instance;  // 绑定视图模型单例

  build() {
    Navigation(this.vm.navStack) {    // 创建导航容器,绑定导航栈
      Column() {                      // 主布局容器
        Tabs({ 
          barPosition: BarPosition.End,  // 标签栏位置:底部(End表示底端)
          index: this.vm.curIndex     // 当前选中标签索引
        }) {
          // ---------- 首页标签 ----------
          TabContent() {
            Home();                   // 加载首页组件
          }
          .clip(false)                // 禁用内容裁剪
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP]) // 适配顶部安全区域
          .tabBar(this.tabBarBuilder(TAB_LIST[0], 0)) // 绑定标签栏构建器

          // ---------- 门店标签 ----------
          TabContent() {
            //Stores();                  // 加载门店组件
          }
          .clip(false)
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
          .tabBar(this.tabBarBuilder(TAB_LIST[1], 1))

          // ---------- 活动标签 ----------
          TabContent() {
            //Activities();              // 加载活动组件
          }
          .clip(false)
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
          .tabBar(this.tabBarBuilder(TAB_LIST[2], 2))

          // ---------- 我的标签 ----------
          TabContent() {
            //Mine();                    // 加载个人中心组件
          }
          .clip(false)
          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
          .tabBar(this.tabBarBuilder(TAB_LIST[3], 3))
        }
        // Tabs全局配置
        .clip(false)
        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
        .scrollable(false)             // 禁用标签栏滚动
        .height('100%')               
        .animationDuration(0)         // 切换动画时长0毫秒(无动画)
        .barMode(BarMode.Fixed)       // 标签栏模式:固定宽度
        .barHeight(56)                
        .onChange((index: number) => { // 标签切换事件监听
          this.vm.curIndex = index;   // 更新当前选中索引
        });
      }
      .clip(false)
      .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
    }
    // Navigation全局配置
    .height('100%')                   // 高度充满屏幕
    .clip(false)
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) // 适配顶部和底部安全区域
    .hideTitleBar(true)               // 隐藏标题栏
    .hideToolBar(true)                // 隐藏工具栏
    .hideBackButton(true)             // 隐藏返回按钮
    .mode(NavigationMode.Stack)       // 导航模式:堆栈模式
  }

  // 自定义标签栏构建器
  @Builder
  tabBarBuilder(item: TabListItem, index: number) {
    Column() {                        
      Image(this.vm.curIndex === index ? item.iconChecked : item.icon) // 动态切换选中/未选图标
        .width(24)                    
        .height(24);                  
      Text(item.label)                
        .fontColor(this.vm.curIndex === index ? 
          'rgba(0,0,0,0.90)' :        
          'rgba(0,0,0,0.60)')        
        .fontFamily('HarmonyHeiTi')   
        .fontWeight(this.vm.curIndex === index ? 
          FontWeight.Medium :         
          FontWeight.Regular)         
        .fontSize($r('app.string.font_size_10')) 
        .margin({ top: $r('app.string.margin_xxs') }); 
    }.width('100%');                  
  }
}

三、首页功能模块与实现流程
1.首页UI结构设计
首页由以下核心组件构成:
·Banner轮播图:展示品牌活动或服务亮点。
·服务分类栅格:提供产后护理、月子餐等分类入口。
·预约参观手势导航:用于用户咨询相关,填写个人信息表单进行预约。
2.功能实现步骤
(1)Home.ets文件创建与实现代码:
①在根目录PostpartumCareCenter下创建scenes场景文件目录
②在scenes目录下创建Home模块(HSP动态共享)
#我的鸿蒙开发手记#鸿蒙实体店铺首页效果-鸿蒙开发者社区
③Home.ets关键代码实现:

import { Banner } from '../view/Banner';
import { NearbyStores } from '../view/NearbyStores';
import { ServiceGrids } from '../view/SeviceGrids';
import { MainEntryVM, StoreModel, TitleTop } from '@ohos_agcit/postpartum_care_center_uicomponents';

const STORE_LIST : StoreModel[] = [
  new StoreModel(1, '南京涵江楼', '南京市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '南京', 31.98, 118.76),
  new StoreModel(2, '南京卓美悦', '南京市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '南京', 31.99, 118.71),
  new StoreModel(5, '苏州华轩苑', '苏州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '苏州', 31.29, 120.64),
  new StoreModel(3, '南京华轩府', '南京市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '南京', 32.03, 118.80),
  new StoreModel(4, '无锡雅辉阁', '无锡市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '无锡', 31.58, 120.30),
  new StoreModel(6, '杭州科技城', '杭州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '杭州', 30.22, 120.12),
  new StoreModel(7, '北京卓美悦', '北京市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '北京', 39.91, 116.47),
  new StoreModel(8, '深圳海月楼', '深圳市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '深圳', 22.54, 114.06),
  new StoreModel(9, '东莞华轩苑', '东莞市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '东莞', 23.02, 113.75),
  new StoreModel(10, '广州银月楼', '广州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '广州', 23.13, 113.26),
  new StoreModel(11, '汕头卓美悦', '汕头市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '汕头', 23.35, 116.68),
  new StoreModel(12, '常州银月楼', '常州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '常州', 31.81, 119.94),
  new StoreModel(13, '上海银月楼', '上海市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '上海', 31.23, 121.47),
  new StoreModel(14, '上海云顶轩', '上海市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '上海', 31.20, 121.36),
  new StoreModel(15, '北京云顶轩', '北京市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '北京', 39.90, 116.41),
  new StoreModel(16, '常州星辉阁', '常州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '常州', 31.78, 119.89),
  new StoreModel(17, '深圳华轩苑', '深圳市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '深圳', 22.57, 113.94),
  new StoreModel(18, '广州卓美拉', '广州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '广州', 23.17, 113.39),
  new StoreModel(19, '上海雅阁楼', '上海市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '上海', 31.18, 121.38),
  new StoreModel(20, '上海华轩府', '上海市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '上海', 31.22, 121.35),
  new StoreModel(21, '杭州涵江楼', '杭州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '杭州', 30.25, 120.16),
  new StoreModel(22, '杭州卓美悦', '杭州市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic2'), '杭州', 30.20, 119.99),
  new StoreModel(23, '无锡卓美悦', '无锡市高新技术产业园区软件大道101号酒店16F', '12345678910',
    $r('app.media.store_pic1'), '无锡', 31.52, 120.45),
];

@Entry
@Preview
@ComponentV2
export struct Home {
  // 获取ViewModel单例实例,用于数据管理和页面跳转控制
  vm: MainEntryVM = MainEntryVM.instance;

  // 生命周期方法:页面即将显示时触发
  aboutToAppear(): void {
    // 初始化门店列表数据(开发环境模拟数据)
    this.vm.storeList.storeList = STORE_LIST;          // 完整门店列表
    this.vm.storeListNearby.storeList = STORE_LIST;   // 附近门店列表
    // 请求定位权限(需在manifest中声明ohos.permission.LOCATION)
    this.vm.requestLocationPermission();
  }

  build() {
    // 主容器:纵向布局填充全屏
    Column() {
      // 顶部标题栏组件(传入国际化标题资源)
      TitleTop({ title: $r('app.string.title_home')})
      
      // 滚动容器(关闭滚动条显示)
      Scroll() {
        Column() {
          // 1. Banner轮播模块
          Banner() 
          
          // 2. 服务分类模块
          Column() {
            Text($r('app.string.title_sub_service'))  
              .fontColor('rgba(0,0,0,0.90)')        
              .fontSize($r('app.string.font_size_18')) 
              .fontFamily('HarmonyHeiTi')             
              .fontWeight(FontWeight.Bold)          
              .height(56)                             
              .padding({ 
                top: $r('app.string.padding_24'),    
                bottom: $r('app.string.padding_8')   
              });
            
            // 服务网格组件(3列布局)
            ServiceGrids()  // 包含月子护理/产后修复等分类
              .margin({ top: $r('app.string.margin_xs') });  // 顶部小间距
          }
          .backgroundColor('#F1F3F5')  // 浅灰色背景
          .padding({                   
            left: $r('app.string.padding_16'),
            right: $r('app.string.padding_16')
          });

          // 3. 预约参观模块
          Column() {
            // 模块标题行(左右布局)
            Row() {
              // 左侧标题
              Text($r('app.string.title_sub_booking'))  // "预约参观"
                .fontColor('rgba(0,0,0,0.90)') 
                .fontSize($r('app.string.font_size_18'))
                .fontFamily('HarmonyHeiTi')
                .fontWeight(FontWeight.Bold)
                .width('50%')          // 占据50%宽度
                .height(56)            // 与右侧等高
                .padding({ 
                  top: $r('app.string.padding_24'),
                  bottom: $r('app.string.padding_8')
                })
                .textAlign(TextAlign.Start);  // 左对齐

              // 右侧"全部门店"可点击区域
              Row() {
                Text($r('app.string.title_sub_all_store'))  // "全部门店"
                  .fontColor('rgba(0,0,0,0.60)')   
                  .fontSize($r('app.string.font_size_14'))
                  .height(56)
                  .padding({ 
                    top: $r('app.string.padding_29'),  // 精密垂直居中
                    bottom: $r('app.string.padding_8')
                  });
                
                // 右箭头图标
                Image($r('app.media.chevron_right'))  // 资源路径:media/chevron_right.svg
                  .width(12)  // 图标尺寸
                  .height(56)
                  .padding({ 
                    top: $r('app.string.padding_26'),
                    bottom: $r('app.string.padding_6'),
                    left: $r('app.string.padding_5')  // 文字与图标间距
                  });
              }
              .justifyContent(FlexAlign.End)  // 子组件右对齐
              .width('50%')
              .height(56)
              .onClick(() => {  // 点击跳转门店页
                this.vm.curIndex = 1;  // 切换底部Tab索引
              });
            }
            .padding({  // 左右安全边距
              left: $r('app.string.padding_16'),
              right: $r('app.string.padding_16')
            })
            .justifyContent(FlexAlign.SpaceBetween)  // 两端对齐
            .width('100%');

            // 附近门店列表组件
            NearbyStores()  // 包含距离/预约按钮等功能
              .margin({ top: $r('app.string.margin_xs') });  // 顶部小间距
          };
        }
        .padding({  // 滚动区域内部间距
          top: $r('app.string.padding_8'),
          bottom: $r('app.string.padding_10')
        })
      }
      .scrollBar(BarState.Off)  // 禁用滚动条(保持视觉简洁)
      .layoutWeight(1)         // 权重分配(撑满剩余空间)
    }
    // 页面级样式设置
    .width('100%')            // 满宽
    .height('100%')           // 满高
    .align(Alignment.TopStart)// 顶部对齐
    .backgroundColor('#F1F3F5')  // 页面背景色
    .clip(false)              // 允许子组件溢出
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])  // 适配刘海屏
  }
}

(2)步骤一:Banner轮播组件开发
描述:自动轮播品牌宣传图,支持手动滑动
Banner.ets代码实现:

// 引入轮播图数据源
import { BANNER_LIST } from '../constants/Constants';
@Preview
@ComponentV2
export struct Banner {
  build() {
    // 创建轮播容器
    Swiper() {
      // 遍历BANNER_LIST数据生成轮播项
      ForEach(BANNER_LIST, (item: Resource) => {
        // 单张轮播图容器
        Image(item)
          .objectFit(ImageFit.Fill)       // 图片填充模式:充满容器
          .width('100%')                 
          .height(246)                     
          .borderRadius($r('app.string.border_radius_16')) // 圆角16单位(从资源文件读取)
          .padding({ 
            right: $r('app.string.padding_16'),
            left: $r('app.string.padding_16')            })
      }, (item: Resource) => JSON.stringify(item)) // 唯一键生成规则
    }
    // 轮播指示器配置
    .indicator(
      Indicator.dot()                     
        .selectedColor('#FFFFFF')          
        .selectedItemWidth(12)             
        .selectedItemHeight(8)             
        .itemWidth(8)                    
        .itemHeight(8)                    
        .color('rgba(0,0,0,0.10)')       
    )
    .clip(false)                          // 禁止内容裁剪
    .autoPlay(true)                      
    .loop(true)                          
.backgroundColor('#F1F3F5')          
.expandSafeArea(                      // 安全区域扩展配置
      [SafeAreaType.SYSTEM],              // 适配系统安全区域(如刘海屏)
      [SafeAreaEdge.TOP]                  // 顶部区域扩展
    );
  }
}

(3)服务分类栅格布局
描述:以3列栅格形式展示服务分类,点击跳转至详情页
SeviceGrids.ets代码实现:

//引用资源路径
import { MainEntryVM } from '@ohos_agcit/postpartum_care_center_uicomponents';
import { SERVICE_LIST } from '../constants/Constants';
import { ServiceGridItem } from '../model/ServiceGridItem';

@Preview  
@ComponentV2  
export struct ServiceGrids {
  // 使用单例模式获取ViewModel实例,用于页面导航等逻辑控制
  vm: MainEntryVM = MainEntryVM.instance;

  build() {
    // 网格布局容器
    Grid() {
      // 遍历服务列表数据生成网格项
      ForEach(SERVICE_LIST, (item: ServiceGridItem, index: number) => {
        // 单个网格项定义
        GridItem() {
          // 垂直排列的列容器(图标+文字)
          Column() {
            // 服务图标
            Image(item.icon)
              .width(40)  
              .height(40)  
              .objectFit(ImageFit.Cover);  // 图片填充模式为覆盖
            
            // 服务名称文本
            Text(item.label)
              .fontFamily('HarmonyHeiTi')  
              .fontWeight(FontWeight.Regular)  
              .fontSize($r('app.string.font_size_12'))  
              .fontColor('rgba(0, 0, 0, 0.9)')  
              .margin({ top: $r('app.string.margin_xxs') });  // 顶部间距使用xxs尺寸
          };
        }
        .width(68)  
        .onClick(() => {  // 点击事件处理
          // 通过ViewModel跳转到服务详情页,传递服务名称参数
          this.vm.navStack.pushPathByName('ServiceDetail', item.label);
        });
      }, (item: ServiceGridItem) => JSON.stringify(item));  // 使用JSON序列化作为ForEach的key生成器
    }
    // 网格布局样式设置
    .columnsGap(8)  // 列间距8vp
    .rowsGap(16)  // 行间距16vp
    .padding({  
      top: $r('app.string.padding_12'),  
      bottom: $r('app.string.padding_12'),  
      right: $r('app.string.padding_16'),  
      left: $r('app.string.padding_16')  
    })
    .borderRadius($r('app.string.border_radius_16'))  
    .backgroundColor('#FFFFFF')  
    .width('100%');  
  }
}

(4)附近门店动态加载
描述:用于用户咨询相关,填写个人信息表单进行预约
NearbyStores.ets代码实现:

// 导入必要的组件和模块
import { MainEntryVM, StoreCard, StoreModel } from '@ohos_agcit/postpartum_care_center_uicomponents';
import { Logger } from '@ohos_agcit/postpartum_care_center_utils';

// 常量定义:最多显示的门店卡片数量
const STORE_SHOWN_NUM: number = 2;

// 附近门店卡片滑动组件
@Preview 
@ComponentV2  
export struct NearbyStores {
  // 使用单例模式获取ViewModel实例
  vm: MainEntryVM = MainEntryVM.instance;
  
  // 当前显示卡片的索引(使用@Local装饰器表示组件内部状态)
  @Local currentIndex: number = 0;
  
  // 手势拖动的X轴偏移量(用于滑动动画计算)
  @Local panTranslateX: number = 0;

  build() {
    Column() {
      // 使用堆叠布局实现卡片重叠效果
      Stack() {
        // 遍历附近门店列表数据
        ForEach(this.vm.storeListNearby.storeList, (item: StoreModel, index: number) => {
          // 单个门店卡片组件
          StoreCard({ store: item })
            // 基础样式设置
            .padding({ 
              left: $r('app.string.padding_16'),  
              right: $r('app.string.padding_16')
            })
            // 动态宽度计算:当前卡片100%,后续卡片逐渐缩小
            .width(`${(1.0 - 0.9 * (index - this.currentIndex) * 0.05) * 100}%`)
            .align(Alignment.Center)  
            
            // 层级控制:保证前面的卡片显示在上层
            .zIndex(this.vm.storeListNearby.storeList.length - index)
            
            // 动态位置:实现卡片堆叠效果
            .position({
              y: item.translateY + (index - this.currentIndex) * 10,  // Y轴偏移
              x: item.translateX + (index - this.currentIndex) * 8,   // X轴偏移
            })
            
            // 透明度控制:只显示前STORE_SHOWN_NUM个卡片
            .opacity((index <= STORE_SHOWN_NUM) ? 1 : 0)
            
            // 手势处理(优先级高于子组件手势)
            .priorityGesture(
              // 拖动手势定义
              PanGesture()
                .onActionStart(() => {  // 手势开始
                  this.panTranslateX = 0;  // 重置偏移量
                  Logger.debug('testTag', 'Pan start');  // 日志记录
                })
                .onActionUpdate((event: GestureEvent) => {  // 手势更新
                  this.panTranslateX += event.offsetX;  // 累加X轴偏移
                  Logger.debug('testTag', `Pan update: ${this.panTranslateX}`);
                })
                .onActionEnd(() => {  // 手势结束
                  const distanceThreshold = 100;  // 滑动阈值100vp
                  
                  // 向右滑动超过阈值时触发切换动画
                  if (this.panTranslateX > distanceThreshold) {
                    animateTo({
                      duration: 200,  // 动画时长200ms
                      curve: Curve.EaseOut,  // 缓动曲线
                      onFinish: () => {  // 动画结束回调
                        // 重置卡片位置
                        item.translateX = 0;
                        item.translateY = 0;
                        
                        // 实现循环列表效果:将第一个元素移到末尾
                        const storeList = [...this.vm.storeListNearby.storeList];
                        storeList.push(storeList[0]);
                        this.vm.storeListNearby.storeList = storeList.slice(1);
                        
                        // 标记不需要重新排序
                        this.vm.storeListNearby.needSortStore = false;
                        Logger.debug('testTag', 'Animation finished');
                      },
                    }, () => {  // 动画执行过程
                      // 设置飞出动画效果
                      item.translateX += 400;  // 向右飞出400vp
                      item.translateY -= 60;   // 向上飞出60vp
                    });
                  }
                  Logger.debug('testTag', 'Pan gesture ended');
                }),
            );
        }, (item: StoreModel) => JSON.stringify(item));  // 使用JSON序列化作为key
      }
      .height(340);  // 固定堆叠容器高度
    };
  }
}

四、最终成果展示
#我的鸿蒙开发手记#鸿蒙实体店铺首页效果-鸿蒙开发者社区

五、注意事项
权限配置:需在module.json5中声明ohos.permission.LOCATION权限。
兼容性:仅支持HarmonyOS 5.0.0及以上版本。
数据安全:用户手机号需通过华为账号服务授权获取。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2025-5-6 13:51:58修改
收藏
回复
举报
回复
    相关推荐