最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

ReactNative項目OpenHarmony三方庫集成實戰(zhàn)指南:react-native-calendar-events(讀取不到日歷里新增的事件,待排查)

 更新時間:2026年04月09日 09:52:46   作者:早點睡390  
文章介紹了react-native-calendar-events庫,這是一個強大的日歷事件庫,支持讀寫系統(tǒng)日歷,實現(xiàn)日程管理功能,文章說明了其安裝配置、核心功能、API使用方法,并提供了注意事項和完整示例,適用于React Native開發(fā)中的日歷事件管理,感興趣的朋友一起看看吧

項目基于 RN 0.72.90 開發(fā)

?? 前言

在移動應(yīng)用開發(fā)中,日歷事件管理是一項常見需求,特別是在日程管理、會議提醒、活動安排等場景中。react-native-calendar-events 是一個功能強大的日歷事件庫,提供了讀取和寫入系統(tǒng)日歷的能力,支持創(chuàng)建、查詢、更新和刪除日歷事件,是實現(xiàn)日程管理功能的理想選擇。

?? 庫簡介

基本信息

  • 庫名稱: react-native-calendar-events
  • 版本信息: 2.2.1 支持 RN 0.72 版本
  • 官方倉庫: https://github.com/wmcmahan/react-native-calendar-events
  • 鴻蒙倉庫: https://atomgit.com/openharmony-sig/rntpc_react-native-calendar-events
  • 主要功能:
    • ?? 日歷權(quán)限管理
    • ?? 日歷增刪改查
    • ?? 事件創(chuàng)建與編輯
    • ? 提醒設(shè)置
    • ?? 重復(fù)規(guī)則配置
    • ?? 參與者管理
    • ?? 跨平臺支持(iOS、Android、HarmonyOS)

為什么需要日歷事件庫?

特性原生方案react-native-calendar-events
跨平臺一致性?? 需分別開發(fā)? 統(tǒng)一 API
權(quán)限管理?? 手動處理? 自動處理
事件操作?? 需封裝? 開箱即用
重復(fù)規(guī)則?? 復(fù)雜實現(xiàn)? 內(nèi)置支持
HarmonyOS 支持?? 需適配? 完善適配

核心功能

功能說明HarmonyOS 支持
requestPermissions請求日歷權(quán)限?
checkPermissions檢查權(quán)限狀態(tài)?
findCalendars獲取所有日歷?
saveCalendar創(chuàng)建日歷?
removeCalendar刪除日歷?
findEventById根據(jù)ID查詢事件?
fetchAllEvents獲取所有事件?
saveEvent創(chuàng)建/更新事件?
removeEvent刪除事件?

兼容性驗證

在以下環(huán)境驗證通過:

  • RNOH: 0.72.90; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.2; ROM: 6.0.0

?? 安裝步驟

1. 安裝依賴

# RN 0.72 版本
npm install @react-native-ohos/react-native-calendar-events@2.2.1-rc.1
# 或者使用 yarn
yarn add @react-native-ohos/react-native-calendar-events@2.2.1-rc.1

2. 驗證安裝

安裝完成后,檢查 package.json 文件:

{
  "dependencies": {
    "@react-native-ohos/react-native-calendar-events": "^2.2.1-rc.1"
  }
}

?? HarmonyOS 平臺配置 ?

1. 引入原生端代碼

打開 harmony/entry/oh-package.json5,添加以下依賴:

"dependencies": {
  "@react-native-ohos/react-native-calendar-events": "file:../../node_modules/@react-native-ohos/react-native-calendar-events/harmony/calendar_events.har"
}

點擊右上角的 sync 按鈕,或者在終端執(zhí)行:

cd entry
ohpm install

2. 配置 CMakeLists

打開 entry/src/main/cpp/CMakeLists.txt,添加:

+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
# RNOH_BEGIN: manual_package_linking_1
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-calendar-events/src/main/cpp" ./calendar_events)
# RNOH_END: manual_package_linking_1
# RNOH_BEGIN: manual_package_linking_2
+ target_link_libraries(rnoh_app PUBLIC rnoh_calendar_events)
# RNOH_END: manual_package_linking_2

