The author, began to lead everyone from scratch, our calendar actual combat.
The first step is to complete the calendar header navigation bar of our calendar.
The sample code is as follows:
@Entry
struct Index {
build() {
Column() {
Row() {
Image($r('sys.media.ohos_ic_public_arrow_left'))
.width(24)
.aspectRatio(1)
.fillColor(Color.Black)
.onClick(() => {
})
Text('calendar')
Column()
.width(24)
}
.padding(5)
.width('100%')
.backgroundColor('#50cccccc')
.justifyContent(FlexAlign.SpaceBetween)
Text('123321')
}
.width('100%')
.height('100%')
}
}
(Explain: Adopt a full-screen vertical layout (Column). At the top is a horizontal navigation bar (Row) with three elements: a 24x24 black return arrow icon (referencing system resources ohos_ic_public_arrow_left) on the left, a "calendar" header text in the middle, and a 24-width placeholder space on the right. The navigation bar has 5 units of padding, a translucent gray background (#50cccccc), and a symmetrical distribution of left and right elements through a two-end alignment layout (SpaceBetween). The return icon has an empty click event callback (the actual return logic needs to be supplemented). The main body area of the page currently only displays the "123321" text, which should be replaced with the calendar function component in practice. The entire page is set to 100% width and height to fill the screen. )
Step 2: Calendar, which completes the logic of obtaining calendar date.
@Entry
@Component
struct Index {
private scrollerForScroll: Scroller = new Scroller();
private scrollerForList: Scroller = new Scroller();
@State listPosition: number = 0; // 0 means scrolling to the top of the List, 1 means intermediate value, and 2 means scrolling to the bottom of the List.
private arr: | string[] = [];
getTime(index: number = 1) {
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1 + index;
const day = date.getDate();
const week = date.getDay();
// Example: Get the day of the week on Thursday, June 5, 2025
const targetDate = new Date(year, month - 1, 1); // Note: Months are counted from 0 (5 for June)
const dayIndex = targetDate.getDay(); // Back 4 (Thursday)
const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"
, "Friday", "Saturday"];
for (let i = 0; i < dayIndex; i++) {
this.arr.push('')
}
// Get how many days there are in a month
const days = new Date(year, month, 0).getDate();
for (let i = 1; i < days + 1; i++) {
this.arr.push(i + '')
}
}
aboutToAppear(): void {
this.getTime()
}
build() {
Column() {
// Nav head navigation bar
Row() {
Image($r('sys.media.ohos_ic_public_arrow_left'))
.width(28)
.aspectRatio(1)
.fillColor(Color.Black)
.onClick(() => {
})
Text('Calendar')
.fontSize(18)
Column()
.width(28)
}
.padding(8)
.width('100%')
.backgroundColor('#50cccccc')
.justifyContent(FlexAlign.SpaceBetween)
// Date arrangement
Row() {
Text('Sunday')
.fontColor('#FF4A24')
Text('Monday')
Text('Tuesday')
Text('Wednesday')
Text('Thursday')
Text('Friday')
Text('Saturday')
.fontColor('#FF4A24')
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
.padding(8)
//Scroll through the calendar
Scroll(this.scrollerForScroll) {
Column() {
Column() {
Text('June 2025')
.fontSize(18)
.width('100%')
.padding(8)
.textAlign(TextAlign.Center)
// Dividing line
Divider()
.color('#CCC')
Grid() {
ForEach(this.arr, (item: number) => {
GridItem() {
Text(item.toString())
.fontSize(16)
.textAlign(TextAlign.Center)
}
})
}
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
}
}
}
.width("100%")
.layoutWeight(1)
}
.width('100%')
.layoutWeight(1)
}
}
(Explanation: This improved code implements a complete calendar function on the basis of the original navigation framework, and mainly includes three core optimizations: first, the new date processing logic (getTime method) dynamically generates calendar data, and initializes the date array for June 2025 (including the blank placeholder at the beginning of the month and the actual date) on page load through the aboutToAppear lifecycle; Secondly, the interface is refactored into a three-part structure - the top navigation bar (increase the size of the icon to 28), the middle day of the week header row (marked in red for Sunday/Saturday), and the scrollable calendar area at the bottom (using the Scroller controller); Finally, the 7-column grid layout (Grid) is used to display the date, the date data is dynamically rendered through ForEach, and the month title "2025-06" and a gray dividing line are added. The current implementation completely displays the static calendar, and functions such as month switching, daily highlighting, and return logic need to be added in the future. )
Step 3: Calendar basic module completes rendering.
The sample code is as follows:
@Entry
@Component
struct Index {
private scrollerForScroll: Scroller = new Scroller();
private scrollerForList: Scroller = new Scroller();
@State listPosition: number = 0; // 0 means scrolling to the top of the List, 1 means intermediate value, and 2 means scrolling to the bottom of the List.
getTime(index: number = 0) {
let arr: string[] = []
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1 + index;
const day = date.getDate();
const week = date.getDay();
// Example: Get the day of the week on Thursday, June 5, 2025
const targetDate = new Date(year, month - 1, 1); // Note: Months are counted from 0 (5 for June)
const dayIndex = targetDate.getDay(); // Back 4 (Thursday)
const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"
, "Friday", "Saturday"];
for (let i = 0; i < dayIndex; i++) {
arr.push('')
}
// Get how many days there are in a month
const days = new Date(year, month, 0).getDate();
for (let i = 1; i < days + 1; i++) {
arr.push(i + '')
}
return arr
}
aboutToAppear(): void {
this.getTime()
}
build() {
Column() {
// Nav head navigation bar
Row() {
Image($r('sys.media.ohos_ic_public_arrow_left'))
.width(28)
.aspectRatio(1)
.fillColor(Color.Black)
.onClick(() => {
})
Text('Calendar')
.fontSize(18)
Column()
.width(28)
}
.padding(8)
.width('100%')
.backgroundColor('#50cccccc')
.justifyContent(FlexAlign.SpaceBetween)
// Date arrangement
Row() {
Text('Sunday')
.fontColor('#FF4A24')
Text('Monday')
Text('Tuesday')
Text('Wednesday')
Text('Thursday')
Text('Friday')
Text('Saturday')
.fontColor('#FF4A24')
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
.padding(8)
//Scroll through the calendar
Scroll(this.scrollerForScroll) {
Column() {
CalenderComp({ arr: this.getTime(), index: 0 })
CalenderComp({ arr: this.getTime(1), index: 1 })
CalenderComp({ arr: this.getTime(2), index: 2 })
}
}
.width("100%")
.layoutWeight(1)
}
.width('100%')
.layoutWeight(1)
}
}
@Component
struct CalenderComp {
@Prop arr: string[] = []
@Prop index: number = 0
year: number = 0
month: number = 0
aboutToAppear(): void {
this.year = (new Date()).getFullYear();
this.month = (new Date()).getMonth() + 1 + this.index
}
build() {
Column({ space: 5 }) {
Text(this.year + 'year' + this.month + 'month')
.fontSize(18)
.width('100%')
.padding(8)
.textAlign(TextAlign.Center)
// dividingLine
Divider()
.color(Color.Red)
.strokeWidth(2)
.margin({ top: 1, bottom: 10 })
Grid() {
ForEach(this.arr, (item: number) => {
GridItem() {
Text(item.toString())
.fontSize(16)
.textAlign(TextAlign.Center)
}
})
}
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
}
}
}
(Explanation: This code realizes the multi-month calendar display function through componentized refactoring, and the core optimization includes three aspects: first, the calendar display logic is extracted into an independent component, CalenderComp, and the component is reused by receiving the date array and month offset parameters by @prop; Secondly, the getTime() method is refactored to return the date array instead of modifying the member variables, and supports the dynamic generation of calendar data for three consecutive months (the current month and the next two months). Finally, the parent component displays a multi-month view in a scrolling container nested with three calendar components. Each calendar component dynamically calculates the year-month header (e.g., "2025year6month"), distinguishes the month with a red bold dividing line, and maintains a 7-column grid layout to display the date. The component-based design significantly improves code reusability and maintainability, laying the foundation for subsequent functional expansion. )
Top comments (0)