0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙OS开发:【一次开发,多端部署】(app市场首页)

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-05-25 16:41 次阅读

应用市场首页

本小节将以应用市场首页为例,介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。

页面设计

一个典型的应用市场首页的UX设计如下所示。

image.png

观察应用市场首页的页面设计,不同断点下的页面设计有较多相似的地方。

据此,我们可以将页面分拆为多个组成部分。

  1. 底部/侧边导航栏
  2. 标题栏与搜索栏
  3. 运营横幅
  4. 快捷入口
  5. 精品应用
  6. 开发前请熟悉鸿蒙开发指导文档 :[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]点击或者复制转到。

image.png

接下来我们逐一分析各部分的实现。

底部/侧边导航栏

在sm和md断点下,导航栏在底部;在lg断点下,导航栏在左侧。可以通过[Tab组件]的barPosition和vertical属性控制TabBar的位置,同时还可以通过barWidth和barHeight属性控制TabBar的尺寸。

import Home from '../common/Home';//组件请参考相关实例
import TabBarItem from '../common/TabBarItem';

@Entry
@Component
struct Index {
  @State currentIndex: number = 0;
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md';
  @Builder
  tabItem(index: number, title: Resource, icon: Resource, iconSelected: Resource) {
    TabBarItem({
      index: index,
      currentIndex: this.currentIndex,
      title: title,
      icon: icon,
      iconSelected: iconSelected
    })
  }

  build() {
    // 设置TabBar在主轴方向起始或结尾位置
    Tabs({ barPosition: this.currentBreakpoint === "lg" ? BarPosition.Start : BarPosition.End }) {
      // 首页
      TabContent() {
        Home()
      }.tabBar(this.tabItem(0, $r('app.string.tabBar1'), $r('app.media.ic_home_normal'), $r('app.media.ic_home_actived')))
      TabContent() {}.tabBar(this.tabItem(1, $r('app.string.tabBar2'), $r('app.media.ic_app_normal'), $r('app.media.ic_app_actived')))
      TabContent() {}.tabBar(this.tabItem(2, $r('app.string.tabBar3'), $r('app.media.ic_game_normal'), $r('app.media.ic_mine_actived')))
      TabContent() {}.tabBar(this.tabItem(3, $r('app.string.tabBar4'), $r('app.media.ic_search_normal'), $r('app.media.ic_search_actived')))
      TabContent() {}.tabBar(this.tabItem(4, $r('app.string.tabBar4'), $r('app.media.ic_mine_normal'), $r('app.media.ic_mine_actived')))
    }
    .backgroundColor('#F1F3F5')
    .barMode(BarMode.Fixed)
    .barWidth(this.currentBreakpoint === "lg" ? 96 : '100%')
    .barHeight(this.currentBreakpoint === "lg" ? '60%' : 56)
    // 设置TabBar放置在水平或垂直方向
    .vertical(this.currentBreakpoint === "lg") 
  }
}

另外在sm及lg断点下,TabBar中各个Item的图标和文字是按照垂直方向排布的,在md断点下,TabBar中各个Item的图标和文字是按照水平方向排布的。

@Component
export default struct TabBarItem {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md';

  build() {
    if (this.currentBreakpoint !== 'md' ) {
      // sm及lg断点下,tabBarItem中的图标和文字垂直排布
      Column() {
       // ...
      }.justifyContent(FlexAlign.Center).height('100%').width('100%')
    } else {
      // md断点下,tabBarItem中的图标和文字水平排布
      Row() {
       // ...
      }.justifyContent(FlexAlign.Center).height('100%').width('100%')
    }
  }
}

标题栏与搜索栏

标题栏和搜索栏,在sm和md断点下分两行显示,在lg断点下单行显示,可以通过栅格实现。在sm和md断点下,标题栏和搜索栏占满12列,此时会自动换行显示。在lg断点下,标题栏占8列而搜索栏占4列,此时标题栏和搜索栏在同一行中显示。

image.png

@Component
export default struct IndexHeader {

