$30 off During Our Annual Pro Sale. View Details »

Flutterで構築する漫画ビューア / FlutterKaigi 2023

katsu
November 10, 2023

Flutterで構築する漫画ビューア / FlutterKaigi 2023

katsu

November 10, 2023
Tweet

Other Decks in Programming

Transcript

  1. Flutterで構築する漫画ビューア
    @katsu

    View Slide

  2. 自己紹介
    ● 伊藤 克弘
    ● エキサイト株式会社
    ● Android / Flutter エンジニア
    ● 10年ほどAndroidアプリ開発
    ● Flutter歴は1年半ほど
    2

    View Slide

  3. 経緯
    株式会社講談社様との協業
    週刊漫画誌「モーニング」の電⼦版アプリ
    「Dモーニング」を2013年にリリース
    Flutter化のための技術検証
    漫画アプリのFlutter化
    3

    View Slide

  4. 前提事項
    ● Flutterバージョンは 3.13.8、Dartバージョンは 3.1.4 を使⽤
    ● モバイルアプリのみを対象とする(ウェブなどは対象外)
    ● ⼀般的な横開きの漫画を対象とする(縦読み漫画などは対象外)
    ● マテリアルデザインで統⼀する
    環境および制約
    4

    View Slide

  5. 目次
    1. 画像を表示する
    2. 画像を拡大する
    3. 暗号化された画像を使用する
    4. 全画面表示に対応する
    5. ページを操作する
    6. 見開きページを表示する
    5

    View Slide

  6. 1. 画像を表⽰する
    6

    View Slide

  7. 1. 画像を表⽰する
    今回使う画像ファイル
    ● ファイル名: 001.png ~ 010.png
    ● サイズ: 980 x 1,400
    ● 配置場所: /images/
    使用する画像
    7

    View Slide

  8. 1. 画像を表⽰する
    ビューアの画⾯としてViewerScreenを⽤意する
    画面の作成
    8

    View Slide

  9. 1. 画像を表⽰する
    アプリのディレクトリを取得するためにpath_providerを使う
    プラットフォームごとの各種ディレクトリにアクセスできる
    ファイルの参照
    pubspec.yaml
    9

    View Slide

  10. 1. 画像を表⽰する
    画像ファイルを⼀覧で取得する
    ファイルの参照
    10

    View Slide

  11. 1. 画像を表⽰する
    画像ファイルを⼀覧で取得する
    ファイルの参照
    アプリケーションディレクトリを取得
    11

    View Slide

  12. 1. 画像を表⽰する
    画像ファイルを⼀覧で取得する
    ファイルの参照
    ディレクトリの要素の Listを取得
    12

    View Slide

  13. 1. 画像を表⽰する
    画像ファイルを⼀覧で取得する
    ファイルの参照
    1. Fileのみを抽出
    2. ファイル名で並び替え
    13

    View Slide

  14. 1. 画像を表⽰する
    FutureBuilderでFutureからウィジェットを構成する
    ウィジェットで画像を参照する
    14

    View Slide

  15. 1. 画像を表⽰する
    FutureBuilderでFutureからウィジェットを構成する
    ウィジェットで画像を参照する
    Futureの状態に
    応じて処理する
    15

    View Slide

  16. 1. 画像を表⽰する
    画像の表⽰にはImageを使う
    ページ表⽰にはPageViewを使う
    画像をPageViewで表示する
    16

    View Slide

  17. 1. 画像を表⽰する
    PageViewの向きを反転する
    → reverseをtrueにする
    画像をPageViewで表示する
    17

    View Slide

  18. 2. 画像を拡⼤する
    18

    View Slide

  19. 目次
    1. 画像を表示する
    2. 画像を拡大する
    3. 暗号化された画像を使用する
    4. 全画面表示に対応する
    5. ページを操作する
    6. 見開きページを表示する
    19

    View Slide

  20. 2. 画像を拡⼤する
    画像の操作にはInteractiveViewerを使う
    拡大縮小や、拡大状態での移動が可能
    InteractiveViewerでの操作
    20

    View Slide

  21. 2. 画像を拡⼤する
    InteractiveViewerのイベントがPageViewと競合する
    → 拡⼤したまま横に動かせなくなる
    拡⼤中はPageViewのスクロールを無効にする
    PageViewとInteractiveViewerでの問題
    21

    View Slide

  22. 2. 画像を拡⼤する
    TransformationController
    InteractiveViewerに設定する
    ‧外部からの操作
    ‧現在の状態を取得
    → 拡⼤状態を判定するのに使う
    拡大中の判定を行う
    22

    View Slide

  23. 2. 画像を拡⼤する
    リスナーで値の変化を検知する
    getMaxScaleOnAxisで拡⼤率を取得する
    拡⼤率が1より⼤きければ拡⼤中とする
    拡大中の判定を行う
    23

    View Slide

  24. 2. 画像を拡⼤する
    PageViewのphysicsでスクロールの反応を定義
    AlwaysScrollableScrollPhysics
    → スクロール可
    NeverScrollableScrollPhysics
    → スクロール不可
    PageViewのページ移動の可否を設定する
    24

    View Slide

  25. 2. 画像を拡⼤する
    ピンチ操作だけではなく、ダブルタップでも拡⼤できるようにする
    ダブルタップを検出するためにGestureDetectorを追加
    ダブルタップでの操作
    25

    View Slide

  26. 2. 画像を拡⼤する
    ダブルタップでの操作
    26

    View Slide

  27. 2. 画像を拡⼤する
    ダブルタップでの操作
    タップ位置が必要なので
    onDoubleTapDownを使う
    27

    View Slide

  28. 2. 画像を拡⼤する
    ダブルタップでの操作
    拡大中の場合は初期状態に戻す
    28

    View Slide

  29. 2. 画像を拡⼤する
    ダブルタップでの操作
    (50, 50)
    (150, 150)
    (0, 0)
    (100, 100)
    (300, 300)
    x3.0
    拡大した分の座標を移動させる
    29

    View Slide

  30. 2. 画像を拡⼤する
    ダブルタップでの操作
    30

    View Slide

  31. 3. 暗号化された画像を使⽤する
    31

    View Slide

  32. 目次
    1. 画像を表示する
    2. 画像を拡大する
    3. 暗号化された画像を使用する
    4. 全画面表示に対応する
    5. ページを操作する
    6. 見開きページを表示する
    32

    View Slide

  33. 3. 暗号化された画像を使⽤する
    AndroidでもiOSでも、アプリ内のファイルにユーザーがアクセスすることはできない
    ただし、ユーザーが端末のルート化やジェイルブレイクなどで
    強⼒なアクセス権を持った場合はアクセスできてしまう
    → コンテンツを暗号化して守ることが必要
    暗号化の必要性
    33

    View Slide

  34. 3. 暗号化された画像を使⽤する
    AndroidでもiOSでも、アプリ内のファイルにユーザーがアクセスすることはできない
    ただし、ユーザーが端末のルート化やジェイルブレイクなどで
    強⼒なアクセス権を持った場合はアクセスできてしまう
    → コンテンツを暗号化して守ることが必要
    ファイルになんらかの暗号化を施したという体で進める。
    暗号化の必要性
    34

    View Slide

  35. 3. 暗号化された画像を使⽤する
    今までは画像ファイルをそのまま読み込んで表⽰していた
    → ファイルが暗号化されているためそのままでは表⽰できない
    ImageProviderを拡張して画像の読み込みをカスタマイズする
    ImageProviderの拡張
    35

    View Slide

  36. 3. 暗号化された画像を使⽤する
    ImageProviderは画像をどのように処理するのかを定義するクラス
    いくつかのImageProviderが標準で⽤意されている
    ● FileImage(ファイルの画像)
    ● NetworkImage(ネットワーク上の画像)
    ● MemoryImage(メモリに展開された画像)
    ⾃作のImageProviderを作成して、画像を復号して読み込めるようにする
    ImageProviderの拡張
    36

    View Slide

  37. 3. 暗号化された画像を使⽤する
    復号用のImageProviderを作る
    FileImageを参考に
    共通部分を作る
    37

    View Slide

  38. 3. 暗号化された画像を使⽤する
    復号用のImageProviderを作る
    最適化のための比較処理
    38

    View Slide

  39. 3. 暗号化された画像を使⽤する
    復号用のImageProviderを作る
    画像の識別のために自身を返す
    39

    View Slide

  40. 3. 暗号化された画像を使⽤する
    復号用のImageProviderを作る
    40
    loadImageで
    画像読み込みの処理を実装する
    画像データをCodecに、
    Codecを画像フレームに変換する

    View Slide

  41. 3. 暗号化された画像を使⽤する
    復号用のImageProviderを作る
    画像データを展開して復号する
    Codecに変換する
    41

    View Slide

  42. 3. 暗号化された画像を使⽤する
    作成したImageProviderをImageに指定する
    復号用のImageProviderを作る
    42
    復号用のImageProviderを作る

    View Slide

  43. 4. 全画⾯表⽰に対応する
    43

    View Slide

  44. 目次
    1. 画像を表示する
    2. 画像を拡大する
    3. 暗号化された画像を使用する
    4. 全画面表示に対応する
    5. ページを操作する
    6. 見開きページを表示する
    44

    View Slide

  45. 4. 全画⾯表⽰に対応する
    全画⾯表⽰ = コンテンツ以外のUIを⾮表⽰にして画⾯全体に表⽰する
    ● より⼤きく鮮明に表⽰できる
    ● 余計な要素がなくなり没⼊感が⾼まる
    通知の確認や画⾯遷移の際にUIが必要になる
    → UIの表⽰を切り替えられるようにする
    全画面表示とは
    45

    View Slide

  46. 4. 全画⾯表⽰に対応する
    OSが管理しているUI
    ‧ステータスバー
    ‧ナビゲーションバー
    ‧ホームインジケーター
    システムUI
    iOS
    Android
    ステータスバー
    ナビゲーションバー ホームインジケーター
    46

    View Slide

  47. 4. 全画⾯表⽰に対応する
    コンテンツの⾼さが変わるため
    表⽰を切り替えた際に位置がズレてしまう
    → UIの裏にも表⽰しておくことで
    コンテンツの⾼さを⼀定にする
    UIの裏にコンテンツを表示する
    47

    View Slide

  48. 4. 全画⾯表⽰に対応する
    Flutterではデフォルトで⼀部のシステムUIの裏に表⽰される
    Androidのナビゲーションバーは除く
    UIの裏にコンテンツを表示する
    ナビゲーションバーの裏には
    表示されない
    48

    View Slide

  49. 4. 全画⾯表⽰に対応する
    SystemChromeでSystemUiModeを切り替えてシステムUIを管理する
    SystemUiMode
    ● edgeToEdge
    ● leanBack
    ● immersive
    ● immersiveSticky
    ● manual
    UIの裏にコンテンツを表示する
    49

    View Slide

  50. 4. 全画⾯表⽰に対応する
    SystemChromeでSystemUiModeを切り替えてシステムUIを管理する
    SystemUiMode
    ● edgeToEdge
    ● leanBack
    ● immersive
    ● immersiveSticky
    ● manual
    UIの裏にコンテンツを表示する
    後ほど説明
    50

    View Slide

  51. 4. 全画⾯表⽰に対応する
    edgeToEdge
    システムUIの裏にコンテンツを表⽰する
    ビューア画⾯の最初に設定しておく
    UIの裏にコンテンツを表示する
    51

    View Slide

  52. 4. 全画⾯表⽰に対応する
    AppBarの裏にコンテンツを表⽰する
    ScaffoldのextendBodyBehindAppBarをtrueにする
    UIの裏にコンテンツを表示する
    52

    View Slide

  53. 4. 全画⾯表⽰に対応する
    画⾯をタップでUIの表⽰を切り替える
    UIが表⽰されている → ⾮表⽰に
    UIが表⽰されていない → 表⽰に
    UIの表示状態を切り替える
    53

    View Slide

  54. 4. 全画⾯表⽰に対応する
    UIの表示状態を切り替える
    表示状態の変更時に
    フラグを更新
    54
    現在の表示状態を
    自前で管理

    View Slide

  55. 4. 全画⾯表⽰に対応する
    UIの表示状態を切り替える
    GestureDetectorに
    タップ時の処理を追加
    55

    View Slide

  56. 4. 全画⾯表⽰に対応する
    UIの表示状態を切り替える
    システムUIを非表示にする
    システムUIを表示する
    56

    View Slide

  57. 4. 全画⾯表⽰に対応する
    ● edgeToEdge
    ● leanBack
    ● immersive
    ● immersiveSticky
    ● manual
    SystemUiMode
    57

    View Slide

  58. 4. 全画⾯表⽰に対応する
    SystemUiMode
    edgeToEdge leanBack
    immersive
    immersiveSticky
    manual
    表示にする 非表示にする 手動で設定する
    58

    View Slide

  59. 4. 全画⾯表⽰に対応する
    SystemUiMode
    edgeToEdge leanBack
    immersive
    immersiveSticky
    manual
    表示にする 非表示にする パラメータで決まる
    iOSでは全て同じ挙動
    59

    View Slide

  60. 4. 全画⾯表⽰に対応する
    edgeToEdge
    ● 全てのシステムUIが表⽰される
    ● コンテンツはシステムUIの裏にも表⽰される
    SystemUiMode
    60

    View Slide

  61. 4. 全画⾯表⽰に対応する
    leanBack
    ● 全てのシステムUIが⾮表⽰になる
    ● 画⾯をタップするとシステムUIが表⽰される
    動画再⽣など、基本的に画⾯を触らない場合に有効
    SystemUiMode
    61

    View Slide

  62. 4. 全画⾯表⽰に対応する
    immersive
    ● 全てのシステムUIが⾮表⽰になる
    ● 端をスワイプするとシステムUIが表⽰される
    ギャラリーなど、⼤まかな操作をする場合に有効
    SystemUiMode
    62

    View Slide

  63. 4. 全画⾯表⽰に対応する
    immersiveSticky
    ● 全てのシステムUIが⾮表⽰になる
    ● 端をスワイプするとシステムUIが表⽰される
    ● ⼀定時間経過で再び⾮表⽰になる
    ● スワイプのイベントをアプリも受け取れる
    お絵かきなど、画⾯全体を操作する場合に有効
    SystemUiMode
    63

    View Slide

  64. 4. 全画⾯表⽰に対応する
    manual
    ● 表⽰するシステムUIを指定する
    ● システムUIは上下に分類される
    どちらも省略した場合はleanBackと同様
    SystemUiMode
    64

    View Slide

  65. 4. 全画⾯表⽰に対応する
    AppBarの表⽰状態
    表⽰する場合はAppBarを、⾮表⽰にする場合はnullを設定する。
    UIの表示状態を切り替える
    65

    View Slide

  66. 4. 全画⾯表⽰に対応する
    動作イメージ
    66

    View Slide

  67. 5. ページを操作する
    67

    View Slide

  68. 目次
    1. 画像を表示する
    2. 画像を拡大する
    3. 暗号化された画像を使用する
    4. 全画面表示に対応する
    5. ページを操作する
    6. 見開きページを表示する
    68

    View Slide

  69. 5. ページを操作する
    PageViewはスワイプでページ移動ができるが、
    それ以外の操作もサポートしていると操作性が⾼まる
    ● タップでの簡単なページ移動
    ● スライダーでの素早いページ移動
    これらの操作に対応する
    スワイプ以外でのページ操作
    69

    View Slide

  70. 5. ページを操作する
    PageController
    PageViewを外部から操作する
    コントローラー経由でページ移動を⾏う
    ページ操作の基本
    70

    View Slide

  71. 5. ページを操作する
    ページ移動には下記のメソッドが使える
    ● jumpTo
    ● jumpToPage
    ● animateTo
    ● animateToPage
    ● nextPage
    ● previousPage
    PageControllerの操作
    71

    View Slide

  72. 5. ページを操作する
    ページ移動には下記のメソッドが使える
    ● jumpTo
    ● jumpToPage
    ● animateTo
    ● animateToPage
    ● nextPage
    ● previousPage
    PageControllerの操作
    72
    指定したページに瞬時に移動する
    オフセットもしくはインデックスを指定する

    View Slide

  73. 5. ページを操作する
    ページ移動には下記のメソッドが使える
    ● jumpTo
    ● jumpToPage
    ● animateTo
    ● animateToPage
    ● nextPage
    ● previousPage
    PageControllerの操作
    73
    指定したページにアニメーションで移動する
    オフセットもしくはインデックスを指定する

    View Slide

  74. 5. ページを操作する
    ページ移動には下記のメソッドが使える
    ● jumpTo
    ● jumpToPage
    ● animateTo
    ● animateToPage
    ● nextPage
    ● previousPage
    PageControllerの操作
    74
    隣のページにアニメーションで移動する
    内部ではanimateToPageが使われている

    View Slide

  75. 5. ページを操作する
    タップでページ移動ができるようにする
    左側の25%の範囲をタップしたら次のページに移動
    右側の25%の範囲をタップしたら前のページに移動
    タップでのページ操作
    75

    View Slide

  76. 5. ページを操作する
    タップでのページ操作
    76

    View Slide

  77. 5. ページを操作する
    タップでのページ操作
    タップ位置を知るために
    onTapUpを使う
    77

    View Slide

  78. 5. ページを操作する
    タップでのページ操作
    横軸のタップ位置を取得
    ページ移動判定の閾値を算出
    78

    View Slide

  79. 5. ページを操作する
    タップでのページ操作
    左右のタップ時に
    隣のページに移動する
    79

    View Slide

  80. 5. ページを操作する
    タップでのページ操作
    UIの表示切替のタップイベントを統
    合する
    80

    View Slide

  81. 5. ページを操作する
    タップでのページ操作
    81

    View Slide

  82. 5. ページを操作する
    Slider : ⼀定の範囲から値を選択するウィジェット
    下記の要件を実装する
    ‧画⾯下部にスライダーを設置
    ‧ページ数を範囲とする
    ‧選択したページに移動する
    スライダーでのページ操作
    82

    View Slide

  83. 5. ページを操作する
    スライダーでのページ操作
    83
    ・Stackでコンテンツに重ねて表示する
    ・SafeAreaでシステムUIを避ける
    ・UIの表示フラグに合わせる
    SafeAreaなし
    SafeAreaあり

    View Slide

  84. 5. ページを操作する
    スライダーでのページ操作
    84
    選択中のページを変数で保持する
    ページの変更時に変数を更新する

    View Slide

  85. 5. ページを操作する
    スライダーと選択中のページを紐付ける
    スライダーでのページ操作
    85

    View Slide

  86. 5. ページを操作する
    スライダーと選択中のページを紐付ける
    スライダーでのページ操作
    86
    値の範囲は0.0 ~ 1.0
    選択中のページ/ページ数

    View Slide

  87. 5. ページを操作する
    スライダーと選択中のページを紐付ける
    スライダーでのページ操作
    87
    値 x ページ数
    対象のページに移動

    View Slide

  88. 5. ページを操作する
    スライダーを反転させる
    PageViewのような単純な⽅法はない
    計算でページのインデックスを逆順にする
    → ロジックが少し複雑になる
    スライダーでのページ操作
    88

    View Slide

  89. 5. ページを操作する
    スライダーを反転させる
    PageViewのような単純な⽅法はない
    計算でページのインデックスを逆順にする
    → ロジックが少し複雑になる
    ウィジェット⾃体を反転させる
    スライダーでのページ操作
    89

    View Slide

  90. 5. ページを操作する
    Transform.flip
    ウィジェットの中⼼を軸に反転させる
    flipXを指定すると⽔平⽅向に反転
    スライダーでのページ操作
    90

    View Slide

  91. 5. ページを操作する
    スライダーでのページ操作
    91

    View Slide

  92. 6. ⾒開きページを表⽰する
    92

    View Slide

  93. 目次
    1. 画像を表示する
    2. 画像を拡大する
    3. 暗号化された画像を使用する
    4. 全画面表示に対応する
    5. ページを操作する
    6. 見開きページを表示する
    93

    View Slide

  94. 6. ⾒開きページを表⽰する
    ⾒開きページは向かい合う左右のページで構成される
    漫画は⾒開き⽤に構成されていることが多い
    → 可能な場合はアプリでも⾒開きで表⽰する
    見開きページとは
    94

    View Slide

  95. 6. ⾒開きページを表⽰する
    OrientationBuilderで親ウィジェットの向きを取得する
    横向きの場合は⾒開き表⽰にする
    見開き表示の判定
    95

    View Slide

  96. 6. ⾒開きページを表⽰する
    ページ数の管理
    96
    画面あたりのページ数が
    変わるため調整する

    View Slide

  97. 6. ⾒開きページを表⽰する
    ページ数の管理
    97
    見開きの場合はページ数の
    最大値を半分として扱う
    半分にしたページ数を
    PageViewとSliderに反映する

    View Slide

  98. 6. ⾒開きページを表⽰する
    ページ数の管理
    98
    選択中のページは
    1ページ表示を基準とする
    基準の値をSliderの
    現在値に反映する

    View Slide

  99. 6. ⾒開きページを表⽰する
    表⽰が切り替わった際にページがズレてしまう
    ページ数の管理
    99
    index == 2

    View Slide

  100. 6. ⾒開きページを表⽰する
    ページ数の管理
    100
    表示が切り替わった際に
    ページを移動させる

    View Slide

  101. 6. ⾒開きページを表⽰する
    ページ数の管理
    101
    直前の向きを保持しておき
    切り替わったかどうかを判定

    View Slide

  102. 6. ⾒開きページを表⽰する
    ページ数の管理
    102
    表示が切り替わった場合は
    対応したページに移動させる

    View Slide

  103. 6. ⾒開きページを表⽰する
    表⽰が切り替わった際に正しいページが表⽰される
    ページ数の管理
    103

    View Slide

  104. 6. ⾒開きページを表⽰する
    2枚の画像を1枚に連結する
    画像の連結
    104

    View Slide

  105. 6. ⾒開きページを表⽰する
    画像の連結
    105
    画像を連結するために
    ImageProviderを変更

    View Slide

  106. 6. ⾒開きページを表⽰する
    画像の連結
    106
    名前付きコンストラクタで
    画像の指定を追加

    View Slide

  107. 6. ⾒開きページを表⽰する
    画像の連結
    107
    比較処理をListに対応

    View Slide

  108. 6. ⾒開きページを表⽰する
    画像を復号した後に連結する
    画像の連結
    108

    View Slide

  109. 6. ⾒開きページを表⽰する
    画像処理のライブラリを使⽤して画像を連結する
    画像の連結
    109
    pubspec.yaml

    View Slide

  110. 6. ⾒開きページを表⽰する
    画像処理のライブラリを使⽤して画像を連結する
    画像の連結
    110
    画像をImage型に
    デコードする

    View Slide

  111. 6. ⾒開きページを表⽰する
    画像処理のライブラリを使⽤して画像を連結する
    画像の連結
    111
    出力先の画像の
    大きさを決定する

    View Slide

  112. 6. ⾒開きページを表⽰する
    画像処理のライブラリを使⽤して画像を連結する
    画像の連結
    112
    画像の数だけ
    順番に連結する

    View Slide

  113. 6. ⾒開きページを表⽰する
    変更したImageProviderを使⽤する
    画像の連結
    113

    View Slide

  114. 6. ⾒開きページを表⽰する
    画像連結の処理が重いのでページ移動の際に画⾯が固まってしまう
    画像の連結
    114

    View Slide

  115. Futureで⾮同期処理にしても同⼀のスレッドで実⾏される
    → 重い処理を実⾏するとメインスレッドがブロックされる
    重い処理は並列で実⾏する必要がある
    6. ⾒開きページを表⽰する
    並列処理の実行
    115

    View Slide

  116. 6. ⾒開きページを表⽰する
    Isolate
    Dartで並列処理を⾏うための仕組み
    ● メインスレッドも⼀つのIsolateである
    ● Isolate毎に異なるイベントループが実⾏される
    ● Isolate間は分断されている
    → 別のIsolateで処理を実⾏すれば画⾯が固まることはない
    並列処理の実行
    116

    View Slide

  117. 6. ⾒開きページを表⽰する
    Isolateを使う
    ● Isolate.spawn:
    低レイヤーでの操作で、⾊々と⾃前で管理する必要がある
    ● compute:
    Flutterの拡張機能で、Isolateをシンプルに扱える
    ● Isolate.run:
    Dart 2.19で追加され、computeと同様にIsolateをシンプルに扱える
    → 今回は⼀番シンプルなIsolate.runを使う
    並列処理の実行
    117

    View Slide

  118. 6. ⾒開きページを表⽰する
    処理全体をIsolate.runのブロックに含める
    並列処理の実行
    118

    View Slide

  119. 6. ⾒開きページを表⽰する
    画⾯が固まることがなくなる
    並列処理の実行
    119

    View Slide

  120. 最後に
    120

    View Slide

  121. 最後に
    今回実装したのは最低限の基本的な機能
    → 改善できる点はたくさんある
    ● OSバージョンごとの最適化
    ● 読み込みの最適化、キャッシュ処理
    ● 操作の効率化
    ● 動作のアニメーション
    ● etc.
    さらなる改善
    121

    View Slide

  122. 最後に
    今回実装したのは最低限の基本的な機能
    → 改善できる点はたくさんある
    ● OSバージョンごとの最適化
    ● 読み込みの最適化、キャッシュ処理
    ● 操作の効率化
    ● 動作のアニメーション
    ● etc.
    さらなる改善
    122
    最高のサービスを目指して!

    View Slide

  123. 123

    View Slide