HarmonyOS鸿蒙Next中日历三方库cjcalendar日历下面添加不了东西

HarmonyOS鸿蒙Next中日历三方库cjcalendar日历下面添加不了东西 我使用https://ohpm.openharmony.cn/#/cn/detail/cjcalendar日历三方库想要在日历下面加上自己的List列表数据但是他却显示不出来,咋办

import {
  CJCalendar,
  CJCalendarControl,
  CJCellStyle,
  CJDateItem,
  CJCalStatusParams,
  OptMode,
  SelectedStyle,
  SelectedShape,
  CJViewModel,
  WeekStartMode,
  CJDateShowBackMode
} from 'cjcalendar';


@Entry
@Component
struct CalendarDemo {
  // 控制器,用于操作日历
  controller: CJCalendarControl = new CJCalendarControl()
  // 日历状态信息
  @State calStatus: CJCalStatusParams = new CJCalStatusParams()
  // 选中的日期
  @State selectedDate: string = ''
  // 自定义样式
  @State cellStyle: CJCellStyle = new CJCellStyle()
  @State isCalendarFold: boolean = false
  @State listData: Array<string> = [
    'item1', 'item2', 'item3', 'item4', 'item5',
    'item6', 'item7', 'item8', 'item9', 'item10',
    'item11', 'item12', 'item13', 'item14', 'item15',
    'item16', 'item17', 'item18', 'item19', 'item20'
  ]

