SwiftUIを使って学習がてらタイマーアプリを作ってみよう8


SwiftUIを使って学習がてらタイマーアプリを作ってみよう Part8

前置き 

前回投稿したPart7の続きです。
今回のゴールとしては
1.UIKitのPageViewControllerを利用して設定画面を時間設定と音楽設定で分けて
表示する
です。

次回はページインジゲータをちょっとカスタムして実装です

開発環境

Mac (OS Big Sur version:11.3.1)
Xcode (version:12.5)
Swift (version: 5.4)
対象IOS(version:14.5以上)

今回の作業

UIPageViewController(UIKit)をSwiftUIでも使えるように実装

基本はAppleが公開しているチュートリアルを真似して実装したため詳細はそちらを見てください

違う所はPage(View)の配列の方をジェネリックじゃなくてAnyViewに変更。
今回は別々のViewをUIPageViewControllerに表示したかったけど、チュートリアルのようにジェネリクスのままだと同一View以外表示ができなかったんで。

PageViewController.swift
// pagesの配列型(ジェネリクス利用)
struct PageViewController<Page:View>: UIViewControllerRepresentable {
    // 表示するViewList
    var pages:[Page]
                      
}

                ↓

PageViewController.swift
// pagesの配列型(AnyView)
struct PageViewController: UIViewControllerRepresentable {
    // 表示するViewList
    var pages:[AnyView]
                      
}

実装したUIViewPageControllerを必要なところで呼び出す

チュートリアルを見ながら実装したんで、UIViewPageControllerを表示するViewを作ってさらにそれをSetting Viewで表示するように変更。(再利用とか考えないなら直でSettingViewで呼び出しても良かったかも)

PageView.swift
import SwiftUI

struct PageView: View {
    var pages:[AnyView]
    @Binding var currentPage: Int
    // スクロール方向を設定 horizontal:横 vertical:縦
    var pageOrientation: UIPageViewController.NavigationOrientation = .horizontal

    var body: some View {
        PageViewController(pages: self.pages, currentPage: self.$currentPage,orientation: self.pageOrientation).self.background(Color.green)
    }
}

SettingView.swift
struct SettingView: View {
    @State private var selection = 0
    @State private var pageSelect = 0
    @State var degree = 15.0

    var body: some View {
        NavigationView{
            GeometryReader{ geometry in
                ZStack(alignment: .bottomLeading){

                    PageView(pages: [
                                AnyView(TimeSetView(selection: self.$selection)),
                                AnyView(MusicSetView())],
                             currentPage: $pageSelect,
                             pageOrientation: .vertical)
                        .background(Color.green) 

                }
                // 画面一杯に広げる
                .frame(minWidth: 0, maxWidth: geometry.size.width,
                       minHeight: 0, maxHeight: geometry.size.height,
                       alignment: .center)
                .background(Color.pink)
                .navigationTitle("Setting")
                // バーのサイズを最小限に設定(Settingと表示される部分)
                .navigationBarTitleDisplayMode(.inline)

            }
        }
    }
}

実際の動作(エミュレータ)

色使いがとても見づらいけど、デバックで色つけしてるので勘弁してください。
背景赤 → PageViewControllerの子ビューの範囲
背景緑 → PageViewControllerの範囲


参考・引用元

Apple Developer SwiftUI Tutorials
Framework Integration Interfacing with UIKit

シリーズ:「SwiftUIの学習でタイマーアプリを作ってみよう」のリンク

part1:プロジェクトの作成とGitHubに登録
part2: Timerを利用したカウント処理の実装
part3:計測画面でのプログレスバーの実装
part4:スピナー実装
part5:ライブラリから音楽を選択して再生
part6:タイマー処理のバックグランド対応
part7:音楽のバックグランド再生対応
part8:PageViewを作成 ←今ここ
part9:PageViewのインジゲータを作成