開発
タグ SwiftUI ページ SegmentedControl PageView
SwiftUIでUIPageViewControllerとSegmentedControlを使う方法を紹介します。
Appleの公式チュートリアルを参考にしています。
UIKit
のUIPageViewController
をラップするPageViewController
と、SwiftUIからPageViewController
を使うためのPageView
を作ります。
まず、PageViewController
です。
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return nil
}
return parent.controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == parent.controllers.count {
return nil
}
return parent.controllers[index + 1]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = parent.controllers.firstIndex(of: visibleViewController)
{
parent.currentPage = index
}
}
}
}
UIViewControllerRepresentable
のmakeUIViewController(context: Context)
でUIPageViewController
を作成します。 updateUIViewController
でPageViewController
のページを表示します。
UIPageViewController
のDelegate
とDataSource
を設定するために、Coordinator
クラスを作成し、makeUIViewController
でdelgate
とdataSource
をcontext
のcoordinator
にセットします。
次にこのPageViewController
を使って、SwiftUIのViewを表示するPageView
を作ります。
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
@Binding var currentPage: Int
init(_ views: [Page], currentPage: Binding<Int>) {
self._currentPage = currentPage
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
PageViewController(controllers: viewControllers, currentPage: $currentPage)
}
}
こちらは簡単で、ページとして表示するViewと、currentPage
を受け取って、PageViewController
に渡します。
これをSegmentedControl
と組み合わせて使います。
struct ContentView: View {
@State private var page = 0
var body: some View {
VStack {
Picker("Page", selection: $page) {
Text("Page 1").tag(0)
Text("Page 2").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 12))
PageView([
Text("Page1"),
Text("Page2")
], currentPage: $page)
}
}
}
PageView
のcurrentPage
は@Binding
プロパティなので、@State
プロパティをPageView
のcurrentPage
にセットします。これによって、currentPage
を書き換えると、ページが自動的に変更されます。
SwiftUIでSegmentedControl
を使うにはPicker
にSegmentedPickerStyle
をセットします。こちらのselection
プロパティも@Binding
プロパティなので、PageView
のcurrentPage
に渡したものと同じプロパティを渡します。
これでSegmentedControl
とPageView
を組み合わせることができました。
gistはこちら
オススメ記事
-
2020/12/1開発
Apple Silicon搭載 MacBook Pro M1で Homebrewとrbenvをインストールする
先日購入したApple Silicon搭載 MacBook Pro M1にこのブログをビルドするためにHomebrewとrbenvをインストールしたのでメモ。
-
2020/11/27開発
Apple Silicon搭載のMacBook Pro M1が危うく文鎮化するところだったので記録
Apple Silicon搭載のMacBook Pro 13インチを仕事用に購入したのですが、クリーンインストールしたところ文鎮化しかけたので記録しておきます。
-
2020/6/23開発
Platform State of the Unionまとめ
Platform State of the Unioまとめ
-
2020/6/23開発
WWDC2020キーノートまとめ
WWDC2020 キーノートまとめ
-
2020/5/31開発
GitHub Pagesで無料ブログを作成する - Part4 自分のオリジナルのテーマを作る
Jekyllでは既存のテーマを使うこともできるのですが、さらに一歩踏み込んで、自分で既存のテーマをカスタマイズしたり、テーマを作ることもできます。
-
2020/5/28開発
GitHub Pagesで無料ブログを作成する - Part3 Jekyllの設定をカスタマイズする
前回の記事では、Jekyllのテーマを利用する方法と記事を追加する方法を紹介しました。今回はさらにJekyllをカスタマイズしていきますが、確認を簡単にするためにまずJekyllをローカル環境で実行する方法を紹介します。
-
2020/5/26開発
GitHub Pagesで無料ブログを作成する - Part2 Jekyllを使ってみる
JekyllはGitHub Pagesで使用することができる静的サイトのジェネレータです。Jekyllを使うことで、Markdownで書いたブログの記事やhtmlで作ったページをビルドして、公開用のhtmlとして生成することができます。
-
2020/5/24開発
GitHub Pagesで無料ブログを作成する - Part1 GitHubにリポジトリを作ってサイトを公開する
以前、GitHub Pagesでブログを運用し始めてから4年くらいたったというブログを書いたのですが、概要を書いただけで具体的な構築方法はあまり記述していなかったので、何回かに分けてブログを作っていく方法を書いていきたいと思います。
-
2020/1/3開発
FirebaseでCloud Storageに画像をアップロードする
今FirebaseとReactでアプリを開発中で、画像をアップロードする部分を作ったのでメモ。
-
2020/1/1開発
2020年にネイティブアプリを開発する方法
去年2019年にネイティブアプリを開発する方法という記事を書きました。その中では1. ネイティブ言語、ネイティブプラットフォーム, 2. React Native, 3. Flutterの3つの方法を紹介していました。2020年はどういう感じになりそうか、という実感を書いておきたいと思います。
MasamichiUeta
ソフトウェアエンジニアです。ソフトウェアエンジニアリング、アプリ開発、趣味などについて書いてます