Building a HarmonyOS Accounting App with HDS Suite: Custom TabBar, Navigation & Progress Components
This tutorial demonstrates how to rapidly construct a HarmonyOS accounting application using the HDS suite, covering a custom center-button TabBar via yltabbar, a title bar with HdsNavDestination, a stacked expense card, a multi-segment circular progress bar with ylprogress, and a horizontal category ranking list.
This article walks through the implementation of a HarmonyOS accounting application's project architecture and home page using the HDS (HarmonyOS Development Suite) component library. The author shares practical code examples for each major UI section.
Custom TabBar with Center Button
The application uses a third-party component yltabbar to achieve an irregular TabBar with a protruding center button. Key configuration options include: recess: false to disable the notch effect needShadow: true to add a shadow centerImage set to a resource for the center button icon tabItemAction and centerItemAction callbacks for tap handling
yltabbar({
currentIndex: this.pageIndex,
tabItems: this.tabItems,
centerImage: $r('app.media.jzadd'),
fontColor: Color.Gray,
selectedFontColor: this.mainColor,
backColor: '#ffffff',
needShadow: true,
recess: false,
tabItemAction: (num) => {
},
centerItemAction: () => {
}
})Home Page Title Bar with HdsNavDestination
The title bar is built using HdsNavDestination 's built-in titleBar property, avoiding custom development. It configures a main title, sub-title, and two menu items with icons and actions. The container also applies padding to avoid the system status bar using AppStorage.get('topHeight').
HdsNavDestination(){
…
}
.width('100%')
.height('100%')
.hideBackButton(true)
.titleBar({
content: {
title: {
mainTitle: 'Hi,幽蓝',
subTitle: '每一笔记录,都是生活的积累'
},
menu: {
value: [{
content: {
label: 'menu1',
icon: $r('app.media.jzsearch'),
isEnabled: true,
action: () => {
console.info('HdsNavDestination menu1');
}
}
}, {
content: {
label: 'menu2',
icon: $r('app.media.jzrl'),
isEnabled: true,
action: () => {
console.info('HdsNavDestination menu2');
}
}
}]
}
},
})
.padding({ top: AppStorage.get('topHeight') as number })
.backgroundColor(this.backColor)Scrollable List with Title Bar Avoidance
The home page content is a List. To prevent the first item from being obscured by the title bar, a blank ListItem with a height of 56 (typical title bar height) is inserted at the top.
ListItem(){
Row(){
Blank().height(56)
}
}Expense Card with Stack Layout
The top expense card uses a Stack to layer a background image ( $r('app.media.backjz')) with a Column containing an icon, label, amount, and income/balance text. The card has rounded corners (14), clipping enabled, and a background color bound to this.mainColor.
Stack(){
Image($r('app.media.backjz'))
.width('100%')
.height('100%')
Column({ space: 20 }){
Row({ space: 8 }){
Image($r('app.media.jzeye'))
.width(13)
.height(13)
Text('本月支出(元)')
.fontColor(Color.White)
.fontSize(12)
}
Text('2352.23')
.fontColor(Color.White)
.fontSize(30)
.fontWeight(FontWeight.Bold)
Text('本月收入5600 结余3120.60')
.fontColor(Color.White)
.fontSize(14)
}
.padding({ left: 20 })
.width('100%')
.height(160)
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Center)
}
.width('100%')
.height(160)
.borderRadius(14)
.clip(true)
.backgroundColor(this.mainColor)Multi-Segment Circular Progress Bar with ylprogress
To display a segmented circular progress (expense categories with different colors), the author uses another custom component ylprogress (installable via ohpm). The system Progress component does not support multiple colors in ring mode. The example shows three segments with values 0.6, 0.3, 0.1 and distinct colors, animated, with centered text overlay via a Stack.
Stack({ alignContent: Alignment.Center }){
ylprogress({
progressList: [
{ value: 0.6, color: this.mainColor },
{ value: 0.3, color: 'rgb(255,157,109)' },
{ value: 0.1, color: 'rgb(254,198,201)' },
],
lineWidth: 15,
animate: true,
textColor: Color.Orange,
})
.width(110)
.height(110)
Column(){
Text('结余')
.fontSize(12)
.fontColor(Color.Gray)
Text('3167.50')
.fontColor(this.mainColor)
.fontSize(16)
.fontWeight(FontWeight.Bold)
}
}
.width(110)
.height(110)Expense Category Ranking List
The ranking section uses a ListItemGroup with a custom header. Inside a single ListItem, a Row with FlexAlign.SpaceBetween renders each category via ForEach over this.shopTypes. Each item is a Column showing an icon, title, value, and rate.
ListItemGroup({ header: this.groupHeader('支出分类排行') }){
ListItem(){
Row(){
ForEach(this.shopTypes, (item: ShopClass, index) => {
Column({ space: 4 }){
Image(item.icon)
.width(40)
.height(42)
Text(item.title)
.fontColor(Color.Black)
.fontSize(13)
.fontWeight(FontWeight.Bold)
Text(item.value)
.fontColor(Color.Black)
.fontSize(13)
.fontWeight(FontWeight.Bold)
Text(item.rate)
.fontColor(Color.Gray)
.fontSize(12)
}
})
}
.padding({ left: 10, right: 10 })
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
.margin({ top: 10 })
}
.margin({ top: 10 })The article concludes by thanking readers. All components showcased are either part of the HDS suite or the author's own open-source libraries ( yltabbar, ylprogress), demonstrating how to compose a polished home page quickly.
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.
