OpenHarmony实战开发-如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。

567 篇文章 1 订阅
555 篇文章 0 订阅

本小节以“设置”应用页面为例,介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。

页面设计

为充分利用屏幕尺寸优势,应用常常有在小屏设备上单栏显示,大屏设备上左右分两栏显示的设计,设置应用页面设计如下。

在这里插入图片描述

观察“设置”应用页面设计,不同断点下“设置主页”、“WLAN页面”和“更多WLAN设置页面”几乎完全一致,只是在sm断点下采用单栏显示,在md和lg断点下采用双栏显示。

在前面的典型页面场景中,已经介绍了如何分析及实现不同断点下设计相似的单个页面,本小节将展开介绍如何实现不同断点下存在单栏和双栏设计的场景。

为了方便读者理解,本小节将围绕以下三个问题进行介绍。

  1. 如何实现单/双栏的显示效果
  2. 如何实现点击跳转或刷新
  3. 如何实现多级跳转

如何实现单/双栏的显示效果

开发者可以使用Row、Column、RowSplit等基础的组件,实现分栏显示的效果,但是需要较多的开发工作量。方舟开发框架在API 9重构了Navigation组件,开发者可以通过配置Navigation组件的属性,控制其按照单栏或双栏的效果进行显示。

Navigation组件由Navbar和Content两部分区域组成,Navigation组件支持Stack、Split以及Auto三种模式。Stack及Split模式下Navigation组件的表现如下图所示。

  • Stack模式
    在这里插入图片描述
  • Split模式
    在这里插入图片描述
  • Auto模式

Auto模式是指Navigation组件可以根据应用窗口尺寸,自动选择合适的模式:窗口宽度小于520vp时,采用Stack模式显示;窗口宽度大于等于520vp时,采用Split模式显示。当窗口尺寸发生改变时,Navigation组件也会自动在Stack模式和Split模式之间切换。

说明:

Navigation组件提供的title、navBarWidth、navBarPosition等属性来调整其显示效果。Navigation组件样式的配置与其它组件类似,这里不做赘述。
首次加载Navigation组件所在的页面时,如果Navigation组件处于Split模式,Navigation组件会自动激活其第一个NavRouter孩子节点(后文会展开介绍NavRouter)来刷新Content区域的显示。
设置主页的核心代码如下所示。Navigation组件默认处于Auto模式,其样式会根据应用窗口尺寸在单栏和双栏之间自动切换。

import { SettingList } from '@ohos/settingItems';

@Entry
@Component
struct Index { 
  build() {
    Navigation() {
      SettingList()
    }
    .title($r('app.string.settings'))
    .navBarWidth('40%')
    .width('100%')
    .height('100%')
    .backgroundColor($r("sys.color.ohos_id_color_sub_background"))
  }
}
//核心代码 SettingList.ets
import { MainItem } from '../components/MainItem';
import { ItemGroup } from '../components/ItemGroup';
import { SearchBox } from '../components/SearchBox';
import { MoreConnectionsItem } from '../moreconnections/MoreConnectionsItem';
import { WlanSettingItem } from '../wlan/WlanSettingItem';
        
class  ItemObj {
  title?: Resource
  tag?: Resource
  icon?:Resource
}
let bluetoothTab:ItemObj={
  title: $r('app.string.bluetoothTab'),
  tag: $r('app.string.enabled'),
  icon: $r('app.media.blueTooth'),
}
let mobileData:ItemObj={
  title: $r('app.string.mobileData'),
  icon: $r('app.media.mobileData'),
}
let brightnessTab:ItemObj={
  title: $r('app.string.brightnessTab'),
  icon: $r('app.media.displayAndBrightness'),
}
let volumeControlTab:ItemObj={
  title: $r('app.string.volumeControlTab'),
  icon: $r('app.media.volume'),
}
let biometricsAndPassword:ItemObj={
  title: $r('app.string.biometricsAndPassword'),
  icon: $r('app.media.biometricsAndPassword'),
}
let applyTab:ItemObj={
  title: $r('app.string.applyTab'),
  icon: $r('app.media.application'),
}
let storageTab:ItemObj={
  title: $r('app.string.storageTab'),
  icon: $r('app.media.storage'),
}
let security:ItemObj={
  title: $r('app.string.security'),
  icon: $r('app.media.security'),
}
let privacy:ItemObj={
  title: $r('app.string.privacy'),
  icon: $r('app.media.privacy'),
}
let usersAccountsTab:ItemObj={
  title: $r('app.string.usersAccountsTab'),
  icon: $r('app.media.userAccounts'),
}
let systemTab:ItemObj={
  title: $r('app.string.systemTab'),
  icon: $r('app.media.system'),
}
let aboutTab:ItemObj={
  title: $r('app.string.aboutTab'),
  icon: $r('app.media.aboutDevice'),
}
        
@Component
export struct SettingList {
  @Builder
  CustomDivider() {
    Divider()
      .strokeWidth('1px')
      .color($r('sys.color.ohos_id_color_list_separator'))
      .margin({ left: 48, right: 8 })
  }

