システム開発<基本編>SwiftUIで、上部Tab制御 & 3種類の画像ファイル選択方法を利用したアプリケーション

Swift

前回は、SwiftUIで、ベーシックTabView 画像回転させるアプリケーション

開発記事を紹介しました。

 

 

今回は、SwiftUIで、上部Tab制御 & 3種類画像ファイル選択方法を利用した

アプリケーションを開発する記事を紹介しようと思います。

SwiftUIで上部Tab制御 & 3種類の画像ファイル選択方法を利用したアプリケーション

 

 

習得内容

今回、SwiftUIで、上部Tab制御 & 3種類画像ファイル選択方法を利用したアプリケーション

を作成する事で、下記の内容を習得する事が出来ます。

  • HeaderBarTabView は、下部に Tab を配置していますが、HeaderBar を実装する事で、上部Tab を配置して、TabView を制御します。
  • Picker画像ファイル選択方法を、メニュー回転ホイールで実現します。
  • DropDown画像ファイル選択方法を、ドロップダウン(プルダウン)で実現します。
  • AnyTransitionドロップダウン(プルダウン)表示・非表示切り替えは、トランジション(transition)で実現します。

 

ドロップダウン(プルダウン)

Swift では、複数の選択肢から1つの値選択する場合、標準コンポーネントとして、

Picker が搭載されています。

通常なら、Picker を利用すれば、要件を満たして事足りるのですが、顧客の指定で、

ドロップダウン(プルダウン)を要求する場合も出て来ます。

(顧客への提案時に経験しました…)

 

Swift には、標準コンポーネントとして、DropDown が搭載されていないので、

今回、ForEachButtontransition を利用して、ドロップダウン(プルダウン)

ドロワー作り込みをしています。

 

動作環境

今回も、アプリが動作する環境は下記になります。

  • mac OS:Sequoia 15.6.1
  • iOS:26.0
  • Xcode:26.0.1
  • Swift:6.2.1

 

 

NavigationStack

NavigationStack については、過去の記事で詳しく説明しましたので、今回も、

詳細説明省略させて頂きます。

 

NavigationStack → TabBarView → Menu/Wheel/DropDown

NavigationStack で、配列コントロールを実現する為に、View を作成して行きます。

  1. TabBarView上部Tab を配置して、TabView を制御します。下部は、画像ファイル選択方法と選択された画像を表示します。
  2. HeaderBarView上部Tab制御を担当します。
  3. MenuPickerView画像ファイル選択方法を、メニューで実現します。
  4. WheelPickerView画像ファイル選択方法を、回転ホイールで実現します。
  5. DropDownView画像ファイル選択方法を、ドロップダウン(プルダウン)で実現します。
  6. DropDownListDropDownView から呼び出される、ドロワー(drawer)の部品です。

 

Xcode の上部タブメニューより、File → New → File from Template を選択します。

 

SwiftUI View を選択します。

 

名称は、TabBarView を入力してみます。

 

Create ボタンを押して、TabBarView.swift  を作成します。

 

同様に、HeaderBarView.swiftMenuPickerView.swiftWheelPickerView.swift

DropDownView.swiftDropDownList.swift を作成します。

 

 

ContentView:メインメニュー(ランチャー)

メインメニュー(ランチャー)ContentView を確認します。

 


import SwiftUI

struct ContentView: View {

    @State var isPopupView_1 = false
    @State var isPopupView_2 = false
    @State var isPopupView_3 = false
    @State var isPopupView_4 = false
    @State var isPopupView_5 = false

    var body: some View {
        
        VStack{
            Button {
                self.isPopupView_1.toggle()
            } label: {
                Text("QRCodeView")
                    .font(.title2)
            }
            .fullScreenCover(isPresented: $isPopupView_1, content: {
                QRCodeView(isPopupView_1: $isPopupView_1)
            })
            .padding()

            Button {
                self.isPopupView_2.toggle()
            } label: {
                Text("ColorPickerView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_2, content: {
                ColorPickerView(isPopupView_2: $isPopupView_2)
            })
            .padding()

            Button {
                self.isPopupView_3.toggle()
            } label: {
                Text("ColorSliderRGBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_3, content: {
                ColorSliderRGBView(isPopupView_3: $isPopupView_3)
            })
            .padding()

            Button {
                self.isPopupView_4.toggle()
                
            } label: {
                Text("ColorSliderHSBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_4, content: {
                ColorSliderHSBView(isPopupView_4: $isPopupView_4)
            })
            .padding()

            Button {
                self.isPopupView_5.toggle()
                
            } label: {
                Text("NavigationListView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_5, content: {
                NavigationListView(isPopupView_5: $isPopupView_5)
            })
            .padding()
        }
    }
}

