Building HarmonyOS Audiobook App: Discover Page Implementation
This tutorial walks through implementing the Discover page for a HarmonyOS audiobook app, covering title bar setup with HdsNavDestination, hot tags layout using Flex wrap, featured playlists with Row and ForEach, and a bottom audio info bar with space-between alignment.
The article demonstrates how to build the Discover page of a HarmonyOS audiobook app. The page consists of three main sections: a title bar, a content list, and a currently playing audio info bar.
Title Bar Implementation
The title bar uses HdsNavDestination with a gradual blur scroll effect. It hides the back button, sets the background color, adds top padding from AppStorage.get('topHeight'), and configures a title bar with main title "发现" (Discover) and a single menu button using a search icon resource.
HdsNavDestination(){ … }.padding({top:AppStorage.get('topHeight') as number}).backgroundColor(this.backColor).hideBackButton(true).titleBar({ style:{ scrollEffectOpts:{ scrollEffectType: ScrollEffectType.GRADUAL_BLUR } }, content:{ title:{ mainTitle:'发现' }, menu:{ value:[ { content:{ label:'', icon:$r('app.media.sjSearch') } } ] } })A screenshot shows the rendered title bar.
Content List and Navigation Bar Avoidance
Because HdsNavDestination is used, the first list item must manually avoid the title bar height. A Blank component with height 56 is inserted at the top of the list.
ListItem(){ Row(){ Blank().height(56) } }Hot Tags Section with Flex Wrap
Hot tags are implemented using a Flex container with direction: FlexDirection.Row, wrap: FlexWrap.Wrap, and main-axis spacing of 10vp. Each tag is a Text component styled with white font, 13px size, centered alignment, horizontal padding 10, vertical padding 6, semi-transparent gray background, 4px border radius, and top margin 10. The tags array contains eight categories: "心理成长", "历史", "商业财经", "文学小说", "科幻", "悬疑推理", "自我提升", "传记".
@State tags:string[] = ['心理成长','历史','商业财经','文学小说','科幻','悬疑推理','自我提升','传记'] Flex({direction:FlexDirection.Row,wrap:FlexWrap.Wrap,space:{main:{value:10,unit:LengthUnit.VP}}}){ ForEach(this.tags,(str:string,index)=>{ Text(str).fontColor(Color.White).fontSize(13).textAlign(TextAlign.Center).padding({left:10,right:10,top:6,bottom:6}).backgroundColor('rgba(200,200,200,0.3)').borderRadius(4).margin({top:10}) }) }A screenshot illustrates the wrap layout resembling a horizontal waterfall flow.
Featured Playlists Horizontal Row
The "精选播单" (Featured Playlists) section displays three items horizontally without scrolling. A Row with justifyContent: FlexAlign.SpaceAround and top padding 10 contains a ForEach over this.bds. Each item is a Column (spacing 7) with an Image (width 100%, height 143, border radius 12, objectFit Fill), a bold white title (14px), a gray content line (13px), and a gray count line (13px). The column aligns items start and has fixed width 100.
Row(){ ForEach(this.bds,(item:BDClass,index)=>{ Column({space:7}){ Image(item.img).width('100%').height(143).borderRadius(12).objectFit(ImageFit.Fill) Text(item.title).fontColor(Color.White).fontSize(14).fontWeight(FontWeight.Bold) Text(item.content).fontColor('rgb(200,200,200)').fontSize(13) Text(item.count).fontColor('rgb(200,200,200)').fontSize(13) }.alignItems(HorizontalAlign.Start).width(100) }) }.width('100%').justifyContent(FlexAlign.SpaceAround).padding({top:10})A screenshot shows the three-card layout.
Currently Playing Audio Info Bar
The bottom audio bar uses a Row with alignItems: VerticalAlign.Center, justifyContent: FlexAlign.SpaceBetween, full width, height 50, background color rgb(106,87,65), and horizontal padding 14. The left side is a Row (space 6) containing a 35x35 cover image and a Column with two white/gray texts: book title "瓦尔登湖" (13px) and chapter "第3章 自然之声" (13px, gray). The right side is a Row (space 10) with two 32x32 icon images for play and list.
Row(){ Row({space:6}){ Image($r('app.media.bodan2')).width(35).height(35) Column(){ Text('瓦尔登湖').fontColor(Color.White).fontSize(13) Text('第3章 自然之声').fontColor('rgb(200,200,200)').fontSize(13) }.alignItems(HorizontalAlign.Start) } Row({space:10}){ Image($r('app.media.barPlay')).width(32).height(32) Image($r('app.media.sjList')).width(32).height(32) } }.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.SpaceBetween).width('100%').height(50).backgroundColor('rgb(106,87,65)').padding({left:14,right:14})A final screenshot shows the complete page with all sections combined.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
51CTO HarmonyOS Developer Community
The HarmonyOS Developer Community is a learning-oriented community for developers to learn, communicate, ask questions, and share.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