3. 引入 CalendarEventPackage

打開 entry/src/main/cpp/PackageProvider.cpp,添加:

#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "CalendarEventsPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
      std::make_shared<RNOHGeneratedPackage>(ctx),
      + std::make_shared<CalendarEventsPackage>(ctx)
    };
}

打開 entry/src/main/ets/RNPackagesFactory.ets,添加:

+ import { CalendarEventPackage } from '@react-native-ohos/react-native-calendar-events/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    new SamplePackage(ctx),
    + new CalendarEventPackage(ctx)
  ];
}

4. 配置權(quán)限

entry/src/main/module.json5 中添加日歷權(quán)限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.READ_CALENDAR",
        "reason": "$string:Access_calendar",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.WRITE_CALENDAR",
        "reason": "$string:Access_calendar",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when": "inuse"
        }
      }
    ]
  }
}

5. 添加權(quán)限說明

打開 entry/src/main/resources/base/element/string.json,添加權(quán)限說明:

{
  "string": [
    {
      "name": "Access_calendar",
      "value": "用于訪問和管理日歷事件"
    }
  ]
}

?? API 詳解

requestPermissions - 請求日歷權(quán)限

請求日歷訪問權(quán)限,必須在訪問日歷數(shù)據(jù)之前調(diào)用。

類型(readOnly?: boolean) => Promise<'authorized' | 'denied' | 'restricted' | 'undetermined'>

參數(shù)

  • readOnly: 是否只請求讀取權(quán)限,默認為 false

返回值

  • authorized: 已授權(quán)
  • denied: 已拒絕
  • restricted: 受限制(如家長控制)
  • undetermined: 未確定

使用場景

  • 應(yīng)用首次啟動時請求權(quán)限
  • 用戶拒絕后重新請求
import RNCalendarEvents from 'react-native-calendar-events';
const requestPermission = async () => {
  const status = await RNCalendarEvents.requestPermissions();
  if (status === 'authorized') {
    console.log('日歷權(quán)限已授權(quán)');
  } else {
    console.log('日歷權(quán)限被拒絕');
  }
};

checkPermissions - 檢查權(quán)限狀態(tài)

檢查當前的日歷權(quán)限狀態(tài),不會彈出權(quán)限請求對話框。

類型(readOnly?: boolean) => Promise<'authorized' | 'denied' | 'restricted' | 'undetermined'>

參數(shù)

  • readOnly: 是否只檢查讀取權(quán)限,默認為 false

使用場景

  • 在執(zhí)行日歷操作前檢查權(quán)限
  • 根據(jù)權(quán)限狀態(tài)顯示不同的 UI
import RNCalendarEvents from 'react-native-calendar-events';
const checkPermission = async () => {
  const status = await RNCalendarEvents.checkPermissions();
  console.log('當前權(quán)限狀態(tài):', status);
  return status === 'authorized';
};

findCalendars - 獲取所有日歷

獲取設(shè)備上所有可用的日歷列表。

類型() => Promise<Calendar[]>

返回值:日歷對象數(shù)組,包含以下屬性:

屬性類型說明
idstring日歷唯一標識
titlestring日歷標題
sourceobject日歷來源
colorstring日歷顏色
allowsModificationsboolean是否允許修改
typestring日歷類型

使用場景

  • 顯示日歷列表供用戶選擇
  • 獲取默認日歷 ID
import RNCalendarEvents from 'react-native-calendar-events';
const getCalendars = async () => {
  const calendars = await RNCalendarEvents.findCalendars();
  calendars.forEach((calendar) => {
    console.log('日歷:', calendar.title, 'ID:', calendar.id);
  });
  return calendars;
};

saveCalendar - 創(chuàng)建日歷

創(chuàng)建一個新的日歷。

類型(options: CalendarOptions) => Promise<string>

參數(shù)

屬性類型必填說明
titlestring日歷標題
typestring日歷類型
displayNamestring顯示名稱
colorstring日歷顏色

返回值:新創(chuàng)建日歷的 ID