  build() {
    Column() {
      // Stack() {
      //   // 标题居中显示
      //   Text(this.selectedDate ? `选中的日期: ${this.selectedDate}` : '未选择日期')
      //     .fontSize(16)
      //     .fontColor('#333')
      //     .margin({ top: 10, bottom: 10 })
      //     .width('100%')
      //     .textAlign(TextAlign.Center)
      //   // 右侧按钮组
      //   Row({ space: 12 }) {
      //     Text('今')
      //       .fontSize(14)
      //       .fontColor('#FFFFFF')
      //       .textAlign(TextAlign.Center)
      //       .width(32)
      //       .height(32)
      //       .backgroundColor('#ffffc51a')
      //       .borderRadius(16)
      //       .onClick(() => {
      //         // 跳转到今天
      //         const today = new Date();
      //         this.controller.skipToDate(today);
      //         console.warn('跳转到今天后的selectedDate:', this.selectedDate);
      //       })
      //     Image(this.isCalendarFold ? $r('app.media.ic_expand_more_24px') : $r('app.media.ic_expand_less_48px'))
      //       .width(24)
      //       .height(24)
      //       .onClick(() => {
      //         this.isCalendarFold = !this.isCalendarFold;
      //         this.controller.setFoldStatue(this.isCalendarFold);
      //       })
      //   }
      //   .height('100%')
      //   .justifyContent(FlexAlign.End)
      //   .margin({ right: 16 }) // 整个按钮组距离右边框16
      //   .width('100%')
      // }
      // .height(50)
      // .backgroundColor(Color.Pink)
      // .width('100%')

      RelativeContainer() {
        Text(this.selectedDate ? `选中的日期: ${this.selectedDate}` : '未选择日期')
          .fontSize(16)
          .fontColor('#333')
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
        Row({ space: 12 }) {
          Text('今')
            .fontSize(14)
            .fontColor('#FFFFFF')
            .textAlign(TextAlign.Center)
            .width(32)
            .height(32)
            .backgroundColor('#ffffc51a')
            .borderRadius(16)
            .onClick(() => {
              // 跳转到今天
              const today = new Date();
              this.controller.skipToDate(today);
              console.warn('跳转到今天后的selectedDate:', this.selectedDate);
            })
          Image(this.isCalendarFold ? $r('app.media.ic_expand_more_24px') : $r('app.media.ic_expand_less_48px'))
            .width(24)
            .height(24)
            .onClick(() => {
              this.isCalendarFold = !this.isCalendarFold;
              this.controller.setFoldStatue(this.isCalendarFold);
            })
        }
        .alignRules({
          right: { anchor: '__container__', align: HorizontalAlign.End }
        })
        .margin({ right: 16 })
        .alignItems(VerticalAlign.Center)
        .height('100%')
      }
      .height(50)
      .backgroundColor(Color.Pink)
      .width('100%')

      List() {
        ForEach(
          this.listData,
          (item: string, index: number) => {
            ListItem() {
              Text(`${item}`)
                .fontSize(18)
                .fontColor('#333')
                .backgroundColor('#FFFFFF')
                .width('100%')
                .padding(20)
                .borderRadius(8)
            }
          },
          (item: string) => item
        )
      }
      .height(200)
      .backgroundColor(Color.Pink)

      // 日历
      Column() {
        CJCalendar({
          // 控制器
          controller: this.controller,

          // 操作模式:单选
          optMode: OptMode.SINGLE,

          // 视图模式:月视图
          viewModel: CJViewModel.MONTH,

          // 从周一开始
          weekStartMode: WeekStartMode.Monday,

          // 显示农历
          showLunar: false,

          // 显示节日
          showJieRi: false,

          // 显示快捷返回今天按钮
          showFastToday: false,
          //显示工具栏
          showToolbar: false,
          // 标题栏高度
          titleHeight: 60,
          // 标题格式化
          titleFormat: "yyyy年MM月",

          // 主题色
          themeColor: "#ffffc51a",

          // 显示星期栏
          showWeekTitle: true,

          // 星期栏高度
          weekTitleHeight: 40,


          // 选中样式
          selectedShape: SelectedShape.SHAPE_CIRCLE,

          // 选中风格
          selectedStyle: SelectedStyle.CLOSE,

          // 是否显示折叠按钮'
          isShowFoldView: false,

          // 是否折叠
          isFold: this.isCalendarFold,

          // 日期选择回调
          onSelectedChanged: (items: CJDateItem[]) => {
            if (items.length > 0) {
              const date = items[0];
              this.selectedDate = `${date.fullYear}-${date.month + 1}-${date.date}`;
              console.log('选择的日期:', this.selectedDate);
            }
          },

          // 月份切换回调
          onMonthChanged: (month: CJDateItem) => {
            console.log('切换到月份:', month.month + 1);
          },

          // 日期点击事件
          onCellItemClick: (item: CJDateItem) => {
            console.log('点击日期:', item.date);
            // 返回false表示不拦截默认操作
            return false;
          },

          // 初始化完成回调
          onInitFinish: () => {
            console.log('日历初始化完成');
            // 可以在这里进行数据初始化
          },

          // 自定义单元格样式
          buildCellStyle: (item: CJDateItem) => {
            const style = new CJCellStyle();

            // 设置默认字体颜色
            style.fontColor = '#333333';
            style.markFontColor = '#666666';

            // 周末特殊样式
            // if (item.week === 0 || item.week === 6) {
            //   style.fontColor = '#1890ff';
            //   style.markFontColor = '#1890ff';
            // }

            // 今天特殊样式
            if (item.isToday) {
              style.todayFontColor = '#333333'; // 字体颜色与普通日期一致
              style.todayBackgroundColor = '#00000000'; // 背景透明(或你想要的任何颜色)
              style.borderColor = '#1890ff'; // 可选:加一个蓝色边框作为提示
              style.borderWidth = 1;
              style.borderRadius = 20; // 设置为圆形
            }
            // 选中样式
            style.selectFontColor = '#ffffff';
            style.selectItemBackgroundColor = '#ff9900';

            // 禁用日期样式
            style.disabledFontColor = '#cccccc';

            // 标记样式
            style.markFontSize = 10;
            style.markFontColor = '#ff4d4f';
            style.markSelectedFontColor = '#ff4d4f';
            style.markBackgroundColor = '#fff2f0';
            style.markRadius = 4;

            return style;
          },

          // 重新构建单元格数据(添加自定义标记)
          reBuildCellItem: (cjDateItem: CJDateItem) => {
            // 为特定日期添加标记
            const today = new Date();
            const tomorrow = new Date(today);
            tomorrow.setDate(tomorrow.getDate() + 1);

            // 明天添加标记
            if (
              cjDateItem.fullYear === tomorrow.getFullYear() &&
                cjDateItem.month === tomorrow.getMonth() &&
                cjDateItem.date === tomorrow.getDate()
            ) {
              cjDateItem.markText = "明天";
            }

            // 节假日标记示例
            // if (cjDateItem.fullYear === 2024 && cjDateItem.month === 9 && cjDateItem.date === 1) {
            //   cjDateItem.markText = "国庆";
            // }

            // 禁用过去的日期
            // const itemDate = new Date(cjDateItem.fullYear, cjDateItem.month, cjDateItem.date);
            // if (itemDate < today && !this.isSameDay(itemDate, today)) {
            //   cjDateItem.disabled = true;
            // }

            return cjDateItem;
          },
          // 自定义月份底部布局
          buildMonthCustomLayout: this.CustomLayout,
          // 是否将底部用户布局添加到整体,默认是每个月
          isAttchCustomLayoutToWhole: false,
          //仅显示日期区域
          onlyShowDateArea: false

        })
          .width('100%')
          .height('100%')
      }
      .width('100%')

    }
    .width('100%')
    .height('100%')
  }

