请教一下关于应用分栏实现

应用分栏实现

HarmonyOS
2024-06-11 20:34:43
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
NGKSWCIDT

1、分栏场景分析

1.1 为什么要分栏

折叠屏展开,平板等屏幕较大的设备,如果还是按照手机布局展示内容,会显得页面太宽,内容太分散,不够美观,此时如果页面能够分左右两块,左边作为导航区,右侧作为内容区,体验会更佳。

1.2 分栏和未分栏效果对比

如果想直接分栏,可以设置mode属性为Split;如果不想分栏,可以设置为Stack;如果想让组件自动识别是否分栏,可以设置为Auto。 推荐使用Auto,这样应用不需要做过多分栏触发时机的识别。

1.3 分栏的场景

屏幕较大的设备,如平板、折叠屏展开、pc、车机大屏等,需要让页面内容更丰富,更方便操作。

左侧作为导航区域,右侧作为内容区域,操作方便。

2、分栏实践

2.1 左侧导航栏

导航栏作为应用一级页面,需要包在Navigation组件内:

@Entry 
@Component 
struct MainEntry { 
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack(); 
  build() {     Navigation(this.pageInfos) { 
    // 内容区,示例item 
    Row() { 
      if (this.info.icon) { 
        Image(this.info.icon) 
          .aspectRatio(1) 
          .width($r('app.float.common_size24')) 
          .borderRadius($r('app.float.common_size4')) 
          .alignSelf(ItemAlign.Center) 
          .margin({ right: $r('app.float.common_margin12') }) 
          .draggable(false) 
          .interpolation(ImageInterpolation.High) 
      } 
      Column() { 
        Text(this.info.title) 
          .fontSize($r('app.float.common_font_size16')) 
          .fontColor($r('app.color.black')) 
          .fontWeight(FontWeight.Medium) 
        Progress({ value: this.progress(), style: ProgressStyle.Linear }) 
          .width($r('app.float.common_size80')) 
          .margin({ top: $r('app.float.common_margin8') }) 
      }.justifyContent(FlexAlign.Center) 
      .alignItems(HorizontalAlign.Start) 
 
      Flex({ justifyContent: FlexAlign.End }) { 
        Text(renderSize(this.free, Constant.BYTE.STORAGE_KB) + ' ' + this.available + '/' + renderSize(this.total, Constant.BYTE.STORAGE_KB)) 
          .fontSize($r('app.float.common_font_size14')) 
          .fontColor($r('app.color.mine_title_font_color')) 
          .opacity($r('app.float.common_opacity6')) 
          .margin({ right: $r('app.float.common_margin2') }) 
          .textOverflow({ overflow: TextOverflow.Ellipsis }) 
          .textAlign(TextAlign.End) 
      } 
    }.layoutWeight(1) 
    .padding({ left: $r('app.float.common_padding8') }) 
 
    Image($r('app.media.ic_arrow_right')) 
      .objectFit(ImageFit.Contain) 
      .renderMode(ImageRenderMode.Original) 
      .aspectRatio(1) 
      .width($r('app.float.common_size12')) 
      .height($r('app.float.common_size24')) 
      .draggable(false) 
      .interpolation(ImageInterpolation.High) 
  } 
  .width('100%') 
  .height($r('app.float.common_size56')) 
  .padding({ 
    left: $r('app.float.common_padding12'), 
    right: $r('app.float.common_padding12') 
  }) 
  .stateStyles({ 
    pressed: pressedStyles, 
    normal: normalStyles 
  }) 
  .onClick(() => { 
    if (this.info.pageUri) { 
      this.pageInfos.clear(); 
      let params: StorageDeviceParamData = { 
        rootUri: this.info.rootUri, 
        title: this.info.title, 
        uuid: this.info.uuid, 
        deviceType: this.info.deviceType 
      }; 
      this.pageInfos.pushPath(new NavPathInfo('myPhone', params)); 
    } 
  }) 
  } 
  .backgroundColor($r('app.color.hicloud_hmos_bg')) 
  .navDestination(this.pageMap) 
  .mode(NavigationMode.Split) 
  .navBarWidth($r('app.float.common_size295')) 
  .hideTitleBar(true) 
  .onNavBarStateChange((isVisible: boolean) => { 
  if (isVisible) { 
    UiUtil.setWindowBackground(SYSTEM_BAR_COLOR.LIGHT_GRAY); 
    this.onPageShow(); 
  } else { 
  this.isRecentPageShow = false; 
} 
}) }