import RNCalendarEvents from 'react-native-calendar-events';
const createCalendar = async () => {
  const calendarId = await RNCalendarEvents.saveCalendar({
    title: '我的日歷',
    type: 'local',
    displayName: '個人日程',
    color: '#FF5722',
  });
  console.log('創(chuàng)建日歷成功, ID:', calendarId);
  return calendarId;
};

removeCalendar - 刪除日歷

根據(jù) ID 刪除指定的日歷。

類型(id: string) => Promise<boolean>

參數(shù)

  • id: 日歷 ID

返回值:是否刪除成功

import RNCalendarEvents from 'react-native-calendar-events';
const deleteCalendar = async (calendarId: string) => {
  const success = await RNCalendarEvents.removeCalendar(calendarId);
  console.log('刪除日歷:', success ? '成功' : '失敗');
  return success;
};

findEventById - 根據(jù) ID 查詢事件

根據(jù)事件 ID 獲取單個事件的詳細信息。

類型(id: string) => Promise<Event | null>

參數(shù)

  • id: 事件 ID

返回值:事件對象,如果未找到則返回 null

事件對象屬性

屬性類型說明
idstring事件唯一標識
titlestring事件標題
locationstring事件地點
startDatestring開始時間
endDatestring結(jié)束時間
allDayboolean是否全天事件
descriptionstring事件描述
calendarIdstring所屬日歷 ID
attendeesarray參與者列表
recurrenceRuleobject重復(fù)規(guī)則
remindersarray提醒列表
import RNCalendarEvents from 'react-native-calendar-events';
const getEventById = async (eventId: string) => {
  const event = await RNCalendarEvents.findEventById(eventId);
  if (event) {
    console.log('事件標題:', event.title);
    console.log('開始時間:', event.startDate);
  }
  return event;
};

fetchAllEvents - 獲取所有事件

獲取指定時間范圍內(nèi)的所有事件。

類型(startDate: string, endDate: string, calendars?: string[]) => Promise<Event[]>

參數(shù)

參數(shù)類型必填說明
startDatestring開始時間(時間戳字符串)
endDatestring結(jié)束時間(時間戳字符串)
calendarsstring[]要查詢的日歷 ID 列表

使用場景

  • 顯示日程列表
  • 日歷視圖數(shù)據(jù)源
  • 查詢特定時間段的事件
import RNCalendarEvents from 'react-native-calendar-events';
const getEvents = async () => {
  const now = Date.now();
  const startDate = now.toString();
  const endDate = (now + 7 * 24 * 60 * 60 * 1000).toString();
  const events = await RNCalendarEvents.fetchAllEvents(startDate, endDate);
  events.forEach((event) => {
    console.log('事件:', event.title, '開始:', event.startDate);
  });
  return events;
};

saveEvent - 創(chuàng)建/更新事件

創(chuàng)建新事件或更新已有事件。如果 details 中包含 id,則更新該事件;否則創(chuàng)建新事件。

類型(title: string, details?: EventDetails, options?: SaveEventOptions) => Promise<string>

參數(shù)

title: 事件標題

details: 事件詳情

屬性類型必填說明
idstring事件 ID(更新時)
typenumber事件類型
titlestring事件標題
locationobject地點信息
startTimenumber開始時間(毫秒)
endTimenumber結(jié)束時間(毫秒)
isAllDayboolean是否全天事件
attendeearray參與者列表
timeZonestring時區(qū)
reminderTimenumber[]提醒時間列表
recurrenceRuleobject重復(fù)規(guī)則
descriptionstring事件描述

location 對象

屬性類型說明
locationstring地點名稱
longitudenumber經(jīng)度
latitudenumber緯度

recurrenceRule 對象

屬性類型說明
recurrenceFrequencynumber重復(fù)頻率(1=每日,2=每周等)
expirenumber過期時間(0表示永不過期)

返回值:事件的 ID