  @Builder searchBar() {
    Stack({alignContent: Alignment.End}) {
      TextInput({ placeholder: $r('app.string.search') })
        .placeholderColor('#FF000000')
        .placeholderFont({ size: 16, weight: 400 })
        .textAlign(TextAlign.Start)
        .caretColor('#FF000000')
        .width('100%')
        .height(40)
        .fontWeight(400)
        .padding({ top: 9, bottom: 9 })
        .fontSize(16)
        .backgroundColor(Color.White)

      Image($r('app.media.ic_public_search'))
        .width(16)
        .height(16)
        .margin({ right: 20 })
    }.height(56).width('100%')
  }

  @Builder titleBar() {
    Text($r('app.string.tabBar1'))
      .fontSize(24)
      .fontWeight(500)
      .fontColor('#18181A')
      .textAlign(TextAlign.Start)
      .height(56)
      .width('100%')
  }

  build() {
    // 借助栅格实现标题栏和搜索栏在不同断点下的不同布局效果。
    GridRow() {
      GridCol({ span: { xs: 12, lg: 8 } }) {
        this.titleBar()
      }
      GridCol({ span: { xs: 12, lg: 4 } }) {
        this.searchBar()
      }
    }
    .width('100%')
  }
}

运营横幅

不同断点下的运营横幅,sm断点下显示一张图片,md断点下显示两张图片,lg断点下显示三张图片。可以通过[Swiper组件的displayCount属性]实现目标效果。

@Component
export default struct IndexSwiper {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md';
  @Builder swiperItem(imageSrc:Resource) {
    Image(imageSrc)
      .width('100%')
      .aspectRatio(2.5)
      .objectFit(ImageFit.Fill)
  }

  build() {
    Swiper() {
      this.swiperItem($r('app.media.ic_public_swiper1'))
      this.swiperItem($r('app.media.ic_public_swiper2'))
      this.swiperItem($r('app.media.ic_public_swiper3'))
      // ...
    }
    .autoPlay(true)
    .indicator(false)
    .itemSpace(10)
    // 配置不同断点下运行横幅中展示的图片数量
    .displayCount(this.currentBreakpoint === 'sm' ? 1 : (this.currentBreakpoint === 'md' ? 2 : 3))
    .width('100%')
    .padding({ left: 12, right: 12, bottom: 16, top: 16 })
  }
}

快捷入口

在不同的断点下,快捷入口的5个图标始终均匀排布,这是典型的均分能力使用场景。

import { entranceIcons } from '../model/HomeData';
import { AllIcons } from '../model/HomeDataType';

@Component
export default struct IndexEntrance {
  build() {
    // 将justifyContent参数配置为FlexAlign.SpaceEvenly实现均分布局
    Row() {
      ForEach(entranceIcons, (icon: AllIcons) = > {
        // 各快捷入口的图标及名称
        Column() { 
          // ... 
          }
      })
    }
    .width('100%')
    .height(64)
    .justifyContent(FlexAlign.SpaceEvenly)
    .padding({ left: 12, right: 12 })
  }
}

精品应用

随着可用显示区域的增加,精品应用中显示的图标数量也不断增加,这是典型的延伸能力使用场景。精品游戏的实现与精品应用类似,不再展开分析。

import { AppItem, MyAppSource } from '../model/HomeDataType';

@Component
export default struct IndexApps {
  private title?: Resource;
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md';
  private apps: AppItem[] = [];
  @Builder
  appListHeader() {
    Row() {
      Text(this.title)
        .width(100)
        .fontSize(16)
        .textAlign(TextAlign.Start)
        .fontWeight(500)
      Blank()
      Text($r('app.string.more'))
        .fontSize(14)
        .textAlign(TextAlign.End)
        .fontWeight(400)
        .margin({ right: 2 })
      Image($r('app.media.ic_public_arrow_right'))
        .width(12)
        .height(18)
        .opacity(0.9)
        .objectFit(ImageFit.Fill)
    }
    .margin({ bottom: 9, top: 9 })
    .width('100%')
    .alignItems(VerticalAlign.Bottom)
  }

