RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(典型布局場(chǎng)景)

jf_46214456 ? 來(lái)源:jf_46214456 ? 作者:jf_46214456 ? 2024-05-25 16:39 ? 次閱讀

典型布局場(chǎng)景

雖然不同應(yīng)用的頁(yè)面千變?nèi)f化,但對(duì)其進(jìn)行拆分和分析,頁(yè)面中的很多布局場(chǎng)景是相似的。本小節(jié)將介紹如何借助自適應(yīng)布局、響應(yīng)式布局以及常見(jiàn)的容器類(lèi)組件,實(shí)現(xiàn)應(yīng)用中的典型布局場(chǎng)景。

布局場(chǎng)景實(shí)現(xiàn)方案 開(kāi)發(fā)前請(qǐng)熟悉鴻蒙開(kāi)發(fā)指導(dǎo)文檔:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md點(diǎn)擊或者復(fù)制轉(zhuǎn)到。
[頁(yè)簽欄]Tab組件 + 響應(yīng)式布局
[運(yùn)營(yíng)橫幅(Banner)]Swiper組件 + 響應(yīng)式布局
[網(wǎng)格]Grid組件 / List組件 + 響應(yīng)式布局
[側(cè)邊欄]SideBar組件 + 響應(yīng)式布局
[單/雙欄]Navigation組件 + 響應(yīng)式布局
[三分欄]SideBar組件 + Navigation組件 + 響應(yīng)式布局
[自定義彈窗]CustomDialogController組件 + 響應(yīng)式布局
[大圖瀏覽]Image組件
[操作入口]Scroll組件+Row組件橫向均分
[頂部]柵格組件
[縮進(jìn)布局]柵格組件
[挪移布局]柵格組件
[重復(fù)布局]柵格組件

說(shuō)明: 在本文[媒體查詢(xún)]小節(jié)中已經(jīng)介紹了如何通過(guò)媒體查詢(xún)監(jiān)聽(tīng)斷點(diǎn)變化,后續(xù)的示例中不再重復(fù)介紹此部分代碼。

頁(yè)簽欄

image.png
布局效果

實(shí)現(xiàn)方案

不同斷點(diǎn)下,頁(yè)簽在頁(yè)面中的位置及尺寸都有差異,可以結(jié)合響應(yīng)式布局能力,設(shè)置不同斷點(diǎn)下[Tab組件]的barPosition、vertical、barWidth和barHeight屬性實(shí)現(xiàn)目標(biāo)效果。

另外,頁(yè)簽欄中的文字和圖片的相對(duì)位置不同,同樣可以通過(guò)設(shè)置不同斷點(diǎn)下[tabBar]對(duì)應(yīng)的CustomBuilder中的布局方向,實(shí)現(xiàn)目標(biāo)效果。

參考代碼

import { BreakpointSystem, BreakPointType } from '../common/breakpointsystem'

interface TabBar  {
  name: string
  icon: Resource
  selectIcon: Resource
}

@Entry
@Component
struct Home {
  @State currentIndex: number = 0
  @State tabs: Array< TabBar > = [{
                                  name: '首頁(yè)',
                                  icon: $r('app.media.ic_music_home'),
                                  selectIcon: $r('app.media.ic_music_home_selected')
                                }, {
                                  name: '排行榜',
                                  icon: $r('app.media.ic_music_ranking'),
                                  selectIcon: $r('app.media.ic_music_ranking_selected')
                                }, {
                                  name: '我的',
                                  icon: $r('app.media.ic_music_me_nor'),
                                  selectIcon: $r('app.media.ic_music_me_selected')
                                }]

  @Builder TabBarBuilder(index: number, tabBar: TabBar) {
    Flex({
      direction: new BreakPointType({
        sm: FlexDirection.Column,
        md: FlexDirection.Row,
        lg: FlexDirection.Column
      }).getValue(this.currentBreakpoint),
      justifyContent: FlexAlign.Center,
      alignItems: ItemAlign.Center
    }) {
      Image(this.currentIndex === index ? tabBar.selectIcon : tabBar.icon)
        .size({ width: 36, height: 36 })
      Text(tabBar.name)
        .fontColor(this.currentIndex === index ? '#FF1948' : '#999')
        .margin(new BreakPointType< (Length|Padding) >({
          sm: { top: 4 },
          md: { left: 8 },
          lg: { top: 4 } }).getValue(this.currentBreakpoint)!)
        .fontSize(16)
    }
    .width('100%')
    .height('100%')
  }

  @StorageLink('currentBreakpoint') currentBreakpoint: string = 'md'
  private breakpointSystem: BreakpointSystem = new BreakpointSystem()

  aboutToAppear() {
    this.breakpointSystem.register()
  }

  aboutToDisappear() {
    this.breakpointSystem.unregister()
  }

  build() {
    Tabs({
      barPosition: new BreakPointType({
        sm: BarPosition.End,
        md: BarPosition.End,
        lg: BarPosition.Start
      }).getValue(this.currentBreakpoint)
    }) {
      ForEach(this.tabs, (item:TabBar, index) = > {
        TabContent() {
          Stack() {
            Text(item.name).fontSize(30)
          }.width('100%').height('100%')
        }.tabBar(this.TabBarBuilder(index!, item))
      })
    }
    .vertical(new BreakPointType({ sm: false, md: false, lg: true }).getValue(this.currentBreakpoint)!)
    .barWidth(new BreakPointType({ sm: '100%', md: '100%', lg: '96vp' }).getValue(this.currentBreakpoint)!)
    .barHeight(new BreakPointType({ sm: '72vp', md: '56vp', lg: '60%' }).getValue(this.currentBreakpoint)!)
    .animationDuration(0)
    .onChange((index: number) = > {
      this.currentIndex = index
    })
  }
}

運(yùn)營(yíng)橫幅(Banner)

image.png
布局效果