import RNCalendarEvents from 'react-native-calendar-events';
const createEvent = async () => {
  const now = Date.now();
  const eventId = await RNCalendarEvents.saveEvent('項目會議', {
    title: '項目會議',
    startTime: now + 60 * 60 * 1000,
    endTime: now + 2 * 60 * 60 * 1000,
    location: {
      location: '會議室A',
      longitude: 116.397,
      latitude: 39.908,
    },
    description: '討論項目進度',
    isAllDay: false,
    reminderTime: [now + 30 * 60 * 1000],
  });
  console.log('創(chuàng)建事件成功, ID:', eventId);
  return eventId;
};
const updateEvent = async (eventId: string) => {
  const now = Date.now();
  const newEventId = await RNCalendarEvents.saveEvent('項目會議(已更新)', {
    id: eventId,
    title: '項目會議(已更新)',
    startTime: now + 2 * 60 * 60 * 1000,
    endTime: now + 3 * 60 * 60 * 1000,
    description: '會議時間已調(diào)整',
  });
  console.log('更新事件成功');
  return newEventId;
};

removeEvent - 刪除事件

根據(jù) ID 刪除指定的事件。

類型(id: string, options?: { futureEvents?: boolean }) => Promise<boolean>

參數(shù)

參數(shù)類型必填說明
idstring事件 ID
futureEventsboolean是否刪除未來的重復(fù)事件

返回值:是否刪除成功

import RNCalendarEvents from 'react-native-calendar-events';
const deleteEvent = async (eventId: string) => {
  const success = await RNCalendarEvents.removeEvent(eventId);
  console.log('刪除事件:', success ? '成功' : '失敗');
  return success;
};

?? 完整示例

