またまた顔面神経麻痺ケアアプリの話。
iPadやAndroidに対応できないかと素人なりに色々模索しているところ。(GitHub)
iPadOSにはSplit ViewやSlide Overがあるし、Androidもフォルダブルスマートフォン等増えてきたので、可変サイズに対応したい。
しかしReact Native Calendarsはそう簡単にはいかないのだ。
やりたいこと
React Native Calendarsのバージョンは1.1300.0。
Horizontal CalendarListを使用している。
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { View, SafeAreaView, ScrollView, useWindowDimensions } from 'react-native';
import { Button } from 'react-native-paper';
import { CalendarList } from 'react-native-calendars';
const HomeScreen = ({ navigation }) => {
const window = useWindowDimensions();
const [calendarKey, setCalendarKey] = useState(0);
const reloadCalendar = () => {
setCalendarKey(calendarKey + 1);
};
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<SafeAreaView>
<CalendarList
key={calendarKey}
staticHeader
calendarHeight={400}
calendarWidth={window.width}
horizontal={true}
pagingEnabled={true}
/>
<View>
<Button onPress={reloadCalendar}>今日</Button>
</View>
</SafeAreaView>
<StatusBar style="auto" />
</ScrollView>
);
};
export default HomeScreen;
しかしこれだと画面サイズが変わってもカレンダーのサイズが変わらない。
ちなみにCalendarList
のkey
を更新してもダメだった。
画面サイズが変更されたタイミングを取得
どういう方法でカレンダーをリロードするにせよ、まず画面サイズが変わったタイミングで実行しなければならない。Dimensions
を使うことにした。
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { View, SafeAreaView, ScrollView, Dimensions, useWindowDimensions } from 'react-native';
import { Button } from 'react-native-paper';
import { useFocusEffect } from '@react-navigation/native';
import { CalendarList } from 'react-native-calendars';
const HomeScreen = ({ navigation }) => {
const window = useWindowDimensions();
const [calendarKey, setCalendarKey] = useState(0);
const reloadCalendar = () => {
setCalendarKey(calendarKey + 1);
};
useFocusEffect(
React.useCallback(() => {
const handleDimensionsChange = () => {
// リロードのロジックをここに追加
};
dimensionsHandler=Dimensions.addEventListener('change',handleDimensionsChange)
return ()=>dimensionsHandler.remove()
}, [])
);
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<SafeAreaView>
<CalendarList
key={calendarKey}
staticHeader
calendarHeight={400}
calendarWidth={window.width}
horizontal={true}
pagingEnabled={true}
/>
<View>
<Button onPress={reloadCalendar}>今日</Button>
</View>
</SafeAreaView>
<StatusBar style="auto" />
</ScrollView>
);
};
export default HomeScreen;
カレンダーのリロード
カレンダーのリロードは、結局CalendarList
を出し入れするだけにした。
他の画面を表示中に画面サイズが変更される可能性も考慮し、useIsFocused
も使っている。
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { View, SafeAreaView, ScrollView, Dimensions, useWindowDimensions } from 'react-native';
import { ActivityIndicator, Button } from 'react-native-paper';
import { useFocusEffect, useIsFocused } from '@react-navigation/native';
import { CalendarList } from 'react-native-calendars';
const HomeScreen = ({ navigation }) => {
const window = useWindowDimensions();
const [calendarKey, setCalendarKey] = useState(0);
const [calendarVisibility, setCalendarVisibility] = useState(true);
const reloadCalendar = () => {
setCalendarVisibility(false);
setTimeout(() => {
setCalendarKey(calendarKey + 1);
setCalendarVisibility(true);
},100);
};
useFocusEffect(
React.useCallback(() => {
const handleDimensionsChange = () => {
// リロードのロジックをここに追加
reloadCalendar()
};
dimensionsHandler=Dimensions.addEventListener('change',handleDimensionsChange)
return ()=>dimensionsHandler.remove()
}, [])
);
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<SafeAreaView>
{useIsFocused() === false ?
<View>
<ActivityIndicator animating={true} />
</View>
: calendarVisibility ?
<CalendarList
key={calendarKey}
staticHeader
calendarHeight={400}
calendarWidth={window.width}
horizontal={true}
pagingEnabled={true}
/>
:
<View>
<ActivityIndicator animating={true} />
</View>
}
<View>
<Button onPress={reloadCalendar}>今日</Button>
</View>
</SafeAreaView>
<StatusBar style="auto" />
</ScrollView>
);
};
export default HomeScreen;
落とし穴
試したところDimensions
を使ったウィンドウサイズ変更タイミングの判定は、AppleシリコンMacではできなかった。
結局Mac対応を諦めるか、Split View & Slide Over対応を諦めるかのどちらかになりそうだ。
Split ViewとSlide Overを無効にする場合は、app.json
に次を追加する。
{
"expo": {
"ios": {
"requireFullScreen": true
}
}
}
コメント