實(shí)現(xiàn)方案

運(yùn)營(yíng)橫幅通常使用[Swiper組件]實(shí)現(xiàn)。不同斷點(diǎn)下,運(yùn)營(yíng)橫幅中展示的圖片數(shù)量不同。只需要結(jié)合響應(yīng)式布局,配置不同斷點(diǎn)下Swiper組件的displayCount屬性,即可實(shí)現(xiàn)目標(biāo)效果。

參考代碼

import { BreakpointSystem, BreakPointType } from '../common/breakpointsystem'

@Entry
@Component
export default struct Banner {
  private data: Array< Resource > = [
    $r('app.media.banner1'),
    $r('app.media.banner2'),
    $r('app.media.banner3'),
    $r('app.media.banner4'),
    $r('app.media.banner5'),
    $r('app.media.banner6'),
  ]
  private breakpointSystem: BreakpointSystem = new BreakpointSystem()
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'

  aboutToAppear() {
    this.breakpointSystem.register()
  }

  aboutToDisappear() {
    this.breakpointSystem.unregister()
  }

  build() {
    Swiper() {
      ForEach(this.data, (item:Resource) = > {
        Image(item)
          .size({ width: '100%', height: 200 })
          .borderRadius(12)
          .padding(8)
      })
    }
    .indicator(new BreakPointType({ sm: true, md: false, lg: false }).getValue(this.currentBreakpoint)!)
    .displayCount(new BreakPointType({ sm: 1, md: 2, lg: 3 }).getValue(this.currentBreakpoint)!)
  }
}

網(wǎng)格

image.png
布局效果

實(shí)現(xiàn)方案

不同斷點(diǎn)下,頁(yè)面中圖片的排布不同,此場(chǎng)景可以通過(guò)響應(yīng)式布局能力結(jié)合[Grid組件]實(shí)現(xiàn),通過(guò)調(diào)整不同斷點(diǎn)下的Grid組件的columnsTemplate屬性即可實(shí)現(xiàn)目標(biāo)效果。

另外,由于本例中各列的寬度相同,也可以通過(guò)響應(yīng)式布局能力結(jié)合[List組件]實(shí)現(xiàn),通過(guò)調(diào)整不同斷點(diǎn)下的List組件的lanes屬性也可實(shí)現(xiàn)目標(biāo)效果。

參考代碼

通過(guò)Grid組件實(shí)現(xiàn)

import { BreakpointSystem, BreakPointType } from '../common/breakpointsystem'

interface GridItemInfo {
  name: string
  image: Resource
}

@Entry
@Component
struct MultiLaneList {
  private data: GridItemInfo[] = [
    { name: '歌單集合1', image: $r('app.media.1') },
    { name: '歌單集合2', image: $r('app.media.2') },
    { name: '歌單集合3', image: $r('app.media.3') },
    { name: '歌單集合4', image: $r('app.media.4') },
    { name: '歌單集合5', image: $r('app.media.5') },
    { name: '歌單集合6', image: $r('app.media.6') },
    { name: '歌單集合7', image: $r('app.media.7') },
    { name: '歌單集合8', image: $r('app.media.8') },
    { name: '歌單集合9', image: $r('app.media.9') },
    { name: '歌單集合10', image: $r('app.media.10') },
    { name: '歌單集合11', image: $r('app.media.11') },
    { name: '歌單集合12', image: $r('app.media.12') }
  ]
  private breakpointSystem: BreakpointSystem = new BreakpointSystem()
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'

  aboutToAppear() {
    this.breakpointSystem.register()
  }

  aboutToDisappear() {
    this.breakpointSystem.unregister()
  }

  build() {
    Grid() {
      ForEach(this.data, (item: GridItemInfo) = > {
        GridItem() {
          Column() {
            Image(item.image)
              .aspectRatio(1.8)
            Text(item.name)
              .margin({ top: 8 })
              .fontSize(20)
          }.padding(4)
        }
      })
    }
    .columnsTemplate(new BreakPointType({
      sm: '1fr 1fr',
      md: '1fr 1fr 1fr 1fr',
      lg: '1fr 1fr 1fr 1fr 1fr 1fr'
    }).getValue(this.currentBreakpoint)!)
  }
}

通過(guò)List組件實(shí)現(xiàn)

import { BreakpointSystem, BreakPointType } from '../common/breakpointsystem'

interface ListItemInfo {
  name: string
  image: Resource
}

@Entry
@Component
struct MultiLaneList {
  private data: ListItemInfo[] = [
    { name: '歌單集合1', image: $r('app.media.1') },
    { name: '歌單集合2', image: $r('app.media.2') },
    { name: '歌單集合3', image: $r('app.media.3') },
    { name: '歌單集合4', image: $r('app.media.4') },
    { name: '歌單集合5', image: $r('app.media.5') },
    { name: '歌單集合6', image: $r('app.media.6') },
    { name: '歌單集合7', image: $r('app.media.7') },
    { name: '歌單集合8', image: $r('app.media.8') },
    { name: '歌單集合9', image: $r('app.media.9') },
    { name: '歌單集合10', image: $r('app.media.10') },
    { name: '歌單集合11', image: $r('app.media.11') },
    { name: '歌單集合12', image: $r('app.media.12') }
  ]
  private breakpointSystem: BreakpointSystem = new BreakpointSystem()
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'

  aboutToAppear() {
    this.breakpointSystem.register()
  }

  aboutToDisappear() {
    this.breakpointSystem.unregister()
  }

  build() {
    List() {
      ForEach(this.data, (item: ListItemInfo) = > {
        ListItem() {
          Column() {
            Image(item.image)
            Text(item.name)
              .margin({ top: 8 })
              .fontSize(20)
          }.padding(4)
        }
      })
    }
    .lanes(new BreakPointType({ sm: 2, md: 4, lg: 6 }).getValue(this.currentBreakpoint)!)
    .width('100%')
  }
}