#Preview {
    ContentView()
}

 

メインメニュー(ランチャー)は、以下の内容です。

  • QRCodeView
  • ColorPickerView
  • ColorSliderRGBView
  • ColorSliderHSBView
  • NavigationListView

今回も、メインメニュー(ランチャー)ContentView に変更は有りませんので、

このまま利用して行きます。

 

NavigationListView:配列コントロール

NavigationListVeiw のソースに、追記・修正をして行きます。

 

ソース例:NavigationListVeiw(配列コントロール)

前回の記事で、BaseTabVeiw(path: $path)SelectTabView(path: $path)

追加した NavigationListVeiw のソースを確認してみます。

 


import SwiftUI

struct NavigationListView: View {

    @Binding var isPopupView_5: Bool
    @State var path: [String] = []

    var navi_lists: [String] = [
        "SwipeView",
        "CarouselView",
        "BaseTabView",
        "TabBarView"
    ]

    var body: some View {
        VStack {

            NavigationStack(path: $path) {

                List(navi_lists, id: \.self) { navi_list in

                    NavigationLink(navi_list, value: navi_list)
                        .font(.system(size: 22))

                }
                .navigationDestination(for: String.self) { navi_list in

                    switch (navi_list) {

                    case "SwipeView":
                        SwipeView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "SwipeDetailView":
                        SwipeDetailView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "CarouselView":
                        CarouselView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "BaseTabView":
                        BaseTabView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "SelectTabView":
                        SelectTabView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "TabBarView":
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.orange)
                            .padding()

                    default:
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.blue)
                            .padding()
                    }
                }
                .navigationTitle("NavigationList")
                .font(.system(size: 22))
                .foregroundColor(.purple)
                
            }
        }

        Button(action: {
            withAnimation {
                self.isPopupView_5.toggle()
            }
        }, label: {
            Text("Close")
                .font(.title2)
                .foregroundColor(.black)
        })
        .padding()
    }
}

#Preview {
    NavigationListView(isPopupView_5: .constant(false))
}

 

ソース例:NavigationListVeiw(配列コントロール:追加・修正版)

NavigationListVeiw のソースに、追記・修正をしたソースを紹介します。

 


import SwiftUI

struct NavigationListView: View {

    @Binding var isPopupView_5: Bool
    @State var path: [String] = []

    var navi_lists: [String] = [
        "SwipeView",
        "CarouselView",
        "BaseTabView",
        "TabBarView"
    ]

    var body: some View {
        VStack {

            NavigationStack(path: $path) {

                List(navi_lists, id: \.self) { navi_list in

                    NavigationLink(navi_list, value: navi_list)
                        .font(.system(size: 22))

                }
                .navigationDestination(for: String.self) { navi_list in

                    switch (navi_list) {

                    case "SwipeView":
                        SwipeView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "SwipeDetailView":
                        SwipeDetailView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "CarouselView":
                        CarouselView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "BaseTabView":
                        BaseTabView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "SelectTabView":
                        SelectTabView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    case "TabBarView":
                        TabBarView(path: $path)
                            .navigationTitle(navi_list)
                            .navigationBarTitleDisplayMode(.inline)

                    default:
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.blue)
                            .padding()
                    }
                }
                .navigationTitle("NavigationList")
                .font(.system(size: 22))
                .foregroundColor(.purple)
                
            }
        }

        Button(action: {
            withAnimation {
                self.isPopupView_5.toggle()
            }
        }, label: {
            Text("Close")
                .font(.title2)
                .foregroundColor(.black)
        })
        .padding()
    }
}

#Preview {
    NavigationListView(isPopupView_5: .constant(false))
}

追記・修正をした部分を説明します。

  • TabBarView(path: $path)TabBarView に、path の引数を渡しています。

 

TabBarView → MenuPicker/WheelPicker/DropDown