import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  TouchableOpacity,
  SafeAreaView,
  StatusBar,
  Alert,
  TextInput,
  Switch,
  TouchableWithoutFeedback,
} from 'react-native';
import RNCalendarEvents from 'react-native-calendar-events';
interface Calendar {
  id: string;
  title: string;
  type?: string;
  displayName?: string;
}
interface Event {
  id: string;
  title: string;
  startDate: string;
  endDate?: string;
  location?: string;
  description?: string;
  allDay?: boolean;
}
const App: React.FC = () => {
  const [calendars, setCalendars] = useState<Calendar[]>([]);
  const [events, setEvents] = useState<Event[]>([]);
  const [isAuthorized, setIsAuthorized] = useState(false);
  const [showForm, setShowForm] = useState(false);
  const [eventTitle, setEventTitle] = useState('');
  const [eventDescription, setEventDescription] = useState('');
  const [eventLocation, setEventLocation] = useState('');
  const [isAllDay, setIsAllDay] = useState(false);
  useEffect(() => {
    checkPermission();
  }, []);
  const checkPermission = async () => {
    const status = await RNCalendarEvents.checkPermissions();
    setIsAuthorized(status === 'authorized');
    if (status === 'authorized') {
      loadCalendars();
      loadEvents();
    }
  };
  const requestPermission = async () => {
    const status = await RNCalendarEvents.requestPermissions();
    setIsAuthorized(status === 'authorized');
    if (status === 'authorized') {
      loadCalendars();
      loadEvents();
    } else {
      Alert.alert('權(quán)限被拒絕', '請在設(shè)置中允許訪問日歷');
    }
  };
  const loadCalendars = async () => {
    try {
      const calendarList = await RNCalendarEvents.findCalendars();
      setCalendars(calendarList);
    } catch (error) {
      console.error('獲取日歷失敗:', error);
    }
  };
  const loadEvents = async () => {
    try {
      const now = new Date();
      const startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString();
      const endDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString();
      const eventList = await RNCalendarEvents.fetchAllEvents(startDate, endDate);
      setEvents(eventList);
    } catch (error) {
      console.error('獲取事件失敗:', error);
    }
  };
  const createEvent = async () => {
    if (!eventTitle.trim()) {
      Alert.alert('提示', '請輸入事件標題');
      return;
    }
    try {
      const now = new Date();
      let startDate: string;
      let endDate: string;
      if (isAllDay) {
        const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
        const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
        startDate = today.toISOString();
        endDate = tomorrow.toISOString();
      } else {
        startDate = new Date(now.getTime() + 60 * 60 * 1000).toISOString();
        endDate = new Date(now.getTime() + 2 * 60 * 60 * 1000).toISOString();
      }
      const eventId = await RNCalendarEvents.saveEvent(eventTitle, {
        startDate,
        endDate,
        location: eventLocation || undefined,
        description: eventDescription,
        allDay: isAllDay,
      });
      Alert.alert('成功', '事件創(chuàng)建成功');
      setShowForm(false);
      setEventTitle('');
      setEventDescription('');
      setEventLocation('');
      setIsAllDay(false);
      loadEvents();
    } catch (error) {
      console.error('創(chuàng)建事件失敗:', error);
      Alert.alert('錯誤', '創(chuàng)建事件失敗');
    }
  };
  const deleteEvent = async (eventId: string) => {
    Alert.alert('確認刪除', '確定要刪除這個事件嗎?', [
      { text: '取消', style: 'cancel' },
      {
        text: '刪除',
        style: 'destructive',
        onPress: async () => {
          try {
            await RNCalendarEvents.removeEvent(eventId);
            Alert.alert('成功', '事件已刪除');
            loadEvents();
          } catch (error) {
            console.error('刪除事件失敗:', error);
            Alert.alert('錯誤', '刪除事件失敗');
          }
        },
      },
    ]);
  };
  const formatDate = (dateString: string) => {
    try {
      const date = new Date(dateString);
      if (isNaN(date.getTime())) {
        return dateString;
      }
      const year = date.getUTCFullYear();
      const month = String(date.getUTCMonth() + 1).padStart(2, '0');
      const day = String(date.getUTCDate()).padStart(2, '0');
      const hours = String(date.getUTCHours()).padStart(2, '0');
      const minutes = String(date.getUTCMinutes()).padStart(2, '0');
      return `${year}-${month}-${day} ${hours}:${minutes}`;
    } catch {
      return dateString;
    }
  };
  const getLocationText = (location: Event['location']) => {
    return location || '';
  };
  if (!isAuthorized) {
    return (
      <SafeAreaView style={styles.container}>
        <StatusBar barStyle="dark-content" backgroundColor="#FFFFFF" />
        <View style={styles.permissionContainer}>
          <Text style={styles.permissionTitle}>日歷權(quán)限</Text>
          <Text style={styles.permissionText}>
            需要日歷權(quán)限才能管理您的日程事件
          </Text>
          <TouchableOpacity style={styles.permissionButton} onPress={requestPermission}>
            <Text style={styles.permissionButtonText}>授權(quán)訪問日歷</Text>
          </TouchableOpacity>
        </View>
      </SafeAreaView>
    );
  }
  return (
    <SafeAreaView style={styles.container}>
      <StatusBar barStyle="dark-content" backgroundColor="#FFFFFF" />
      <View style={styles.header}>
        <Text style={styles.headerTitle}>日歷事件管理</Text>
        <TouchableOpacity
          style={styles.addButton}
          onPress={() => setShowForm(true)}
        >
          <Text style={styles.addButtonText}>+ 新建</Text>
        </TouchableOpacity>
      </View>
      <ScrollView style={styles.content}>
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>日歷列表 ({calendars.length})</Text>
          {calendars.length === 0 ? (
            <Text style={styles.emptyText}>暫無日歷</Text>
          ) : (
            calendars.map((calendar, index) => (
              <View key={calendar.id || index} style={styles.calendarItem}>
                <View style={styles.calendarColor} />
                <View style={styles.calendarInfo}>
                  <Text style={styles.calendarTitle}>{calendar.title || '未命名日歷'}</Text>
                  <Text style={styles.calendarType}>類型: {calendar.type || '本地'}</Text>
                </View>
              </View>
            ))
          )}
        </View>
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>近期事件 ({events.length})</Text>
          {events.length === 0 ? (
            <View style={styles.emptyContainer}>
              <Text style={styles.emptyText}>暫無事件</Text>
              <Text style={styles.emptyHint}>點擊右上角"新建"創(chuàng)建事件</Text>
            </View>
          ) : (
            events.map((event) => (
              <View key={event.id} style={styles.eventItem}>
                <View style={styles.eventHeader}>
                  <Text style={styles.eventTitle}>{event.title}</Text>
                  <TouchableOpacity onPress={() => deleteEvent(event.id)}>
                    <Text style={styles.deleteText}>刪除</Text>
                  </TouchableOpacity>
                </View>
                <Text style={styles.eventTime}>開始: {formatDate(event.startDate)}</Text>
                {event.endDate && (
                  <Text style={styles.eventTime}>結(jié)束: {formatDate(event.endDate)}</Text>
                )}
                {event.location && (
                  <Text style={styles.eventLocation}>?? {getLocationText(event.location)}</Text>
                )}
                {event.description && (
                  <Text style={styles.eventDescription}>{event.description}</Text>
                )}
              </View>
            ))
          )}
        </View>
      </ScrollView>
      {showForm && (
        <TouchableWithoutFeedback onPress={() => setShowForm(false)}>
          <View style={styles.overlay}>
            <TouchableWithoutFeedback onPress={() => {}}>
              <View style={styles.formContainer}>
                <Text style={styles.formTitle}>新建事件</Text>
                <Text style={styles.inputLabel}>事件標題</Text>
                <TextInput
                  style={styles.input}
                  placeholder="請輸入事件標題"
                  value={eventTitle}
                  onChangeText={setEventTitle}
                />
                <Text style={styles.inputLabel}>地點(可選)</Text>
                <TextInput
                  style={styles.input}
                  placeholder="請輸入地點"
                  value={eventLocation}
                  onChangeText={setEventLocation}
                />
                <Text style={styles.inputLabel}>描述(可選)</Text>
                <TextInput
                  style={[styles.input, styles.textArea]}
                  placeholder="請輸入描述"
                  value={eventDescription}
                  onChangeText={setEventDescription}
                  multiline
                />
                <View style={styles.switchRow}>
                  <Text style={styles.switchLabel}>全天事件</Text>
                  <Switch value={isAllDay} onValueChange={setIsAllDay} />
                </View>
                <View style={styles.formButtons}>
                  <TouchableOpacity
                    style={[styles.formButton, styles.cancelButton]}
                    onPress={() => setShowForm(false)}
                  >
                    <Text style={styles.cancelButtonText}>取消</Text>
                  </TouchableOpacity>
                  <TouchableOpacity
                    style={[styles.formButton, styles.confirmButton]}
                    onPress={createEvent}
                  >
                    <Text style={styles.confirmButtonText}>創(chuàng)建</Text>
                  </TouchableOpacity>
                </View>
              </View>
            </TouchableWithoutFeedback>
          </View>
        </TouchableWithoutFeedback>
      )}
    </SafeAreaView>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5F5F5',
  },
  permissionContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  permissionTitle: {
    fontSize: 24,
    fontWeight: '700',
    color: '#333333',
    marginBottom: 12,
  },
  permissionText: {
    fontSize: 16,
    color: '#666666',
    textAlign: 'center',
    marginBottom: 24,
  },
  permissionButton: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 32,
    paddingVertical: 14,
    borderRadius: 8,
  },
  permissionButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: '600',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: 16,
    backgroundColor: '#FFFFFF',
    borderBottomWidth: 1,
    borderBottomColor: '#E5E5EA',
  },
  headerTitle: {
    fontSize: 20,
    fontWeight: '700',
    color: '#333333',
  },
  addButton: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 6,
  },
  addButtonText: {
    color: '#FFFFFF',
    fontSize: 14,
    fontWeight: '600',
  },
  content: {
    flex: 1,
    padding: 16,
  },
  section: {
    backgroundColor: '#FFFFFF',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#333333',
    marginBottom: 12,
  },
  calendarItem: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#F0F0F0',
  },
  calendarColor: {
    width: 12,
    height: 12,
    borderRadius: 6,
    backgroundColor: '#007AFF',
    marginRight: 12,
  },
  calendarInfo: {
    flex: 1,
  },
  calendarTitle: {
    fontSize: 16,
    color: '#333333',
    fontWeight: '500',
  },
  calendarType: {
    fontSize: 14,
    color: '#999999',
    marginTop: 2,
  },
  emptyContainer: {
    alignItems: 'center',
    paddingVertical: 32,
  },
  emptyText: {
    fontSize: 16,
    color: '#999999',
  },
  emptyHint: {
    fontSize: 14,
    color: '#CCCCCC',
    marginTop: 8,
  },
  eventItem: {
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#F0F0F0',
  },
  eventHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  eventTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333333',
    flex: 1,
  },
  deleteText: {
    fontSize: 14,
    color: '#FF3B30',
    marginLeft: 12,
  },
  eventTime: {
    fontSize: 14,
    color: '#666666',
    marginTop: 4,
  },
  eventLocation: {
    fontSize: 14,
    color: '#666666',
    marginTop: 4,
  },
  eventDescription: {
    fontSize: 14,
    color: '#999999',
    marginTop: 4,
  },
  overlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'rgba(0,0,0,0.5)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  formContainer: {
    backgroundColor: '#FFFFFF',
    borderRadius: 12,
    padding: 20,
    width: '90%',
    maxWidth: 400,
  },
  formTitle: {
    fontSize: 20,
    fontWeight: '700',
    color: '#333333',
    marginBottom: 20,
    textAlign: 'center',
  },
  inputLabel: {
    fontSize: 14,
    color: '#666666',
    marginBottom: 4,
  },
  input: {
    borderWidth: 1,
    borderColor: '#E5E5EA',
    borderRadius: 8,
    paddingHorizontal: 16,
    paddingVertical: 12,
    fontSize: 16,
    marginBottom: 12,
  },
  textArea: {
    height: 80,
    textAlignVertical: 'top',
  },
  switchRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingVertical: 8,
    marginBottom: 20,
  },
  switchLabel: {
    fontSize: 16,
    color: '#333333',
  },
  formButtons: {
    flexDirection: 'row',
    gap: 12,
  },
  formButton: {
    flex: 1,
    paddingVertical: 14,
    borderRadius: 8,
    alignItems: 'center',
  },
  cancelButton: {
    backgroundColor: '#F0F0F0',
  },
  cancelButtonText: {
    fontSize: 16,
    color: '#666666',
    fontWeight: '600',
  },
  confirmButton: {
    backgroundColor: '#007AFF',
  },
  confirmButtonText: {
    fontSize: 16,
    color: '#FFFFFF',
    fontWeight: '600',
  },
});
export default App;