側(cè)邊欄

布局效果

image.png

實(shí)現(xiàn)方案

側(cè)邊欄通常通過(guò)[SideBarContainer組件]實(shí)現(xiàn),結(jié)合響應(yīng)式布局能力,在不同斷點(diǎn)下為SideBarConContainer組件的sideBarWidth、showControlButton等屬性配置不同的值,即可實(shí)現(xiàn)目標(biāo)效果。

參考代碼

import { BreakpointSystem, BreakPointType } from '../common/breakpointsystem'

interface imagesInfo{
  label:string,
  imageSrc:Resource
}
const images:imagesInfo[]=[
  {
    label:'moon',
    imageSrc:$r('app.media.my_image_moon')
  },
  {
    label:'sun',
    imageSrc:$r('app.media.my_image')
  }
]

@Entry
@Component
struct SideBarSample {
  @StorageLink('currentBreakpoint') private currentBreakpoint: string = "md";
  private breakpointSystem: BreakpointSystem = new BreakpointSystem()
  @State selectIndex: number = 0;
  @State showSideBar:boolean=false;

  aboutToAppear() {
    this.breakpointSystem.register() 
  }

  aboutToDisappear() {
    this.breakpointSystem.unregister()
  }

  @Builder itemBuilder(index: number) {
    Text(images[index].label)
      .fontSize(24)
      .fontWeight(FontWeight.Bold)
      .borderRadius(5)
      .margin(20)
      .backgroundColor('#ffffff')
      .textAlign(TextAlign.Center)
      .width(180)
      .height(36)
      .onClick(() = > {
        this.selectIndex = index;
        if(this.currentBreakpoint === 'sm'){
          this.showSideBar=false
        }
      })
  }

  build() {
    SideBarContainer(this.currentBreakpoint === 'sm' ? SideBarContainerType.Overlay : SideBarContainerType.Embed) {
      Column() {
        this.itemBuilder(0)
        this.itemBuilder(1)
      }.backgroundColor('#F1F3F5')
      .justifyContent(FlexAlign.Center)

      Column() {
        Image(images[this.selectIndex].imageSrc)
          .objectFit(ImageFit.Contain)
          .height(300)
          .width(300)
      }
      .justifyContent(FlexAlign.Center)
      .width('100%')
      .height('100%')
    }
    .height('100%')
    .sideBarWidth(this.currentBreakpoint === 'sm' ? '100%' : '33.33%')
    .minSideBarWidth(this.currentBreakpoint === 'sm' ? '100%' : '33.33%')
    .maxSideBarWidth(this.currentBreakpoint === 'sm' ? '100%' : '33.33%')
    .showControlButton(this.currentBreakpoint === 'sm')
    .autoHide(false)
    .showSideBar(this.currentBreakpoint !== 'sm'||this.showSideBar)
    .onChange((isBarShow: boolean) = > {
      if(this.currentBreakpoint === 'sm'){
          this.showSideBar=isBarShow
        }         
    })
  }
}

單/雙欄

布局效果

image.png

實(shí)現(xiàn)方案

單/雙欄場(chǎng)景可以使用[Navigation組件]實(shí)現(xiàn),Navigation組件可以根據(jù)窗口寬度自動(dòng)切換單/雙欄顯示,減少開(kāi)發(fā)工作量。

參考代碼

