207 Tech Blog

テクノロジーで物流を変える 207 (ニーマルナナ) 株式会社のテックブログ

時代はDual Screen! マイクロソフトが提供している react-native-dualscreeninfo を使ってみた

こんにちは。207株式会社でソフトウェアエンジニアをしている id:ryo-rm です。
僕は電子書籍を読むデバイスとして Surface Duo を使っています。
見開きにしたときの表示や持ちやすさがとても好きで、読書がとても捗るデバイスです。

Surface Duoは "Dual Screen" のデバイスMicrosoft では定義しており、今回はこのDual Screen対応のためのReact Native用ライブラリ react-native-dualscreeninfo を使って遊んでみました。

Surface Duo
Surface Duo

はじめに

Surface Duoは2画面デバイスで、左右の画面それぞれに別のアプリを表示したり、1つのアプリを見開き表示にして本のように持つことができるユニークなAndroidスマートフォンです。

一方で少し残念な点としては、アプリを見開き状態にしたとき、内部的にはヒンジ部分も表示領域になっているため中央部分が途切れてしまいます。
特に左右表示にしたときは、電子書籍では端の文が読めなくなってしまうなどの致命的な問題があります。

Microsoft からDual Screenのデバイスに対応するためのドキュメントが公開されており、このドキュメントに従って開発することで、この「ヒンジ問題」を解消することができるようになっています。

docs.microsoft.com

React Native向けには react-native-dualscreeninfoMicrosoft から提供されていて*1、このライブラリを組み込むことで Dual Screen 対応が簡単にできるようになっています。

www.npmjs.com

環境について

今回は、弊社で開発している 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

github.com

使ってみた

以下のような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])

isDualModetrue のときに TwoPaneView を使って画面表示をするようしたら、見開き画面を実装できます!*3

  if (isDualMode) {
    return (
      <TwoPaneView
        leftComponent={
          <View>
            <Text></Text>
          </View>
        }
        rightComponent={
          <View>
            <Text></Text>
          </View>
        }
      />);
  }
  return <View />

TODOCUサポーターの適当な画面を TwoPaneView で表示してみました。

TwoPaneViewで表示してみたときの実機画像&quot;
TwoPaneViewで表示してみたときの実機画像

左側に地図、右側に配送荷物の詳細情報を表示してみています。実機画像だと普通ですが、スクリーンキャプチャしてみるとヒンジ部分に空白が挿入され、意図したどおりに動作しているのが確認できました!すげ〜!

スクリーンをキャプチャした図
スクリーンをキャプチャした図

おわりに

実際に組み込むとなるといろいろ検証が必要ですが、ライブラリを使うことでかんたんにDual Screenデバイスの制御がReact Nativeでもできました。
Dual Screen対応が必須になる未来が来るのだろうか 🧐

最後にいつもの宣伝で、

207株式会社では、レガシーな物流業界の変革に挑む配達員向け効率化アプリ「TODOCUサポーター」を開発しています。 開発チームでは一緒に開発してくれるアプリエンジニア(React Native)やバックエンドエンジニアの仲間を大絶賛募集中です!

もし少しでもご興味がありましたら、以下のnotionをご覧ください!

207-inc.super.site

*1:記事を執筆している時点では、Weekly Downloadsが10になっていて本当にMicrosoftが出しているのか不安になる

*2:twopaneviewとdualscreeninfoを同時にインストールして利用したら、RNHingeコンポーネントでエラーが出ました。。

*3:微妙にバグっぽい動きになるので、これだけでは正しく対応できていない可能性が濃厚です