今回は、View で利用する画像(写真)Xcode に追加せず、前回までに Assets 内に

保存した画像(写真)を利用します。

 

ソース例:TabBarView

NavigationList から TabBarView を選択して、表示します。

TabBarView は、

  1. HeaderBarView
  2. MenuPickerView
  3. WheelPickerView
  4. DropDownView

4つの Veiw を組み合わせています。

 


import SwiftUI

struct TabBarView: View {

    @Binding var path: [String]
    @State private var selectedTab: Int = 1

    var body: some View {
        ZStack {
            Color.white
                .edgesIgnoringSafeArea(.all)

            VStack {

                HeaderBarView(selectedTab: $selectedTab)

                TabView(selection: $selectedTab) {

                    MenuPickerView()
                        .tag(1)

                    WheelPickerView()
                        .tag(2)

                    DropDownView()
                        .tag(3)

                }
                .tabViewStyle(.page(indexDisplayMode: .never))
            }
        }
    }
}

#Preview {
    TabBarView(path: .constant(["TabBarView"]))
}
  • @State private var selectedTab選択Tab を宣言しています。
  • HeaderBarView(selectedTab: $selectedTab)HeaderBarView に、selectedTab の引数を渡して呼び出しています。VStack で、上部に配置しています。
  • TabView(selection: $selectedTab) {TabView に、selectedTab の引数を渡しています。TabView で切り替える画面に tag 修飾子を付与し、引数に番号を指定します。
  • MenuPickerView().tag(1)MenuPickerView を呼び出して、通常の Picker画像(写真)ファイル名を選択します。tag:1 を指定しています。
  • WheelPickerView().tag(2)WheelPickerView を呼び出して、回転ホイール画像(写真)ファイル名を選択します。tag:2 を指定しています。
  • DropDownView().tag(3)DropDownView を呼び出して、ドロップダウン(プルダウン)画像(写真)ファイル名を選択します。tag:3 を指定しています。
  • .tabViewStyle(.page(indexDisplayMode: .never))tabViewStyle page で、indexDisplayMode: .never を指定することで、TabView の下に標準で配置しているPageControl非表示にします。

4つの Veiw は、前回までのように NavigationStack から、switch 文でコントロール

するのではなく、TabBarView から直接呼び出しています。

 

ソース例:HeaderBarView

TabBarView 上部に配置する、HeaderBarView のソースを紹介します。

 


import SwiftUI

struct HeaderBarView: View {

    @Binding var selectedTab: Int

    var body: some View {
        HStack {
            Spacer()

            HStack {
                Image(systemName: "cat")
                Text("MenuPicker")
            }
            .foregroundColor(selectedTab == 1 ? Color.blue : Color.gray)
            .onTapGesture {
                withAnimation {
                    selectedTab = 1
                }
            }

            Spacer()

            HStack {
                Image(systemName: "cat.fill")
                Text("WheelPicker")
            }
            .foregroundColor(selectedTab == 2 ? Color.green : Color.gray)
            .onTapGesture {
                withAnimation {
                    selectedTab = 2
                }
            }

            Spacer()

            HStack {
                Image(systemName: "pawprint")
                Text("DropDown")
            }
            .foregroundColor(selectedTab == 3 ? Color.pink : Color.gray)
            .onTapGesture {
                withAnimation {
                    selectedTab = 3
                }
            }

            Spacer()
        }
    }
}

#Preview {
    HeaderBarView(selectedTab: .constant(1))
}

  • @Binding var selectedTab: Int@State を指定した親ViewTabBarView)から渡される selectedTab が利用出来るように宣言しています。
  • HStack { Image(systemName: “cat”) Text(“MenuPicker”) }SF Symbolsアイコンと、“MenuPicker”文字列水平に設定しています。
  • .foregroundColor(selectedTab == 1 ? Color.blue : Color.gray)selectedTab 1なら青色で表示、それ以外はグレーで表示しています。
  • .onTapGesture { withAnimation { selectedTab = 1 }}タップした時に、selectedTab 1を代入しています。
  • HStack { Image(systemName: “cat.fill”) Text(“WheelPicker”) }SF Symbols黒猫アイコンと、“WheelPicker”文字列水平に設定しています。
  • .foregroundColor(selectedTab == 2 ? Color.green : Color.gray)selectedTab 2なら緑色で表示、それ以外はグレーで表示しています。
  • .onTapGesture { withAnimation { selectedTab = 2 }}タップした時に、selectedTab 2を代入しています。

  • HStack { Image(systemName: “pawprint”) Text(“DropDown”) }SF Symbols足跡アイコンと、“DropDown”文字列水平に設定しています。
  • .foregroundColor(selectedTab == 3 ? Color.pink : Color.gray)selectedTab 3ならピンク色で表示、それ以外はグレーで表示しています。
  • .onTapGesture { withAnimation { selectedTab = 3 }}タップした時に、selectedTab 3を代入しています。

 

 