   build() {
     List({ space: 12 }) {
       ListItem() {
        SearchBox()
       }
       .padding({ top: 8, bottom: 8 })
       .width('100%')

      ListItem() {
        ItemGroup() {
          WlanSettingItem()

          this.CustomDivider()

          MainItem(bluetoothTab)

          this.CustomDivider()

          MainItem(mobileData)

          this.CustomDivider()
          MoreConnectionsItem()
        }
      }

      ListItem() {
        ItemGroup() {
          MainItem(brightnessTab)
        }
      }

      ListItem() {
        ItemGroup() {
          MainItem(volumeControlTab)
        }
      }

      ListItem() {
        ItemGroup() {
          MainItem(biometricsAndPassword)

          this.CustomDivider()

          MainItem(applyTab)

          this.CustomDivider()

          MainItem(storageTab)

          this.CustomDivider()

          MainItem(security)

          this.CustomDivider()

          MainItem(privacy)
        }
      }

      ListItem() {
        ItemGroup() {
          MainItem(usersAccountsTab)

          this.CustomDivider()

          MainItem(systemTab)

          this.CustomDivider()

          MainItem(aboutTab)
        }
      }

    }
    .padding({ left: 12, right: 12 })
    .width('100%')
    .height('100%')
    .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
   }
}        
  

如何实现点击跳转或刷新

Navigation组件通常搭配NavRouter组件以及NavDestination组件一起使用:

  • NavRouter组件用于控制Navigation组件Content区域的显示和刷新逻辑。
  • NavDestination组件用于实际刷新Navigation组件Content区域的显示。

刷新控制
NavRouter组件用于控制Navigation组件中Content区域的刷新逻辑,其必须包含两个孩子节点。
在这里插入图片描述

NavRouter组件默认提供了点击响应处理,不需要开发者自定义点击事件逻辑。另外,NavRouter组件还提供了onStateChange回调事件,用于通知开发者NavRouter的状态:用户点击NavRouter,激活NavRouter并加载对应的NavDestination子组件时,回调onStateChange(true);NavRouter对应的NavDestination子组件不再显示时,回调onStateChange(false)。

img

结合设置应用的具体场景来看,上图1号小红框是NavRouter的第一个孩子节点,2号红框是NavRouter的第二个孩子节点,相应的核心代码实现如下。

import { MainItem } from '../components/MainItem';
import { WlanMoreSettingItem } from '../components/WlanMoreSettingItem';
import { SubItemToggle } from '../components/SubItemToggle';
import { SubItemWifi } from '../components/SubItemWifi';
import { ItemDescription } from '../components/ItemDescription';
import { ItemGroup } from '../components/ItemGroup';

class  MainItemObj {
  title?: Resource
  tag?: string
  icon?:Resource
  label?: string
}
let mainItem:MainItemObj={
  title: $r('app.string.wifiTab'),
  tag: 'UX',
  icon: $r('app.media.wlan'),
  label: 'WLAN'
}
@Component
export struct WlanSettingItem {
  @LocalStorageLink('selectedLabel') selectedLabel: string  = ''

  build() {
    Column() {
      NavRouter() {
        MainItem(mainItem)

        NavDestination() {
          WlanSetting()
        }
        .title($r('app.string.wifiTab'))
        .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
      }
    }
  }
}
@Component
struct WlanSetting {
  @Builder CustomDivider() {
    Divider()
      .strokeWidth('1px')
      .color($r('sys.color.ohos_id_color_list_separator'))
      .margin({left: 12, right: 8})
  }

  build() {
    Column() {
      Column() {
        ItemGroup() {
          SubItemToggle({title: $r('app.string.wifiTab'), isOn: true})
        }

        Row().height(16)

        ItemGroup() {
          WlanMoreSettingItem()
        }
      }
      .margin({bottom: 19.5})
      .flexShrink(0)

      Scroll() {
        Column() {
          ItemDescription({description: $r('app.string.wifiTipConnectedWLAN')})
            .padding({
              left: 12,
              right: 12,
              bottom: 9.5
            })

          ItemGroup() {
            SubItemWifi({
              title: 'UX',
              subTitle: $r('app.string.wifiSummaryConnected'),
              isConnected: true,
              icon: $r('app.media.ic_wifi_signal_4_dark')
            })
          }

          Column() {
            ItemDescription({description: $r('app.string.wifiTipValidWLAN')})
              .margin({
                left: 12,
                right: 12,
                top: 19.5,
                bottom: 9.5
              })

            ItemGroup() {
              SubItemWifi({
                title: 'Huwe-yee',
                subTitle: $r('app.string.wifiSummaryEncrypted'),
                isConnected: false,
                icon: $r('app.media.ic_wifi_lock_signal_4_dark')
              })

              this.CustomDivider()

              SubItemWifi({
                title: 'UX-5G',
                subTitle: $r('app.string.wifiSummaryOpen'),
                isConnected: false,
                icon: $r('app.media.ic_wifi_signal_4_dark')
              })

              this.CustomDivider()

              SubItemWifi({
                title: 'E1-AP',
                subTitle: $r('app.string.wifiSummarySaveOpen'),
                isConnected: false,
                icon: $r('app.media.ic_wifi_signal_4_dark')
              })
            }
          }
        }
      }
      .scrollable(ScrollDirection.Vertical)
      .scrollBar(BarState.Off)
      .width('100%')
      .flexShrink(1)
    }
    .width('100%')
    .height('100%')
    .padding({left: 12, right: 12})
  }
}

