こんにちは。207株式会社でソフトウェアエンジニアをしている id:ryo-rm です。
僕は電子書籍を読むデバイスとして Surface Duo を使っています。
見開きにしたときの表示や持ちやすさがとても好きで、読書がとても捗るデバイスです。
Surface Duoは "Dual Screen" のデバイスと Microsoft では定義しており、今回はこのDual Screen対応のためのReact Native用ライブラリ react-native-dualscreeninfo
を使って遊んでみました。
はじめに
Surface Duoは2画面デバイスで、左右の画面それぞれに別のアプリを表示したり、1つのアプリを見開き表示にして本のように持つことができるユニークなAndroidスマートフォンです。
一方で少し残念な点としては、アプリを見開き状態にしたとき、内部的にはヒンジ部分も表示領域になっているため中央部分が途切れてしまいます。
特に左右表示にしたときは、電子書籍では端の文が読めなくなってしまうなどの致命的な問題があります。
Microsoft からDual Screenのデバイスに対応するためのドキュメントが公開されており、このドキュメントに従って開発することで、この「ヒンジ問題」を解消することができるようになっています。
React Native向けには react-native-dualscreeninfo が Microsoft から提供されていて*1、このライブラリを組み込むことで Dual Screen 対応が簡単にできるようになっています。
環境について
今回は、弊社で開発している TODOCUサポーター に組み込んで検証してみました。
検証に利用したバージョンはこのようになっています。
Expo Bare Workflowで開発しており、React Native 0.68 です。
$ npx expo-env-info expo-env-info 1.0.3 environment info: System: OS: macOS 12.3.1 Shell: 5.8 - /bin/zsh Binaries: Node: 16.13.1 - ~/.nvm/versions/node/v16.13.1/bin/node Yarn: 1.22.11 - ~/207/TodocuSupporter/node_modules/.bin/yarn npm: 8.6.0 - ~/.nvm/versions/node/v16.13.1/bin/npm Watchman: 2022.03.21.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.11.2 - /Users/rk/.rbenv/shims/pod SDKs: iOS SDK: Platforms: DriverKit 21.4, iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5 Android SDK: API Levels: 28, 29, 30, 31 Build Tools: 29.0.2, 30.0.2, 30.0.3, 31.0.0, 32.0.0 System Images: android-31 | ARM 64 v8a, android-31 | Google APIs ARM 64 v8a, android-32 | Google APIs ARM 64 v8a, android-32 | Google Play ARM 64 v8a IDEs: Android Studio: 2021.1 AI-211.7628.21.2111.8309675 Xcode: 13.3.1/13E500a - /usr/bin/xcodebuild npmPackages: babel-preset-expo: ~9.1.0 => 9.1.0 expo: ^45.0.0 => 45.0.4 react: 17.0.2 => 17.0.2 react-dom: 17.0.2 => 17.0.2 react-native: 0.68.2 => 0.68.2 react-native-web: 0.17.7 => 0.17.7 npmGlobalPackages: eas-cli: 0.53.0 expo-cli: 5.4.11 Expo Workflow: bare
インストール
基本的には README に従うだけですが、手元の環境ではビルドできず、以下のエラーが出ました。
> Task :expo-modules-core:compileDebugKotlin FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':expo-modules-core:compileDebugKotlin'. > Compilation error. See log for more details
Kotlinのバージョンの問題で、こちらの環境ではREADME記載の kotlinVersion = "1.3.50"
ではビルドできなかったため、 build.gradle
内で kotlinVersion = "1.6.0"
にすることでビルドができました。
また、 Github には react-native-dualscreeninfo
以外に react-native-twopaneview
なども提供されていますが、 dualscreeninfo
にも TwoPaneView
があるため今回は他のライブラリはインストールしませんでした。*2
使ってみた
以下のようなhookを作成し、2画面になったときに画面を出し分けできるようにします。
import { DualScreenInfo, DualScreenInfoPayload, } from 'react-native-dualscreeninfo'; // 省略 const [isDualMode, setDualMode] = useState(DualScreenInfo.isSpanning) useEffect(() => { const handler = ({ isSpanning }: DualScreenInfoPayload) => { setDualMode(prev => { if (prev !== isSpanning) { return isSpanning; } return prev; }); }; DualScreenInfo.addEventListener('didUpdateSpanning', handler) return () => { DualScreenInfo.removeEventListener('didUpdateSpanning', handler) } }, [setDualMode])
isDualMode
が true
のときに TwoPaneView
を使って画面表示をするようしたら、見開き画面を実装できます!*3
if (isDualMode) { return ( <TwoPaneView leftComponent={ <View> <Text>左</Text> </View> } rightComponent={ <View> <Text>右</Text> </View> } />); } return <View />
TODOCUサポーターの適当な画面を TwoPaneView
で表示してみました。
左側に地図、右側に配送荷物の詳細情報を表示してみています。実機画像だと普通ですが、スクリーンキャプチャしてみるとヒンジ部分に空白が挿入され、意図したどおりに動作しているのが確認できました!すげ〜!
おわりに
実際に組み込むとなるといろいろ検証が必要ですが、ライブラリを使うことでかんたんにDual Screenデバイスの制御がReact Nativeでもできました。
Dual Screen対応が必須になる未来が来るのだろうか 🧐
最後にいつもの宣伝で、
207株式会社では、レガシーな物流業界の変革に挑む配達員向け効率化アプリ「TODOCUサポーター」を開発しています。 開発チームでは一緒に開発してくれるアプリエンジニア(React Native)やバックエンドエンジニアの仲間を大絶賛募集中です!
もし少しでもご興味がありましたら、以下のnotionをご覧ください!