ソース例:MenuPickerView

TabBarView 下部1番目に配置する、MenuPickerView のソースを紹介します。

 


import SwiftUI

struct MenuPickerView: View {

    @State private var selectIndex: Int = 0
    @State var cat_image: String = "IMG_0057"

    var imageNames: [String] = [
        "IMG_0057",
        "IMG_0230",
        "IMG_0405",
        "IMG_0402",
        "IMG_0411",
        "IMG_0412",
    ]
   
    var body: some View {
        ZStack {
            Color.white
                .edgesIgnoringSafeArea(.all)

            VStack {
                Picker("cat", selection: $selectIndex) {
                    ForEach(0..<imageNames.count, id: \.self) { imageIndex in
                        withAnimation {
                            Text(imageNames[imageIndex])
                        }
                    }
                }
                .pickerStyle(.menu)
                .onChange(of: selectIndex) {
                    withAnimation {
                        cat_image = imageNames[selectIndex]
                    }
                }
                .padding()

                Image(cat_image)
                    .resizable()
                    .scaledToFill()
            }
        }
    }
}

#Preview {
    MenuPickerView()
}
  • @State private var selectIndex: Int = 0selectIndex を宣言して、初期値に0を代入しています。
  • @State var cat_image: String = “IMG_0057”cat_image を宣言して、初期値に “IMG_0057” を代入しています。
  • var imageNames: [String] = [ “IMG_0057”, “IMG_0230”, …]Assets に保存した複数の画像(写真)名称を利用する為に、配列で宣言しています。
  • Picker(“cat”, selection: $selectIndex) {Picker を設定しています。
  • ForEach(0..<imageNames.count, id: \.self) { imageIndex inAssets に保存した画像(写真)を、ForEach() 配列画像(写真)を繰り返し生成して表示しています。
  • Text(imageNames[imageIndex])選択された画像(写真)名称を設定しています。
  • .pickerStyle(.menu)pickerStylemenu に設定する事で、メニュー表示が実現します。
  • .onChange(of: selectIndex) {画像(写真)名称変更した時の処理を記載します。
  • cat_image = imageNames[selectIndex]cat_image に、選択された画像(写真)名称を設定しています。
  • Image(cat_image)Image に、選択された画像(写真)を設定しています。

 

 

ソース例:WheelPickerVirew

TabBarView 下部2番目に配置する、WheelPickerView のソースを紹介します。

 


import SwiftUI

struct WheelPickerView: View {

    @State private var selectIndex: Int = 0
    @State var cat_image: String = "IMG_0088"

    var imageNames: [String] = [
        "IMG_0088",
        "IMG_0148",
        "IMG_0234",
        "IMG_0096",
        "IMG_0090",
        "IMG_0976",
    ]

    var body: some View {
        ZStack {
            Color.white
                .edgesIgnoringSafeArea(.all)

            VStack {
                Picker("cat", selection: $selectIndex) {
                    ForEach(0..<imageNames.count, id: \.self) { imageIndex in
                        withAnimation {
                            Text(imageNames[imageIndex])
                        }
                    }
                }
                .pickerStyle(.wheel)
                .onChange(of: selectIndex) {
                    withAnimation {
                        cat_image = imageNames[selectIndex]
                    }
                }
                .padding()

                Image(cat_image)
                    .resizable()
                    .scaledToFill()
            }
        }
    }
}

#Preview {
    WheelPickerView()
}

  • @State private var selectIndex: Int = 0selectIndex を宣言して、初期値に0を代入しています。
  • @State var cat_image: String = “IMG_0088”cat_image を宣言して、初期値に “IMG_0088” を代入しています。
  • var imageNames: [String] = [ “IMG_0088”, “IMG_0148”, …]Assets に保存した複数の画像(写真)名称を利用する為に、配列で宣言しています。
  • Picker(“cat”, selection: $selectIndex) {Picker を設定しています。
  • ForEach(0..<imageNames.count, id: \.self) { imageIndex inAssets に保存した画像(写真)を、ForEach() 配列画像(写真)を繰り返し生成して表示しています。
  • Text(imageNames[imageIndex])選択された画像(写真)名称を設定しています。
  • .pickerStyle(.wheel)pickerStylewheel に設定する事で、回転ホイール表示が実現します。
  • .onChange(of: selectIndex) {画像(写真)名称変更した時の処理を記載します。
  • cat_image = imageNames[selectIndex]cat_image に、選択された画像(写真)名称を設定しています。
  • Image(cat_image)Image に、選択された画像(写真)を設定しています。

 

DropDownView → DropDownList

DropDownView は、DropDownList と組み合わせて表示しています。

 

ソース例:DropDownView

TabBarView 下部3番目に配置する、DropDownView のソースを紹介します。

 


import SwiftUI

struct DropDownView: View {

    @State private var isExpanded = false
    @State private var selectedItem = "IMG_0981"
    @State private var dropdown_height: CGFloat = 0.1

    @State private var imageNames: [String] = [
        "IMG_0981",
        "IMG_0059",
        "IMG_0232",
        "IMG_0688",
        "IMG_0541",
        "IMG_0058",
    ]

    var body: some View {
        GeometryReader { geometry in

            let geo_width: CGFloat = geometry.size.width

            ZStack {
                Color.white
                    .edgesIgnoringSafeArea(.all)

                VStack(spacing: 20) {

                    Button {
                        withAnimation {
                            isExpanded.toggle()
                        }
                    } label: {
                        HStack {
                            Text(selectedItem)
                                .foregroundColor(.black)

                            Spacer()

                            Image(systemName: "chevron.down")
                                .rotationEffect(.degrees(isExpanded ? 180 : 0))
                        }
                        .padding()
                        .background(
                            RoundedRectangle(cornerRadius: 8)
                                .stroke(Color.gray)
                        )
                    }
                    .frame(width: geo_width * 0.6)

                    Image(selectedItem)
                        .resizable()
                        .scaledToFit()
                }

                if isExpanded {
                    Color.black.opacity(0.001)
                        .ignoresSafeArea()
                        .onTapGesture {
                            withAnimation {
                                isExpanded = false
                            }
                        }

                    DropDownList(items: $imageNames, selectedItem: $selectedItem, isExpanded: $isExpanded, dropdown_height: $dropdown_height)
                        .transition(.move(edge: .top).combined(with: .opacity))
                        .frame(width: geo_width * 0.6)
                }
            }
        }
    }
}

#Preview {
    DropDownView()
}

  • @State private var isExpanded = falseisExpanded を宣言して、初期値に false を 代入しています。ボタン押した(タップした)かどうかの判定に利用します。
  • @State var selectedItem: String = “IMG_0981”selectedItem を宣言して、初期値に “IMG_0981” を代入しています。
  • @State private var dropdown_height: CGFloat = 0.1dropdown_height を宣言して、初期値に0.1を代入しています。
  • var imageNames: [String] = [ “IMG_0981”, “IMG_0059”, …]Assets に保存した複数の画像(写真)名称を利用する為に、配列で宣言しています。
  • GeometryReader { geometry in画面サイズを取得する為に利用します。
  • let geo_width: CGFloat = geometry.size.width画面を、geo_width に代入しています。
  • Button {ボタン押した(タップした)時の処理を記載します。
  • isExpanded.toggle()isExpanded の値を反転させています。
  • Text(selectedItem)Text selectedItem を設定しています。
  • Image(systemName: “chevron.down”)SF Sybols で、chevron.downアイコンを設定しています。

  • .rotationEffect(.degrees(isExpanded ? 180 : 0))isExpandedtrue の場合、chevron.downアイコン180度回転(上下反転)させます。
  • RoundedRectangle(cornerRadius: 8)ボタン半径 8 で指定した角丸四角形を設定しています。
  • .frame(width: geo_width * 0.6)ボタンを、画面0.6倍に設定しています。
  • Image(selectedItem)Image selectedItem を設定しています。
  • if isExpanded {isExpandedtrue の場合の処理を記載します。
  • .onTapGesture { withAnimation { isExpanded = false }}タップした時に、isExpandedfalse を代入しています。isExpanded.toggle() の記載でも大丈夫ですが、今回は明確に false を代入しています。
  • DropDownList(items: $imageNames,…)DropDownList() を呼び出しています。
  • .transition(.move(edge: .top).combined(with: .opacity))ドロップダウン(プルダウン)表示・非表示切り替えで、transition を指定しています。 move(edge: .top)で、上(top)から表示・非表示(戻る)を実現し、opacity組み合わせる(combined)事で、透明な状態からじわじわドロップダウン(プルダウン)が出現したり、消えたりします。
  • .frame(width: geo_width * 0.6)ドロップダウン(プルダウン)を、画面0.6倍に設定しています。

 

AnyTransition:表示・非表示の切り替え

View表示・非表示切り替えに、transition(トランジション)を利用しています。

transition(トランジション)の主なタイプは、下記になります。

  • .slideからスライドして出現し、スライドして消えて行きます。
  • .opacity透明な状態からじわじわと出現し、消える時もじわじわ透明になって行きます。
  • .scale拡大しながら表示、縮小しながら消えていきます。
  • .move(edge: Edge)edge 指定された方向(.top/.leading/.bottom/.trailing)から出現して、指定された同方向へ消えて行きます。
  • .offset(CGSize)CGSize で指定されたオフセット位置から、移動しながら表示して、同じ位置へ移動しながら非表示になります。
  • .identitytransition(トランジション)の効果は、行いません。

 

AnyTransition については、下記を参考にしています。

 

 

 

ソース例:DropDownList

DropDownView からドロワー(drawer)として呼び出される、DropDownList

ソースを紹介します。

 


import SwiftUI

struct DropDownList: View {

    @Binding var items: [String]
    @Binding var selectedItem: String
    @Binding var isExpanded: Bool
    @Binding var dropdown_height: CGFloat

    var body: some View {
        GeometryReader { geometry in

            let geo_height: CGFloat = geometry.size.height

            VStack(spacing: 0) {
                ForEach(items, id: \.self) {item in
                    Button {
                        selectedItem = item

                        withAnimation {
                            isExpanded = false
                        }
                    } label: {
                        HStack {
                            Text(item)
                                .foregroundColor(.black)
                            Spacer()
                        }
                        .padding()
                        .background(Color.white)
                    }

                    if item != items.last {
                        Divider()
                    }
                }
            }
            .background(
                RoundedRectangle(cornerRadius: 8)
                    .fill(Color.white)
                    .shadow(radius: 5)
            )
            .padding(.horizontal, 16)
            .offset(y: geo_height * dropdown_height)
        }
    }
}

#Preview {
    DropDownList(items: .constant(["IMG_0981"]), selectedItem: .constant("IMG_0981"), isExpanded: .constant(false), dropdown_height: .constant(0.1))
}

  • @Binding var items:[String]@State を指定した親ViewDropDownView)から渡される items が利用出来るように宣言しています。
  • @Binding var selectedItem: String@State を指定した親ViewDropDownView)から渡される selectedItem が利用出来るように宣言しています。
  • @Binding var isExpanded: Bool@State を指定した親ViewDropDownView)から渡される isExpanded が利用出来るように宣言しています。
  • @Binding var dropdown_height: CGFloat@State を指定した親ViewDropDownView)から渡される dropdown_height が利用出来るように宣言しています。
  • GeometryReader { geometry in画面サイズを取得する為に利用します。
  • let geo_height: CGFloat = geometry.size.height画面高さを、geo_height に代入しています。
  • ForEach(items, id: \.self) {item inForEach() で、親ViewDropDownView)から渡された items を繰り返し表示しています。
  • Button { selectedItem = item withAnimation { isExpanded = false } }ボタン押した(タップした)時は、selectedItem に選択した item を代入し、isExpandedfalse を代入しています。
  • if item != items.last { Divider() }item items 最終データで無い場合は、仕切り線を挿入しています。
  • RoundedRectangle(cornerRadius: 8)ボタン半径 8 で指定した角丸四角形を設定しています。
  • .offset(y: geo_height * dropdown_height)ドロップダウン(プルダウン)高さの位置を、geo_height * dropdown_height で設定しています。dropdown_height には、親ViewDropDownView)から0.1が渡されてきます。ドロップダウン(プルダウン)ボタンドロワー(drawer)隙間狭くする場合は、geo_height * dropdown_height 調整してみて下さい。

 

アプリ実行:シミュレータ起動

では、実際にアプリを実行してみます。

Xcode の上部タブメニューより、Product → Run を選択するか、command + R

押してみて下さい。

 

エラーが無ければ、iPhoneシミュレータが起動します。

 

 

ContntVeiw(メインメニュー)が表示されました。

 

NavigationListView:ナビゲーション画面

続けて、NavigationListViewボタン押してみます(タップします)

 

 

ContntVeiw(メインメニュー)の上に NavigationListVeiw(ナビゲーション機能)

重なって、表示されました。

  • SwipeView
  • CarouselView
  • BaseTabVeiw
  • TabBarView

現在の 配列(path の状態は、下記になります。

  • path = []

 

TabBarView:上部Tab制御 & 3種類の画像ファイル選択方法

では、TabBarView を操作してみます。

 

 

MenuPicker

NavigationList 4段目TabBarView を押してみます(タップします)

 

 

画面上部には、TabBarView のタイトルが表示されていますが、

NavigationListVeiw で、タイトルを表示するように設定していました。

 

タイトルの下には、分かりにくいかもしれませんが、上部Tabが表示されています。

  1. 上部Tab左側には、青色アイコンMenuPicker の文字が表示されています。
  2. 上部Tab中央には、グレー色アイコンWheelPicker の文字が表示されています。
  3. 上部Tab右側には、グレー色足跡アイコンDropDown の文字が表示されています。

 

上部Tabには、IMG_0057 画像ファイル名ボタンが表示されていますので、

押してみます(タップします)

 

 

複数の画像ファイル名で、選択肢が表示された事が分かると思います。

複数の選択肢から、別の画像を選んでみます。

 

 

ボタン画像(IMG_0405)が、入れ替わっていると思います。

 

WheelPicker

次に、上部Tab中央(WheelPicker)押してみます(タップします)

 

 

  1. 上部Tab左側は、グレー色アイコンMenuPicker に切り替わりました。
  2. 上部Tab中央は、緑色アイコンWheelPicker に切り替わりました。
  3. 上部Tab右側は、グレー色足跡アイコンDropDown の文字はそのままです。

 

上部Tabには、IMG_0088 画像ファイル名回転ホイールが表示されていますので、

スクロールして、複数の選択肢から、別の画像を選んでみます。

 

 

回転ホイール画像(IMG_0234)が、入れ替わっていると思います。

更にスクロールして、複数の選択肢から、別の画像を選んでみます。

 

 

回転ホイール画像(IMG_0976)が、入れ替わった事が分かると思います。

 

DropDown

次に、上部Tab右側(DropDown)押してみます(タップします)

 

 

  1. 上部Tab左側は、グレー色アイコンMenuPicker の文字はそのままです。
  2. 上部Tab中央は、グレー色アイコンWheelPicker に切り替わりました。
  3. 上部Tab右側は、ピンク色足跡アイコンDropDown に切り替わりました。

 

上部Tabには、IMG_0981 画像ファイル名ボタンに表示されていますので、

ファイル名押してみます(タップします)

 

 

ボタンの下に、ドロワー(drawer)が表示された事が分かると思います。

複数の選択肢から、別の画像を選んでみます。

 

 

ボタン画像(IMG_0688)が、入れ替わっていると思います。

 

上部Tab制御 & 3種類MenuPicker/WheelPicker/DropDown)の画像ファイル選択方法

利用して、画像を入れ替えてみました。

 

 

まとめ

今回は、SwiftUIで、上部Tab制御 & 3種類画像ファイル選択方法を利用した

アプリケーションを開発する記事を紹介しました。

 

次回は、SwiftUIで、マルチ言語切り替えるアプリケーションを開発する記事を

紹介しようと思います。

 

コメント

タイトルとURLをコピーしました