显示刷新
NavDestination组件用于实际刷新Navigation组件Content区域的显示。激活后的NavRouter对应的NavDestination组件,会占满整个Content区域并刷新其显示。

开发者可以通过NavDestination组件提供的如下属性,调整其最终显示效果:

  • backgroundColor:设置NavDestination组件的背景色。
  • title:自定义NavDestination组件的标题。
  • hideTitleBar:隐藏NavDestination组件的标题栏。

特别的,Navigation组件会根据当前的状态决定是否在NavDestination组件标题栏起始部分自动添加返回键图标。当Navigation组件添加了返回键图标时,还可以自动响应及处理系统三键导航中的返回键事件。

在这里插入图片描述

如何实现多级跳转
可以在NavDesination组件中,继续使用NavRouter组件,以实现多级跳转。多级跳转场景下,Navigation组件同样会根据当前的状态决定是否自动添加返回键图标及响应系统三键导航中的返回键事件。

一级页面	二级页面

结合具体场景,红框3是一个NavRouter组件,点击后可以控制Navigation组件中的Content区域刷新为红框4对应的NavDestination组件吗,其核心代码实现如下所示。

import { SubItemArrow } from '../components/SubItemArrow';//组件请参考相关示例
import { SubItemToggle } from '../components/SubItemToggle';
import { ItemGroup } from '../components/ItemGroup';
import { ItemDescription } from '../components/ItemDescription';

class SubItemArrowObj{
  title?: Resource
}
let subItemArrow:SubItemArrowObj={
  title: $r('app.string.moreWlanSettings')
}
@Component
export struct WlanMoreSettingItem {
  @LocalStorageLink('selectedLabel') selectedLabel: string = ''

  build() {
    NavRouter() {
      SubItemArrow(subItemArrow)

      NavDestination() {
        WlanMoreSetting()
      }
      .title($r('app.string.moreWlanSettings'))
      .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
    }
  }
}

@Component
export struct WlanMoreSetting {
  build() {
    Scroll() {
      Column() {
        ItemGroup() {
          SubItemArrow({
            title: $r('app.string.wlanPlus'),
            tag: $r('app.string.enabled')
          })
        }
        ItemDescription({description: $r('app.string.wlanPlusTip')})
          .margin({
            top: 8,
            bottom: 24,
            left: 12,
            right: 12
          })

        ItemGroup() {
          SubItemArrow({ title: $r('app.string.wlanDirect') })
        }

        Blank().height(12)

        ItemGroup() {
          SubItemToggle({title: $r('app.string.wlanSecurityCheck')})
        }

        ItemDescription({description: $r('app.string.wlanSecurityCheckTip')})
          .margin({
            top: 8,
            bottom: 24,
            left: 12,
            right: 12
          })

        ItemGroup() {
          SubItemArrow({title: $r('app.string.savedWlan')})
          Divider()
            .strokeWidth('1px')
            .color($r('sys.color.ohos_id_color_list_separator'))
            .margin({left: 12, right: 8})
          SubItemArrow({title: $r('app.string.installCertificates')})
        }
      }
      .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
      .padding({left: 12, right: 12})
    }
    .scrollBar(BarState.Off)
    .width('100%')
  }
}

总结

在这里插入图片描述

本示例的基础导航结构上图所示:

  • 激活SettingList中的WLANSettingItem,可以加载及显示WlanSetting。
  • 激活WlanSetting中的WlanMoreSettingItem,可以加载及显示WlanMoreSetting。

Navigation组件支持自动切换单栏和双栏的显示效果,同时可以根据当前状态自动添加返回键及响应系统的返回键事件。借助Navigation组件,开发者不用关心单栏和双栏场景的差异而更关注于应用本身,极大的减少开发工作量及提高开发效率。

如果大家还没有掌握鸿蒙,现在想要在最短的时间里吃透它,我这边特意整理了《鸿蒙语法ArkTS、TypeScript、ArkUI、相关教学视频》以及《鸿蒙生态应用开发白皮书V2.0PDF》《鸿蒙开发学习手册》(共计890页)鸿蒙开发资料等…希望对大家有所帮助:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

OpenHarmony APP开发教程步骤:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

鸿蒙生态应用开发白皮书V2.0PDF:https://docs.qq.com/doc/DZVVkRGRUd3pHSnFG

在这里插入图片描述

南北双向高工技能基础:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

应用开发中高级就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

全网首发-工业级 南向设备开发就业技术:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

《鸿蒙开发学习手册》:

如何快速入门:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.基本概念
2.构建第一个ArkTS应用
3.……

在这里插入图片描述

开发基础知识:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值