  @Builder
  appListItem(app:AppItem) {
    Column() {
      Image(app.image)
        .width(this.currentBreakpoint === 'lg' ? 80 : 56)
        .height(this.currentBreakpoint === 'lg' ? 80 : 56)
        .margin({ bottom: 8 })
      Text(app.title)
        .width(this.currentBreakpoint === 'lg' ? 80 : 56)
        .height(16)
        .fontSize(12)
        .textAlign(TextAlign.Center)
        .fontColor('#18181A')
        .margin({ bottom: 8 })
      Text($r('app.string.install'))
        .width(this.currentBreakpoint === 'lg' ? 80 : 56)
        .height(28)
        .fontColor('#0A59F7')
        .textAlign(TextAlign.Center)
        .borderRadius(this.currentBreakpoint === 'lg' ? 26 : 20)
        .fontWeight(500)
        .fontSize(12)
        .padding({ top: 6, bottom: 6, left: 8, right: 8 })
        .backgroundColor('rgba(0,0,0,0.05)')
    }
  }
  build() {
    Column() {
      this.appListHeader()
      // 借助List组件能力,实现延伸能力场景
      List({ space: this.currentBreakpoint === 'lg' ? 44 : 20}) {
        LazyForEach(new MyAppSource(this.apps), (app: AppItem)= > {
          ListItem() {
            // 每个应用的图标、名称及安装按钮
            this.appListItem(app)
          }
        })
      }
      .width('100%')
      .height(this.currentBreakpoint === 'lg' ? 140 : 120)
      .listDirection(Axis.Horizontal)
    }
    .width('100%')
    .height(this.currentBreakpoint === 'lg' ? 188 : 164)
    .padding({ bottom: 8, left: 12, right: 12 })
  }
}

运行效果

将上述各页面主要部分组合在一起后,即可完成整体页面开发。

import IndexSwiper from './IndexSwiper';
import IndexEntrance from './IndexEntrance';
import IndexApps from './IndexApps';
import { appList, gameList } from '../model/HomeData';
import IndexHeader from './IndexHeader';

@Component
struct IndexContent {
  // ...
  build() {
    List() {
      // 运营横幅
      ListItem() {
        IndexSwiper()
      }
      // 快捷入口
      ListItem() {
        IndexEntrance()
      }
      // 精品应用
      ListItem() {
        IndexApps({ title: $r('app.string.boutique_application'), apps: appList })
      }
      // 精品游戏
      ListItem() {
        IndexApps({ title: $r('app.string.boutique_game'), apps: gameList })
      }
    }
    .width("100%")
  }
}

@Entry
@Component
export default struct Home {
  // ...
  build() {
    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Start }) {
      // 标题栏和搜索栏
      IndexHeader()
      // 运营横幅、快捷入口、精品应用、精品游戏等
      IndexContent()
    }
    .height('100%')
    .backgroundColor("#F1F3F5")
  }
}

`HarmonyOSOpenHarmony鸿蒙文档籽料:mau123789是v直接拿`

搜狗高速浏览器截图20240326151450.png
本页面的实际运行效果如下图所示。

image.png

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 移动开发
    +关注

    关注

    0

    文章

    52

    浏览量

    9437
  • 鸿蒙系统
    +关注

    关注

    183

    文章

    2623

    浏览量

    65460
  • HarmonyOS
    +关注

    关注

    79

    文章

    1910

    浏览量

    29497
  • OpenHarmony
    +关注

    关注

    24

    文章

    3443

    浏览量

    15332
  • 鸿蒙OS
    +关注

    关注

    0

    文章

    186

    浏览量

    4305