  @Builder
  CustomLayout() {
    Column() {
      List() {
        ForEach(
          this.listData,
          (item: string, index: number) => {
            ListItem() {
              Text(`${item}`)
                .fontSize(18)
                .fontColor('#333')
                .backgroundColor('#FFFFFF')
                .width('100%')
                .padding(20)
                .borderRadius(8)
            }
          },
          (item: string) => item
        )
      }
      .height(200)
      .backgroundColor(Color.Pink)

      Text('操作说明:点击日期可选中,选中日期背景为橙色。\n“明天”、“国庆”等为日期标记。')
        .fontSize(14)
        .fontColor('#1890ff')
        .textAlign(TextAlign.Center)
        .margin({
          top: 20,
          left: 20,
          right: 20,
          bottom: 10
        })
        .width('100%')

    }

  }

  // 判断是否是同一天
  isSameDay(date1: Date, date2: Date): boolean {
    return date1.getFullYear() === date2.getFullYear() &&
      date1.getMonth() === date2.getMonth() &&
      date1.getDate() === date2.getDate();
  }
}

更多关于HarmonyOS鸿蒙Next中日历三方库cjcalendar日历下面添加不了东西的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中,cjcalendar日历库添加不了内容,通常是因为该库未适配ArkTS/ArkUI,或API调用方式与鸿蒙Next不兼容。鸿蒙Next使用Stage模型和ArkTS,需确认cjcalendar是否支持该框架。检查库的版本是否针对HarmonyOS Next开发,并查看官方文档中关于日历组件数据绑定的示例。

更多关于HarmonyOS鸿蒙Next中日历三方库cjcalendar日历下面添加不了东西的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


根据你提供的代码,问题在于 buildMonthCustomLayout@Builder 方法 CustomLayout 的作用域。

@Builder 方法默认无法直接访问组件内的状态变量(如 this.listData)。在你的代码中,CustomLayout 方法内部的 ForEach(this.listData, ...) 语句中的 this 指向的是 Builder 的上下文,而非你的 CalendarDemo 组件,因此 this.listData 是未定义的,导致列表无法渲染。

解决方案:

CustomLayout 方法修改为带参数的函数式 @Builder,并将 listData 作为参数传入。

  1. 修改 CustomLayout 方法的定义和调用:

    // 1. 修改方法定义,添加参数
    @Builder
    CustomLayout(listData: Array<string>) {
      Column() {
        List() {
          ForEach(
            listData, // 使用传入的参数
            (item: string, index: number) => {
              ListItem() {
                Text(`${item}`)
                  .fontSize(18)
                  .fontColor('#333')
                  .backgroundColor('#FFFFFF')
                  .width('100%')
                  .padding(20)
                  .borderRadius(8)
              }
            },
            (item: string) => item
          )
        }
        .height(200)
        .backgroundColor(Color.Pink)
    
        Text('操作说明:点击日期可选中,选中日期背景为橙色。\n“明天”、“国庆”等为日期标记。')
          .fontSize(14)
          .fontColor('#1890ff')
          .textAlign(TextAlign.Center)
          .margin({
            top: 20,
            left: 20,
            right: 20,
            bottom: 10
          })
          .width('100%')
      }
    }
    
  2. CJCalendar 组件调用时传入 listData

    CJCalendar({
      // ... 其他参数保持不变
      buildMonthCustomLayout: () => {
        // 调用时传入当前组件的 listData
        this.CustomLayout(this.listData)
      },
      // ... 其他参数保持不变
    })
    

修改后,CustomLayout 将能正确接收到 listData 数据,并在日历底部渲染出你的列表。

核心原因: @Builder 装饰的方法有其独立的作用域。当它需要访问组件状态时,必须通过参数显式传递。直接使用 this 会指向错误的上下文对象,导致数据访问失败。

回到顶部