?? 注意事項

1. 權(quán)限配置

  • 必須在 module.json5 中配置 READ_CALENDARWRITE_CALENDAR 權(quán)限
  • 權(quán)限說明文案需要在 string.json 中定義
  • 首次使用時需要調(diào)用 requestPermissions() 請求權(quán)限

2. 時間格式

  • fetchAllEvents 的參數(shù)需要使用時間戳字符串
  • saveEventstartTimeendTime 使用毫秒時間戳
  • 時間戳需要轉(zhuǎn)換為字符串傳遞

3. 日歷 ID

  • 創(chuàng)建事件前需要確保有可用的日歷
  • 可以通過 findCalendars() 獲取日歷列表
  • 建議使用系統(tǒng)默認日歷或創(chuàng)建專用日歷

4. 事件更新

  • 更新事件時需要在 details 中傳入事件 ID
  • 更新會覆蓋原有的事件信息
  • 建議先查詢事件詳情再進行更新

5. 重復(fù)事件

  • recurrenceFrequency 值:1=每日,2=每周,3=每月,4=每年
  • expire 為 0 表示永不過期
  • 刪除重復(fù)事件時可以指定 futureEvents 參數(shù)

6. 錯誤處理

  • 所有 API 都返回 Promise,需要使用 try-catch 捕獲錯誤
  • 權(quán)限被拒絕時需要引導(dǎo)用戶到設(shè)置中開啟
  • 日歷操作失敗時需要給用戶明確的錯誤提示