收藏 人收藏

    评论

    相关推荐

    HarmonyOS开发案例:【一次开发多端部署-音乐专辑】

    基于自适应和响应式布局,实现一次开发多端部署音乐专辑页面。
    的头像 发表于 05-13 16:48 439次阅读
    HarmonyOS<b class='flag-5'>开发</b>案例:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>-音乐专辑】

    鸿蒙OS开发:【一次开发多端部署】(一多天气)项目

    本示例展示一个天气应用界面,包括首页、城市管理、添加城市、更新时间弹窗,体现一次开发多端部署的能力。
    的头像 发表于 05-20 14:59 430次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(一多天气)项目

    鸿蒙OS开发:【一次开发多端部署】(app市场首页)项目

    本示例展示了应用市场首页,页面中包括Tab栏、运营横幅、精品应用、精品游戏等。
    的头像 发表于 05-21 10:57 369次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(<b class='flag-5'>app</b><b class='flag-5'>市场</b><b class='flag-5'>首页</b>)项目

    鸿蒙OS开发:【一次开发多端部署】(音乐专辑主页)

    本示例使用一次开发多端部署中介绍的自适应布局能力和响应式布局能力进行多设备(或多窗口尺寸)适配,保证应用在不同设备或不同窗口尺寸下可以正常显示。
    的头像 发表于 05-21 14:48 387次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(音乐专辑主页)

    鸿蒙OS开发:【一次开发多端部署】(音乐专辑页面)

    基于自适应和响应式布局,实现一次开发多端部署音乐专辑页面。
    的头像 发表于 05-25 16:21 254次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(音乐专辑页面)

    鸿蒙OS开发:【一次开发多端部署】(视频应用)

    者提供了“一次开发多端部署”的系统能力,让开发者可以基于一次
    的头像 发表于 05-25 16:29 235次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(视频应用)

    鸿蒙OS开发:典型页面场景【一次开发多端部署】实战(应用市场首页

    本示例展示了应用市场首页,页面中包括Tab栏、运营横幅、精品应用、精品游戏等。
    的头像 发表于 05-24 15:21 611次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:典型页面场景【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】实战(应用<b class='flag-5'>市场</b><b class='flag-5'>首页</b>)

    鸿蒙OS开发:典型页面场景【一次开发多端部署】实战(音乐专辑页2)

    本示例使用[一次开发多端部署]中介绍的自适应布局能力和响应式布局能力进行多设备(或多窗口尺寸)适配,保证应用在不同设备或不同窗口尺寸下可以正常显示。
    的头像 发表于 05-25 16:47 1651次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:典型页面场景【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】实战(音乐专辑页2)

    鸿蒙OS开发:典型页面场景【一次开发多端部署】实战(设置典型页面)

    本示例展示了设置应用的典型页面,其在小窗口和大窗口有不同的显示效果,体现一次开发多端部署的能力。
    的头像 发表于 05-27 09:36 535次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:典型页面场景【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】实战(设置典型页面)

    Happ开发后,如何实现多端部署

    做出来后,怎么烧录到它上面?说好的“一次开发多端部署”2、DevEco Studio 开发出来的Happ,它能不能安装到 android的
    发表于 09-10 21:42

    HarmonyOS\"一次开发多端部署\"优秀实践——玩机技巧,码上起航

    的潜在用户群体。个应用要在多类设备上提供统的内容,需要适配不同的屏幕尺寸和硬件,开发成本较高。\"一次开发
    发表于 08-30 18:14

    华为开发者大会2021:一次开发 多端部署

    一次开发 多端部署使能开发者从单设备生态跨入多设备生态!
    的头像 发表于 10-22 15:09 1440次阅读
    华为<b class='flag-5'>开发</b>者大会2021:<b class='flag-5'>一次</b><b class='flag-5'>开发</b> <b class='flag-5'>多端</b><b class='flag-5'>部署</b>

    华为开发者大会2021:软件部总裁龚体 鸿蒙系统 一次开发 多端部署 万物互连

    华为开发者大会2021:鸿蒙系统 一次开发 多端部署 万物互连 在华为
    的头像 发表于 10-22 15:09 4163次阅读
    华为<b class='flag-5'>开发</b>者大会2021:软件部总裁龚体 <b class='flag-5'>鸿蒙</b>系统 <b class='flag-5'>一次</b><b class='flag-5'>开发</b> <b class='flag-5'>多端</b><b class='flag-5'>部署</b> 万物互连

    鸿蒙OS开发:【一次开发多端部署】(多设备自适应能力)简单介绍

    本示例是《一次开发多端部署》的配套示例代码,展示了[页面开发的一多能力],包括自适应布局、响应式布局、典型布局场景以及资源文件使用。
    的头像 发表于 05-21 14:59 205次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(多设备自适应能力)简单介绍

    鸿蒙OS开发:【一次开发多端部署】( 设置app页面)

    本示例展示了设置应用的典型页面,其在小窗口和大窗口有不同的显示效果,体现一次开发多端部署的能力。
    的头像 发表于 05-21 14:56 212次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>:【<b class='flag-5'>一次</b><b class='flag-5'>开发</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】( 设置<b class='flag-5'>app</b>页面)