2.2 导航栏右侧内容区

分栏右侧内容区是导航栏的子页面,需要包在NavDestination组件内:

注意点:内容区组件不需要用@Entry修饰,build时需要包在NavDestination内。

@Component 
export struct MyPhone { 
  build() { 
    NavDestination() { 
      // 内容区 
    } 
    .onBackPressed(() => {       return this.onBackPress(); 
    }) 
    .backgroundColor($r('app.color.hicloud_hmos_bg')) 
    .hideTitleBar(true) 
    .onShown(() => this.onPageShow()) 
    .onHidden(() => this.onPageHide()) 
    .width('100%') 
    .height('100%') 
    .expandSafeArea([SafeAreaType.KEYBOARD]) 
  } 
}

2.3 关联导航栏和内容区

即导航栏区域点击某个item,右侧需要显示对应内容区

首先2.1章节Navigation的navDestination需要设置子页面的映射关系,根据name去匹配加载不同的子页面。

定义this.pageMap,2.1章节有用到:

@Builder 
pageMap(name: string, params: Object) { 
  if (name === 'MyPhone') { 
    MyPhone({ pageParams: params }); 
  } 
}

导航栏item点击后触发的事件在2.1章节代码onClick事件内,即往pageInfos栈内push子页面,这样就可以在右侧显示。

2.4 demo验证

为了方便理解,写了个简易demo(和业务代码有区别)把上面三步串起来:

@Entry 
@Component 
struct MainEntryTest { 
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack(); 
     onPageShow() {   
  }   
  onPageHide() {   
  }   
  build() { 
    Navigation(this.pageInfos) { 
     Row() { 
     Column() { 
       Text('内部存储') 
       .fontSize('20fp') 
       .fontColor('#000000') 
       .fontWeight(FontWeight.Medium) 
     } 
      .alignItems(HorizontalAlign.Start) 
    } 
    .padding({ left: '36vp',right: '24vp', top: '12vp'}) 
    .width('100%') 
    .height('56vp') 
    .onClick(() => { 
      let params: Record<string, string> = { 
       'rootUri': '' 
     }; 
      this.pageInfos.pushPath(new NavPathInfo('MyPhone', params)); 
    }) 
    }     .backgroundColor('#F1F3F5') 
    .navDestination(this.pageMap) 
    .mode(NavigationMode.Split) 
    .navBarWidth('295vp') 
    .title('浏览') 
    .titleMode(NavigationTitleMode.Mini) 
    .hideBackButton(true) 
    .onNavBarStateChange((isVisible: boolean) => { 
     if (isVisible) { 
     this.onPageShow(); 
    } 
   }) 
  }   
   
  @Builder   pageMap(name: string, params: Object) { 
    if (name === 'MyPhone') { 
    MyPhoneTest({ pageParams: params }); 
    } 
  } 
}   
@Component 
export struct MyPhoneTest { 
  @Consume('pageInfos') pageInfos: NavPathStack; 
  private pageParams: Object = new Object(); 
     onPageHide() { 
  } 
  onPageShow() { 
  }   
  build() { 
    NavDestination() { 
    Text('内容区') 
     .fontSize('40fp') 
    } 
    .onBackPressed(() => { 
     this.pageInfos.pop(); 
      return true; 
    }) 
    .backgroundColor('#F1F3F5') 
    .title('我的手机') 
    .onShown(() => this.onPageShow()) 
    .onHidden(() => this.onPageHide()) 
    .width('100%') 
    .height('100%') 
  } 
}

Demo效果:

分享
微博
QQ
微信
回复
2024-06-12 17:30:02
相关问题
请教一下关于Ticktimer 的疑问?
1923浏览 • 1回复 待解决
请教一下如何实现函数的重载
230浏览 • 1回复 待解决
请教一下如何开关闪光灯
160浏览 • 1回复 待解决
谁分享一下如何实现匿名内部类
249浏览 • 0回复 待解决
请问一下鸿蒙的pad应用该如何签名?
6658浏览 • 1回复 待解决
ob有如何报错,麻烦帮忙看一下
3255浏览 • 1回复 待解决
关于liteos-a的些问题想请教各位
7070浏览 • 2回复 待解决
请问一下tab按钮组切换效果
411浏览 • 1回复 待解决
编译OpenHarmony2.0失败,求助一下
7482浏览 • 3回复 已解决
想了解一下MD5算法示例。
299浏览 • 1回复 待解决
分享一下你的鸿蒙系统使用感受吧
2743浏览 • 1回复 待解决