7. 性能優(yōu)化

  • 查詢事件時指定合理的時間范圍
  • 避免頻繁查詢大量事件
  • 建議緩存日歷列表減少查詢次數(shù)

到此這篇關(guān)于ReactNative項目OpenHarmony三方庫集成實戰(zhàn)指南:react-native-calendar-events(讀取不到日歷里新增的事件,待排查)的文章就介紹到這了,更多相關(guān)react-native-calendar-events庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React 數(shù)據(jù)獲取條件競爭原理解析

    React 數(shù)據(jù)獲取條件競爭原理解析

    這篇文章主要為大家介紹了React 數(shù)據(jù)獲取條件競爭原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • 六分鐘帶你快速學(xué)會react中的useMemo

    六分鐘帶你快速學(xué)會react中的useMemo

    簡單說React.memo()是通過校驗props中的數(shù)據(jù)是否改變的來決定組件是否需要重新渲染的一種緩存技術(shù),下面這篇文章主要給大家介紹了關(guān)于如何快速學(xué)會react中useMemo的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • react搭建在線編輯html的站點通過引入grapes實現(xiàn)在線拖拉拽編輯html

    react搭建在線編輯html的站點通過引入grapes實現(xiàn)在線拖拉拽編輯html

    Grapes插件是一種用于Web開發(fā)的開源工具,可以幫助用戶快速創(chuàng)建動態(tài)和交互式的網(wǎng)頁元素,它還支持多語言和多瀏覽器,適合開發(fā)響應(yīng)式網(wǎng)頁和移動應(yīng)用程序,這篇文章主要介紹了react搭建在線編輯html的站點通過引入grapes實現(xiàn)在線拖拉拽編輯html,需要的朋友可以參考下
    2023-08-08
  • 在?React?中使用?i18next的示例

    在?React?中使用?i18next的示例

    這篇文章主要介紹了在?React?中使用?i18next,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • 詳解使用create-react-app添加css modules、sasss和antd

    詳解使用create-react-app添加css modules、sasss和antd

    這篇文章主要介紹了詳解使用create-react-app添加css modules、sasss和antd,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • React?Router?v6路由懶加載的2種方式小結(jié)

    React?Router?v6路由懶加載的2種方式小結(jié)

    React?Router?v6?的路由懶加載有2種實現(xiàn)方式,1是使用react-router自帶的?route.lazy,2是使用React自帶的?React.lazy,下面我們就來看看它們的具體實現(xiàn)方法吧
    2024-04-04
  • React特征學(xué)習之Form格式示例詳解

    React特征學(xué)習之Form格式示例詳解

    這篇文章主要為大家介紹了React特征學(xué)習之Form格式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • react表單受控的實現(xiàn)方案

    react表單受控的實現(xiàn)方案

    數(shù)據(jù)的受控控制一直是react里的一個痛點,當我想要實現(xiàn)一個輸入框的受控控制時,我需要定義一個onChange和value,手動去實現(xiàn)數(shù)據(jù)的綁定,本文小編給大家介紹了react表單受控的實現(xiàn)方案,需要的朋友可以參考下
    2023-12-12
  • React?Hooks使用startTransition與useTransition教程示例

    React?Hooks使用startTransition與useTransition教程示例

    這篇文章主要為大家介紹了React?Hooks使用startTransition與useTransition教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • React利用lazy+Suspense實現(xiàn)路由懶加載

    React利用lazy+Suspense實現(xiàn)路由懶加載

    這篇文章主要為大家詳細介紹了React如何利用lazy+Suspense實現(xiàn)路由懶加載,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-06-06

最新評論

微山县| 巨鹿县| 青铜峡市| 东乌珠穆沁旗| 柏乡县| 永州市| 米林县| 岳普湖县| 洱源县| 望谟县| 华宁县| 澄城县| 灵寿县| 洛川县| 深圳市| 扎鲁特旗| 砚山县| 新津县| 屏南县| 香河县| 壤塘县| 晴隆县| 赤城县| 长泰县| 安康市| 长丰县| 夏邑县| 阿勒泰市| 法库县| 大埔县| 潜江市| 遵义县| 大理市| 林周县| 旺苍县| 永定县| 白山市| 陈巴尔虎旗| 卢氏县| 金溪县| 响水县|