@Component
struct Details {
  private imageSrc: Resource=$r('app.media.my_image_moon')
  build() {
    Column() {
      Image(this.imageSrc)
        .objectFit(ImageFit.Contain)
        .height(300)
        .width(300)
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

@Component
struct Item {
  private imageSrc?: Resource
  private label?: string

  build() {
    NavRouter() {
      Text(this.label)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .borderRadius(5)
        .backgroundColor('#FFFFFF')
        .textAlign(TextAlign.Center)
        .width(180)
        .height(36)
      NavDestination() {
        Details({imageSrc: this.imageSrc})
      }.title(this.label)
      .backgroundColor('#FFFFFF')
    }
  }
}

@Entry
@Component
struct NavigationSample {
  build() {
    Navigation() {
      Column({space: 30}) {
        Item({label: 'moon', imageSrc: $r('app.media.my_image_moon')})
        Item({label: 'sun', imageSrc: $r('app.media.my_image')})
      }
      .justifyContent(FlexAlign.Center)
      .height('100%')
      .width('100%')
    }
    .mode(NavigationMode.Auto)
    .backgroundColor('#F1F3F5')
    .height('100%')
    .width('100%')
    .navBarWidth(360)
    .hideToolBar(true)
    .title('Sample')
  }
}

三分欄

布局效果

image.png

場(chǎng)景說(shuō)明

為充分利用設(shè)備的屏幕尺寸優(yōu)勢(shì),應(yīng)用在大屏設(shè)備上常常有二分欄或三分欄的設(shè)計(jì),即“A+C”,“B+C”或“A+B+C”的組合,其中A是側(cè)邊導(dǎo)航區(qū),B是列表導(dǎo)航區(qū),C是內(nèi)容區(qū)。在用戶(hù)動(dòng)態(tài)改變窗口寬度時(shí),當(dāng)窗口寬度大于或等于840vp時(shí)頁(yè)面呈現(xiàn)A+B+C三列,放大縮小優(yōu)先變化C列;當(dāng)窗口寬度小于840vp大于等于600vp時(shí)呈現(xiàn)A+C列,放大縮小時(shí)優(yōu)先變化C列;當(dāng)窗口寬度小于600vp大于等于360vp時(shí),僅呈現(xiàn)C列。

實(shí)現(xiàn)方案

三分欄場(chǎng)景可以組合使用[SideBarContainer]組件與[Navigation組件]實(shí)現(xiàn),SideBarContainer組件可以通過(guò)側(cè)邊欄控制按鈕控制顯示/隱藏,Navigation組件可以根據(jù)窗口寬度自動(dòng)切換該組件內(nèi)單/雙欄顯示,結(jié)合響應(yīng)式布局能力,在不同斷點(diǎn)下為SideBarConContainer組件的minContentWidth屬性配置不同的值,即可實(shí)現(xiàn)目標(biāo)效果。設(shè)置minContentWidth屬性的值可以通過(guò)[斷點(diǎn)]監(jiān)聽(tīng)窗口尺寸變化的同時(shí)設(shè)置不同的值并儲(chǔ)存成一個(gè)全局對(duì)象。

參考代碼

// MainAbility.ts
import window from '@ohos.window'
import display from '@ohos.display'
import Ability from '@ohos.app.ability.Ability'

export default class MainAbility extends Ability {
  private windowObj?: window.Window
  private curBp?: string
  private myWidth?: number
  // ...
  // 根據(jù)當(dāng)前窗口尺寸更新斷點(diǎn)
  private updateBreakpoint(windowWidth:number) :void{
    // 將長(zhǎng)度的單位由px換算為vp
    let windowWidthVp = windowWidth / (display.getDefaultDisplaySync().densityDPI / 160)
    let newBp: string = ''
    let newWd: number
    if (windowWidthVp < 320) {
      newBp = 'xs'
      newWd = 360
    } else if (windowWidthVp < 600) {
      newBp = 'sm'
      newWd = 360
    } else if (windowWidthVp < 840) {
      newBp = 'md'
      newWd = 600
    } else {
      newBp = 'lg'
      newWd = 600
    }
    if (this.curBp !== newBp) {
      this.curBp = newBp
      this.myWidth = newWd
      // 使用狀態(tài)變量記錄當(dāng)前斷點(diǎn)值
      AppStorage.setOrCreate('currentBreakpoint', this.curBp)
      // 使用狀態(tài)變量記錄當(dāng)前minContentWidth值
      AppStorage.setOrCreate('myWidth', this.myWidth)
    }
  }

  onWindowStageCreate(windowStage: window.WindowStage) :void{
    windowStage.getMainWindow().then((windowObj) = > {
      this.windowObj = windowObj
      // 獲取應(yīng)用啟動(dòng)時(shí)的窗口尺寸
      this.updateBreakpoint(windowObj.getWindowProperties().windowRect.width)
      // 注冊(cè)回調(diào)函數(shù),監(jiān)聽(tīng)窗口尺寸變化
      windowObj.on('windowSizeChange', (windowSize)= >{
        this.updateBreakpoint(windowSize.width)
      })
    });
   // ...
  }
    
  // 窗口銷(xiāo)毀時(shí),取消窗口尺寸變化監(jiān)聽(tīng)
  onWindowStageDestroy() :void {
    if (this.windowObj) {
      this.windowObj.off('windowSizeChange')
    }
  }
  //...
}


// tripleColumn.ets
@Component
struct Details {
  private imageSrc: Resource=$r('app.media.startIcon')
  build() {
    Column() {
      Image(this.imageSrc)
        .objectFit(ImageFit.Contain)
        .height(300)
        .width(300)
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

@Component
struct Item {
  private imageSrc?: Resource
  private label?: string

  build() {
    NavRouter() {
      Text(this.label)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .backgroundColor('#66000000')
        .textAlign(TextAlign.Center)
        .width('100%')
        .height('30%')
      NavDestination() {
        Details({imageSrc: this.imageSrc})
      }.title(this.label)
      .hideTitleBar(false)
      .backgroundColor('#FFFFFF')
    }
    .margin(10)
  }
}

@Entry
@Component
struct TripleColumnSample {
  @State arr: number[] = [1, 2, 3]
  @StorageProp('myWidth') myWidth: number = 360

  @Builder NavigationTitle() {
    Column() {
      Text('Sample')
        .fontColor('#000000')
        .fontSize(24)
        .width('100%')
        .height('100%')
        .align(Alignment.BottomStart)
        .margin({left:'5%'})
    }.alignItems(HorizontalAlign.Start)
  }

  build() {
    SideBarContainer() {
      Column() {
        List() {
          ForEach(this.arr, (item:number, index) = > {
            ListItem() {
              Text('A'+item)
                .width('100%').height("20%").fontSize(24)
                .fontWeight(FontWeight.Bold)
                .textAlign(TextAlign.Center).backgroundColor('#66000000')
            }
          })
        }.divider({ strokeWidth: 5, color: '#F1F3F5' })
      }.width('100%')
      .height('100%')
      .justifyContent(FlexAlign.SpaceEvenly)
      .backgroundColor('#F1F3F5')

      Column() {
        Navigation() {
          List(){
            ListItem() {
              Column() {
                Item({ label: 'B1', imageSrc: $r('app.media.startIcon') })
                Item({ label: 'B2', imageSrc: $r('app.media.startIcon') })
              }
            }.width('100%')
          }
        }
        .mode(NavigationMode.Auto)
        .minContentWidth(360)
        .navBarWidth(240)
        .backgroundColor('#FFFFFF')
        .height('100%')
        .width('100%')
        .hideToolBar(true)
        .title(this.NavigationTitle)
      }.width('100%').height('100%')
    }.sideBarWidth(240)
    .minContentWidth(this.myWidth)
  }
}

自定義彈窗

image.png

布局效果

實(shí)現(xiàn)方案

自定義彈窗通常通過(guò)[CustomDialogController]實(shí)現(xiàn),有兩種方式實(shí)現(xiàn)本場(chǎng)景的目標(biāo)效果:

  • 通過(guò)gridCount屬性配置自定義彈窗的寬度。
    系統(tǒng)默認(rèn)對(duì)不同斷點(diǎn)下的窗口進(jìn)行了柵格化:sm斷點(diǎn)下為4柵格,md斷點(diǎn)下為8柵格,lg斷點(diǎn)下為12柵格。通過(guò)gridCount屬性可以配置彈窗占據(jù)柵格中的多少列,將該值配置為4即可實(shí)現(xiàn)目標(biāo)效果。
  • 將customStyle設(shè)置為true,即彈窗的樣式完全由開(kāi)發(fā)者自定義。
    開(kāi)發(fā)者自定義彈窗樣式時(shí),開(kāi)發(fā)者可以根據(jù)需要配置彈窗的寬高和背景色(非彈窗區(qū)域保持默認(rèn)的半透明色)。自定義彈窗樣式配合[柵格組件]同樣可以實(shí)現(xiàn)目標(biāo)效果。

參考代碼

@Entry
@Component
struct CustomDialogSample {
  // 通過(guò)gridCount配置彈窗的寬度
  dialogControllerA: CustomDialogController = new CustomDialogController({
    builder: CustomDialogA ({
      cancel: this.onCancel,
      confirm: this.onConfirm
    }),
    cancel: this.onCancel,
    autoCancel: true,
    gridCount: 4,
    customStyle: false
  })
  // 自定義彈窗樣式
  dialogControllerB: CustomDialogController = new CustomDialogController({
    builder: CustomDialogB ({
      cancel: this.onCancel,
      confirm: this.onConfirm
    }),
    cancel: this.onCancel,
    autoCancel: true,
    customStyle: true
  })

  onCancel() {
    console.info('callback when dialog is canceled')
  }

  onConfirm() {
    console.info('callback when dialog is confirmed')
  }

  build() {
    Column() {
      Button('CustomDialogA').margin(12)
        .onClick(() = > {
          this.dialogControllerA.open()
        })
      Button('CustomDialogB').margin(12)
        .onClick(() = > {
          this.dialogControllerB.open()
        })
    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
  }
}

@CustomDialog
struct CustomDialogA {
  controller?: CustomDialogController
  cancel?: () = > void
  confirm?: () = > void

  build() {
    Column() {
      Text('是否刪除此聯(lián)系人?')
        .fontSize(16)
        .fontColor('#E6000000')
        .margin({bottom: 8, top: 24, left: 24, right: 24})
      Row() {
        Text('取消')
          .fontColor('#007DFF')
          .fontSize(16)
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .onClick(()= >{
            if(this.controller){
                 this.controller.close()
             }
            this.cancel!()
          })
        Line().width(1).height(24).backgroundColor('#33000000').margin({left: 4, right: 4})
        Text('刪除')
          .fontColor('#FA2A2D')
          .fontSize(16)
          .layoutWeight(1)
          .textAlign(TextAlign.Center)
          .onClick(()= >{
             if(this.controller){
                 this.controller.close()
             }
            this.confirm!()
          })
      }.height(40)
      .margin({left: 24, right: 24, bottom: 16})
    }.borderRadius(24)
  }
}

@CustomDialog
struct CustomDialogB {
  controller?: CustomDialogController
  cancel?: () = > void
  confirm?: () = > void

  build() {
    GridRow({columns: {sm: 4, md: 8, lg: 12}}) {
      GridCol({span: 4, offset: {sm: 0, md: 2, lg: 4}}) {
        Column() {
          Text('是否刪除此聯(lián)系人?')
            .fontSize(16)
            .fontColor('#E6000000')
            .margin({bottom: 8, top: 24, left: 24, right: 24})
          Row() {
            Text('取消')
              .fontColor('#007DFF')
              .fontSize(16)
              .layoutWeight(1)
              .textAlign(TextAlign.Center)
              .onClick(()= >{
                if(this.controller){
                 this.controller.close()
                }
                this.cancel!()
              })
            Line().width(1).height(24).backgroundColor('#33000000').margin({left: 4, right: 4})
            Text('刪除')
              .fontColor('#FA2A2D')
              .fontSize(16)
              .layoutWeight(1)
              .textAlign(TextAlign.Center)
              .onClick(()= >{
                 if(this.controller){
                 this.controller.close()
                }
                this.confirm!()
              })
          }.height(40)
          .margin({left: 24, right: 24, bottom: 16})
        }.borderRadius(24).backgroundColor('#FFFFFF')
      }
    }.margin({left: 24, right: 24})
  }
}

大圖瀏覽

布局效果

image.png

實(shí)現(xiàn)方案

圖片通常使用[Image組件]展示,Image組件的objectFit屬性默認(rèn)為ImageFit.Cover,即保持寬高比進(jìn)行縮小或者放大以使得圖片兩邊都大于或等于顯示邊界。在大圖瀏覽場(chǎng)景下,因屏幕與圖片的寬高比可能有差異,常常會(huì)發(fā)生圖片被截?cái)嗟膯?wèn)題。此時(shí)只需將Image組件的objectFit屬性設(shè)置為ImageFit.Contain,即保持寬高比進(jìn)行縮小或者放大并使得圖片完全顯示在顯示邊界內(nèi),即可解決該問(wèn)題。

參考代碼

@Entry
@Component
struct BigImage {
  build() {
    Row() {
      Image($r("app.media.image"))
        .objectFit(ImageFit.Contain)
    }
  }
}

操作入口

布局效果

image.png

實(shí)現(xiàn)方案

Scroll(內(nèi)容超出寬度時(shí)可滾動(dòng)) + Row(橫向均分:justifyContent(FlexAlign.SpaceAround)、 最小寬度約束:constraintSize({ minWidth: '100%' })

參考代碼

interface OperationItem {
  name: string
  icon: Resource
}

@Entry
@Component
export default struct OperationEntries {
  @State listData: Array< OperationItem > = [
    { name: '私人FM', icon: $r('app.media.self_fm') },
    { name: '歌手', icon: $r('app.media.singer') },
    { name: '歌單', icon: $r('app.media.song_list') },
    { name: '排行榜', icon: $r('app.media.rank') },
    { name: '熱門(mén)', icon: $r('app.media.hot') },
    { name: '運(yùn)動(dòng)音樂(lè)', icon: $r('app.media.sport') },
    { name: '音樂(lè)FM', icon: $r('app.media.audio_fm') },
    { name: '福利', icon: $r('app.media.bonus') }]

  build() {
    Scroll() {
      Row() {
        ForEach(this.listData, (item:OperationItem) = > {
          Column() {
            Image(item.icon)
              .width(48)
              .aspectRatio(1)
            Text(item.name)
              .margin({ top: 8 })
              .fontSize(16)
          }
          .justifyContent(FlexAlign.Center)
          .height(104)
          .padding({ left: 12, right: 12 })
        })
      }
      .constraintSize({ minWidth: '100%' }).justifyContent(FlexAlign.SpaceAround)
    }
    .width('100%')
    .scrollable(ScrollDirection.Horizontal)
  }
}

頂部

布局效果

image.png

實(shí)現(xiàn)方案

最外層使用柵格行組件GridRow布局

文本標(biāo)題使用柵格列組件GridCol

搜索框使用柵格列組件GridCol

參考代碼

@Entry
@Component
export default struct Header {
  @State needWrap: boolean = true

  build() {
    GridRow() {
      GridCol({ span: { sm: 12, md: 6, lg: 7 } }) {
        Row() {
          Text('推薦').fontSize(24)
          Blank()
          Image($r('app.media.ic_public_more'))
            .width(32)
            .height(32)
            .objectFit(ImageFit.Contain)
            .visibility(this.needWrap ? Visibility.Visible : Visibility.None)
        }
        .width('100%').height(40)
        .alignItems(VerticalAlign.Center)
      }

      GridCol({ span: { sm: 12, md: 6, lg: 5 } }) {
        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
          Search({ placeholder: '猜您喜歡: 萬(wàn)水千山' })
            .placeholderFont({ size: 16 })
            .margin({ top: 4, bottom: 4 })
          Image($r('app.media.audio_fm'))
            .width(32)
            .height(32)
            .objectFit(ImageFit.Contain)
            .flexShrink(0)
            .margin({ left: 12 })
          Image($r('app.media.ic_public_more'))
            .width(32)
            .height(32)
            .objectFit(ImageFit.Contain)
            .flexShrink(0)
            .margin({ left: 12 })
            .visibility(this.needWrap ? Visibility.None : Visibility.Visible)
        }
      }
    }.onBreakpointChange((breakpoint: string) = > {
      if (breakpoint === 'sm') {
        this.needWrap = true
      } else {
        this.needWrap = false
      }
    })
    .padding({ left: 12, right: 12 })
  }
}

縮進(jìn)布局

布局效果

image.png

實(shí)現(xiàn)方案

借助[柵格組件],控制待顯示內(nèi)容在不同的斷點(diǎn)下占據(jù)不同的列數(shù),即可實(shí)現(xiàn)不同設(shè)備上的縮進(jìn)效果。另外還可以調(diào)整不同斷點(diǎn)下柵格組件與兩側(cè)的間距,獲得更好的顯示效果。

參考代碼

@Entry
@Component
struct IndentationSample {
  @State private gridMargin: number = 24
  build() {
    Row() {
      GridRow({columns: {sm: 4, md: 8, lg: 12}, gutter: 24}) {
        GridCol({span: {sm: 4, md: 6, lg: 8}, offset: {md: 1, lg: 2}}) {
          Column() {
            ForEach([0, 1, 2, 4], () = > {
              Column() {
                ItemContent()
              }
            })
          }.width('100%')
        }
      }
      .margin({left: this.gridMargin, right: this.gridMargin})
      .onBreakpointChange((breakpoint: string) = > {
        if (breakpoint === 'lg') {
          this.gridMargin = 48
        } else if (breakpoint === 'md') {
          this.gridMargin = 32
        } else {
          this.gridMargin = 24
        }
      })
    }
    .height('100%')
    .alignItems((VerticalAlign.Center))
    .backgroundColor('#F1F3f5')
  }
}

@Component
struct ItemContent {
  build() {
    Column() {
      Row() {
        Row() {
        }
        .width(28)
        .height(28)
        .borderRadius(14)
        .margin({ right: 15 })
        .backgroundColor('#E4E6E8')

        Row() {
        }
        .width('30%').height(20).borderRadius(4)
        .backgroundColor('#E4E6E8')
      }.width('100%').height(28)

      Row() {
      }
      .width('100%')
      .height(68)
      .borderRadius(16)
      .margin({ top: 12 })
      .backgroundColor('#E4E6E8')
    }
    .height(128)
    .borderRadius(24)
    .backgroundColor('#FFFFFF')
    .padding({ top: 12, bottom: 12, left: 18, right: 18 })
    .margin({ bottom: 12 })
  }
}

挪移布局

布局效果

image.png

實(shí)現(xiàn)方案

不同斷點(diǎn)下,柵格子元素占據(jù)的列數(shù)會(huì)隨著開(kāi)發(fā)者的配置發(fā)生改變。當(dāng)一行中的列數(shù)超過(guò)柵格組件在該斷點(diǎn)的總列數(shù)時(shí),可以自動(dòng)換行,即實(shí)現(xiàn)”上下布局”與”左右布局”之間切換的效果。

參考代碼

@Entry
@Component
struct DiversionSample {
  @State private currentBreakpoint: string = 'md'
  @State private imageHeight: number = 0
  build() {
    Row() {
      GridRow() {
        GridCol({span: {sm: 12, md: 6, lg: 6}}) {
          Image($r('app.media.illustrator'))
          .aspectRatio(1)
          .onAreaChange((oldValue: Area, newValue: Area) = > {
            this.imageHeight = Number(newValue.height)
          })
          .margin({left: 12, right: 12})
        }

        GridCol({span: {sm: 12, md: 6, lg: 6}}) {
          Column(){
            Text($r('app.string.user_improvement'))
              .textAlign(TextAlign.Center)
              .fontSize(20)
              .fontWeight(FontWeight.Medium)
            Text($r('app.string.user_improvement_tips'))
              .textAlign(TextAlign.Center)
              .fontSize(14)
              .fontWeight(FontWeight.Medium)
          }
          .margin({left: 12, right: 12})
          .justifyContent(FlexAlign.Center)
          .height(this.currentBreakpoint === 'sm' ? 100 : this.imageHeight)
        }
      }.onBreakpointChange((breakpoint: string) = > {
        this.currentBreakpoint = breakpoint;
      })
    }
    .height('100%')
    .alignItems((VerticalAlign.Center))
    .backgroundColor('#F1F3F5')
  }
}

重復(fù)布局

布局效果

image.png
實(shí)現(xiàn)方案

不同斷點(diǎn)下,配置柵格子組件占據(jù)不同的列數(shù),即可實(shí)現(xiàn)“小屏單列顯示、大屏雙列顯示”的效果。另外,還可以通過(guò)柵格組件的onBreakpointChange事件,調(diào)整頁(yè)面中顯示的元素?cái)?shù)量。

參考代碼

搜狗高速瀏覽器截圖20240326151344.png

`HarmonyOSOpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`

@Entry
@Component
struct RepeatSample {
  @State private currentBreakpoint: string = 'md'
  @State private listItems: number[] = [1, 2, 3, 4, 5, 6, 7, 8]
  @State private gridMargin: number = 24

  build() {
    Row() {
      // 當(dāng)目標(biāo)區(qū)域不足以顯示所有元素時(shí),可以通過(guò)上下滑動(dòng)查看不同的元素
      Scroll() {
        GridRow({gutter: 24}) {
          ForEach(this.listItems, () = > {
           // 通過(guò)配置元素在不同斷點(diǎn)下占的列數(shù),實(shí)現(xiàn)不同的布局效果
            GridCol({span: {sm: 12, md: 6, lg: 6}}) {
              Column() {
                RepeatItemContent()
              }
            }
          })
        }
        .margin({left: this.gridMargin, right: this.gridMargin})
        .onBreakpointChange((breakpoint: string) = > {
          this.currentBreakpoint = breakpoint;
          if (breakpoint === 'lg') {
            this.gridMargin = 48
          } else if (breakpoint === 'md') {
            this.gridMargin = 32
          } else {
            this.gridMargin = 24
          }
        })
      }.height(348)
    }
    .height('100%')
    .backgroundColor('#F1F3F5')
  }
}

@Component
struct RepeatItemContent {
  build() {
    Flex() {
      Row() {
      }
      .width(43)
      .height(43)
      .borderRadius(12)
      .backgroundColor('#E4E6E8')
      .flexGrow(0)

      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.SpaceAround }) {
        Row() {
        }
        .height(10)
        .width('80%')
        .backgroundColor('#E4E6E8')

        Row() {
        }
        .height(10)
        .width('50%')
        .backgroundColor('#E4E6E8')
      }
      .flexGrow(1)
      .margin({ left: 13 })
    }
    .padding({ top: 13, bottom: 13, left: 13, right: 37 })
    .height(69)
    .backgroundColor('#FFFFFF')
    .borderRadius(24)
  }
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 移動(dòng)開(kāi)發(fā)

    關(guān)注

    0

    文章

    52

    瀏覽量

    9734
  • 鴻蒙系統(tǒng)
    +關(guān)注

    關(guān)注

    183

    文章

    2634

    瀏覽量

    66302
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1973

    瀏覽量

    30143
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3713

    瀏覽量

    16254
  • 鴻蒙OS
    +關(guān)注

    關(guān)注

    0

    文章

    188

    瀏覽量

    4382
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    HarmonyOS開(kāi)發(fā)案例:【一次開(kāi)發(fā),多端部署(視頻應(yīng)用)】

    者提供了“一次開(kāi)發(fā),多端部署”的系統(tǒng)能力,讓開(kāi)發(fā)者可以基于一次
    的頭像 發(fā)表于 05-11 15:41 ?1441次閱讀
    HarmonyOS<b class='flag-5'>開(kāi)發(fā)</b>案例:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>(視頻應(yīng)用)】

    HarmonyOS開(kāi)發(fā)案例:【一次開(kāi)發(fā),多端部署-音樂(lè)專(zhuān)輯】

    基于自適應(yīng)和響應(yīng)式布局,實(shí)現(xiàn)一次開(kāi)發(fā)、多端部署音樂(lè)專(zhuān)輯頁(yè)面。
    的頭像 發(fā)表于 05-13 16:48 ?679次閱讀
    HarmonyOS<b class='flag-5'>開(kāi)發(fā)</b>案例:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>-音樂(lè)專(zhuān)輯】

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】應(yīng)用(自適應(yīng)布局

    針對(duì)常見(jiàn)的開(kāi)發(fā)場(chǎng)景,方舟開(kāi)發(fā)框架提煉了七種自適應(yīng)布局能力,這些布局可以獨(dú)立使用,也可多種布局疊加
    的頭像 發(fā)表于 05-24 10:34 ?1018次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】應(yīng)用(自適應(yīng)<b class='flag-5'>布局</b>)

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(多天氣)項(xiàng)目

    本示例展示個(gè)天氣應(yīng)用界面,包括首頁(yè)、城市管理、添加城市、更新時(shí)間彈窗,體現(xiàn)一次開(kāi)發(fā),多端部署的能力。
    的頭像 發(fā)表于 05-20 14:59 ?837次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(<b class='flag-5'>一</b>多天氣)項(xiàng)目

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(音樂(lè)專(zhuān)輯主頁(yè))

    本示例使用一次開(kāi)發(fā)多端部署中介紹的自適應(yīng)布局能力和響應(yīng)式布局能力進(jìn)行多設(shè)備(或多窗口尺寸)適配,
    的頭像 發(fā)表于 05-21 14:48 ?726次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(音樂(lè)專(zhuān)輯主頁(yè))

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(音樂(lè)專(zhuān)輯頁(yè)面)

    基于自適應(yīng)和響應(yīng)式布局,實(shí)現(xiàn)一次開(kāi)發(fā)多端部署音樂(lè)專(zhuān)輯頁(yè)面。
    的頭像 發(fā)表于 05-25 16:21 ?790次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(音樂(lè)專(zhuān)輯頁(yè)面)

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(視頻應(yīng)用)

    者提供了“一次開(kāi)發(fā),多端部署”的系統(tǒng)能力,讓開(kāi)發(fā)者可以基于一次
    的頭像 發(fā)表于 05-25 16:29 ?4535次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(視頻應(yīng)用)

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(自適應(yīng)布局

    針對(duì)常見(jiàn)的開(kāi)發(fā)場(chǎng)景,方舟開(kāi)發(fā)框架提煉了七種自適應(yīng)布局能力,這些布局可以獨(dú)立使用,也可多種布局疊加
    的頭像 發(fā)表于 05-25 16:36 ?1691次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(自適應(yīng)<b class='flag-5'>布局</b>)

    鴻蒙OS開(kāi)發(fā)典型頁(yè)面場(chǎng)景一次開(kāi)發(fā),多端部署】實(shí)戰(zhàn)(音樂(lè)專(zhuān)輯頁(yè)2)

    本示例使用[一次開(kāi)發(fā)多端部署]中介紹的自適應(yīng)布局能力和響應(yīng)式布局能力進(jìn)行多設(shè)備(或多窗口尺寸)適
    的頭像 發(fā)表于 05-25 16:47 ?2090次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:<b class='flag-5'>典型</b>頁(yè)面<b class='flag-5'>場(chǎng)景</b>【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】實(shí)戰(zhàn)(音樂(lè)專(zhuān)輯頁(yè)2)

    鴻蒙OS開(kāi)發(fā)典型頁(yè)面場(chǎng)景一次開(kāi)發(fā),多端部署】實(shí)戰(zhàn)(設(shè)置典型頁(yè)面)

    本示例展示了設(shè)置應(yīng)用的典型頁(yè)面,其在小窗口和大窗口有不同的顯示效果,體現(xiàn)一次開(kāi)發(fā)、多端部署的能力。
    的頭像 發(fā)表于 05-27 09:36 ?1138次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:<b class='flag-5'>典型</b>頁(yè)面<b class='flag-5'>場(chǎng)景</b>【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】實(shí)戰(zhàn)(設(shè)置<b class='flag-5'>典型</b>頁(yè)面)

    HarmonyOS\"一次開(kāi)發(fā),多端部署\"優(yōu)秀實(shí)踐——玩機(jī)技巧,碼上起航

    的潛在用戶(hù)群體。個(gè)應(yīng)用要在多類(lèi)設(shè)備上提供統(tǒng)的內(nèi)容,需要適配不同的屏幕尺寸和硬件,開(kāi)發(fā)成本較高。\"一次開(kāi)發(fā),
    發(fā)表于 08-30 18:14

    華為開(kāi)發(fā)者大會(huì)2021:一次開(kāi)發(fā) 多端部署

    一次開(kāi)發(fā) 多端部署使能開(kāi)發(fā)者從單設(shè)備生態(tài)跨入多設(shè)備生態(tài)!
    的頭像 發(fā)表于 10-22 15:09 ?1641次閱讀
    華為<b class='flag-5'>開(kāi)發(fā)</b>者大會(huì)2021:<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b> <b class='flag-5'>多端</b><b class='flag-5'>部署</b>

    華為開(kāi)發(fā)者大會(huì)2021:軟件部總裁龔體 鴻蒙系統(tǒng) 一次開(kāi)發(fā) 多端部署 萬(wàn)物互連

    華為開(kāi)發(fā)者大會(huì)2021:鴻蒙系統(tǒng) 一次開(kāi)發(fā) 多端部署 萬(wàn)物互連 在華為
    的頭像 發(fā)表于 10-22 15:09 ?4544次閱讀
    華為<b class='flag-5'>開(kāi)發(fā)</b>者大會(huì)2021:軟件部總裁龔體 <b class='flag-5'>鴻蒙</b>系統(tǒng) <b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b> <b class='flag-5'>多端</b><b class='flag-5'>部署</b> 萬(wàn)物互連

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】(多設(shè)備自適應(yīng)能力)簡(jiǎn)單介紹

    本示例是《一次開(kāi)發(fā)多端部署》的配套示例代碼,展示了[頁(yè)面開(kāi)發(fā)多能力],包括自適應(yīng)
    的頭像 發(fā)表于 05-21 14:59 ?2398次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】(多設(shè)備自適應(yīng)能力)簡(jiǎn)單介紹

    鴻蒙OS開(kāi)發(fā):【一次開(kāi)發(fā),多端部署】( 設(shè)置app頁(yè)面)

    本示例展示了設(shè)置應(yīng)用的典型頁(yè)面,其在小窗口和大窗口有不同的顯示效果,體現(xiàn)一次開(kāi)發(fā)、多端部署的能力。
    的頭像 發(fā)表于 05-21 14:56 ?1042次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>OS</b><b class='flag-5'>開(kāi)發(fā)</b>:【<b class='flag-5'>一次</b><b class='flag-5'>開(kāi)發(fā)</b>,<b class='flag-5'>多端</b><b class='flag-5'>部署</b>】( 設(shè)置app頁(yè)面)
    RM新时代网站-首页