はじめに
SwiftUIで画像ライブラリを表示しつつ、PhotosPickerで選んだ画像をハイライト表示&高画質プレビューするUI実装をまとめています。
実装イメージ
- サムネイル一覧を表示(複数選択可能)
- 選択された画像には白いハイライトを表示
- タップで高画質プレビュー画面に遷移(
fullScreenCover
)
使用環境
- Swift 6.1
- Xcode 16.2
- SwiftUI
コード
import SwiftUI
import PhotosUI
struct ImageGalleryView: View {
// PhotosPickerで選択された画像のメタ情報
@State private var selectedItems: [PhotosPickerItem] = []
// 実際に表示するUIImageの配列
@State private var images: [UIImage] = []
// 現在選択中のインデックス
@State private var selectedIndex: Int? = nil
// プレビュー画面の表示フラグ
@State private var isPreviewPresented = false
var body: some View {
NavigationView {
VStack {
// 写真選択ボタン(最大10枚)
PhotosPicker(selection: $selectedItems,
maxSelectionCount: 10,
matching: .images,
photoLibrary: .shared()) {
Text("画像選択")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
// 選択された画像の一覧表示(グリッド)
ScrollView {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))], spacing: 10) {
ForEach(images.indices, id: \.self) { index in
Image(uiImage: images[index])
.resizable()
.scaledToFill()
.frame(width: 100, height: 100)
.clipped()
// 選択状態を白くハイライト表示
.overlay(
RoundedRectangle(cornerRadius: 8)
.fill(Color.white.opacity(selectedIndex == index ? 0.4 : 0.0))
)
// タップでプレビュー表示へ
.onTapGesture {
selectedIndex = index
isPreviewPresented = true
}
}
}
.padding()
}
}
.navigationTitle("画像ライブラリ")
}
// 選択項目が変更されたときに画像データを読み込み
.onChange(of: selectedItems) {
Task {
images = [] // 初期化
for item in selectedItems {
// Dataとして読み込み → UIImageに変換
if let data = try? await item.loadTransferable(type: Data.self),
let image = UIImage(data: data) {
images.append(image)
}
}
}
}
// フルスクリーンでの画像プレビュー
.fullScreenCover(isPresented: $isPreviewPresented) {
if let index = selectedIndex, images.indices.contains(index) {
ZStack {
Color.black.ignoresSafeArea()
Image(uiImage: images[index])
.resizable()
.scaledToFit()
.padding()
}
// タップで閉じる
.onTapGesture {
isPreviewPresented = false
}
}
}
}
}
まとめ
SwiftUIの PhotosPicker と組み合わせることで、写真選択・非同期ローディング・UI表現をシンプルに実装できます。特に以下の点が良い学びになりました。
- 状態管理(@State)とイベント駆動の連携方法
- 非同期で複数画像を処理するシンプルな書き方
- overlay による視覚表現の柔軟性