3
5

More than 3 years have passed since last update.

SwiftUIに内包されているStructまとめ - ViewControl編

Last updated at Posted at 2021-05-08

はじめに

SwiftUIフレームワークに内包されている構造体の内、頻繁に利用する構造体をまとめようと思います。

  • Views
    • Controls ☆本記事ではここが対象
    • Layout
    • Paints
    • Other
  • Modifiers
    • Controls
    • Effects
    • Layout
    • Text
    • Image
    • List
    • Styles
    • Accessibility
    • Events
    • Gestures
    • Shape Modifiers
    • Other

など
今後残りの部分についてもまとめていければと思っています。

また、端末で動作確認できるようにもしているので、もし興味があればローカルで端末にビルドいただければと思います。
ソースコード

Views

Controls

Button

    @State var number = 0
    var body: some View {
        VStack {
            Text("\(number)")
                .padding()
            Button(action: {
                    number = number + 1
            }) {
                Text("DefaultButtonStyle")
            }.buttonStyle(DefaultButtonStyle())

            Button(action: {
                    number = number + 1
            }) {
                Text("PlainButtonStyle")
            }.buttonStyle(PlainButtonStyle())

            Button(action: {
                    number = number + 1
            }) {
                Text("BorderlessButtonStyle")
            }.buttonStyle(BorderlessButtonStyle())
        }
    }

ColorPicker

    @State private var selectedColor = Color.red
    var body: some View {
        ColorPicker("ColorPicker", selection: $selectedColor)
            .frame(width: 150)
    }

DatePicker

    @State private var date = Date()    
    var body: some View {
        VStack {
            DatePicker(selection: $date, displayedComponents: [.date]) {
                Text("displayedComponents .date")
            }.padding()
            DatePicker(selection: $date, displayedComponents: [.hourAndMinute]) {
                Text("displayedComponents .hourAndMinute")
            }.padding()
        }
    }

    @State private var date = Date()

    var body: some View {
        ScrollView(.vertical){
            VStack {
                DatePicker(selection: $date) {
                    Text("CompactDatePickerStyle")
                }.datePickerStyle(CompactDatePickerStyle())

                DatePicker(selection: $date) {
                    Text("GraphicalDatePickerStyle")
                }.datePickerStyle(GraphicalDatePickerStyle())

                DatePicker(selection: $date) {
                    Text("WheelDatePickerStyle")
                }.datePickerStyle(WheelDatePickerStyle())

                DatePicker(selection: $date) {
                    Text("DefaultDatePickerStyle")
                }.datePickerStyle(DefaultDatePickerStyle())
            }
        }
    }

DisclosureGroup

    struct ToggleStates {
        var oneIsOn: Bool = false
        var twoIsOn: Bool = true
    }
    @State private var toggleStates = ToggleStates()
    @State private var topExpanded: Bool = true

    var body: some View {
        VStack {
            DisclosureGroup("Items", isExpanded: $topExpanded) {
                Toggle("Toggle 1", isOn: $toggleStates.oneIsOn)
                Toggle("Toggle 2", isOn: $toggleStates.twoIsOn)
                DisclosureGroup("Sub-items") {
                    Text("Sub-item 1")
                }
            }.padding()
        }
    }

EditButton

    @State private var editMode = EditMode.inactive
    @State private var fruits = [
        "Apple",
        "Banana",
        "Papaya",
        "Mango"
    ]

    var body: some View {
        VStack {
            NavigationView{
                List {
                    ForEach(
                        fruits,
                        id: \.self
                    ) { fruit in
                        Text(fruit)
                    }
                    .onDelete { self.fruits.remove(atOffsets: $0) }
                    .onMove { self.fruits.move(fromOffsets: $0, toOffset: $1) }
                }
                .navigationTitle("Fruits")
                .toolbar { EditButton() }
                .environment(\.editMode, $editMode)
            }
            Text(String(describing: "editMode: \(editMode)"))                        
        }
    }

Form

Form

    @State var toggleState = false
    var body: some View {
        VStack {
            Form {
                Section(header: Text("Text")) {
                    Text("item 1")
                    Text("item 2")
                }
                Section(header: Text("Toggle")) {
                    Toggle(isOn: $toggleState) {
                        Text("item 3")
                    }
                }
                Section(header: Text("Button")) {
                    Button(action: {}) {
                        Text("item 4")
                    }
                }
            }
        }
    }

GroupBox

GroupBox

    var body: some View {
        GroupBox(
            label: Label("Heart Rate", systemImage: "heart.fill").foregroundColor(.red)
        ) {
            Text("Your hear rate is 90 BPM.")
        }.padding()

Label

Label

    var body: some View {
        VStack {
            Label("Label", systemImage: "42.circle")
                .padding()
            Label("Label: TitleOnlyLabelStyle", systemImage: "bolt.fill")
                .padding()
                .labelStyle(TitleOnlyLabelStyle())
            Label("Label: IconOnlyLabelStyle", systemImage: "bolt.fill")
                .padding()
                .labelStyle(IconOnlyLabelStyle())
            Label("Label: TitleAndIconLabelStyle", systemImage: "bolt.fill")
                .padding()
                .labelStyle(TitleAndIconLabelStyle())
            Label {
                Text("bbbb")
                    .font(.body)
                    .foregroundColor(.primary)
                Text("cccc")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            } icon: {
                Circle()
                    .fill(Color.red)
                    .frame(width: 44, height: 44, alignment: .center)
                    .overlay(Text("aaa"))
            }
        }

Link

    var body: some View {
        Link(destination: URL(string: "https://www.google.com/?hl=ja")!) {
            Text("googleを開く")
        }.padding()
        .font(.title)
        .foregroundColor(.green)
    }

Navigation

    var body: some View {
        VStack {
            NavigationView {
                List {
                    NavigationLink(destination: ButtonView()) {
                        Text("Button Page")
                    }
                    NavigationLink(destination: ColorPickerView()) {
                        Text("ColorPicker Page")
                    }
                }
            }.navigationViewStyle(StackNavigationViewStyle())

            NavigationView {
                List {
                    NavigationLink(destination: ButtonView()) {
                        Text("Button Page")
                    }
                    NavigationLink(destination: ColorPickerView()) {
                        Text("ColorPicker Page")
                    }
                }
           }.navigationViewStyle(DoubleColumnNavigationViewStyle())            
        }.navigationBarTitle(Text("Navigation"))

OutlineGroup

    struct FileItem: Hashable, Identifiable, CustomStringConvertible {
        var id: Self { self }
        var name: String
        var children: [FileItem]? = nil
        var description: String {
            switch children {
            case nil:
                return "📄 \(name)"
            case .some(let children):
                return children.isEmpty ? "📂 \(name)" : "📁 \(name)"
            }
        }
    }

    let data =
      FileItem(name: "users", children:
        [FileItem(name: "user1234", children:
          [FileItem(name: "Photos", children:
            [FileItem(name: "photo001.jpg"),
             FileItem(name: "photo002.jpg")]),
           FileItem(name: "Movies", children:
             [FileItem(name: "movie001.mp4")]),
              FileItem(name: "Documents", children: [])
          ]),
         FileItem(name: "newuser", children:
           [FileItem(name: "Documents", children: [])
           ])
        ])

    var body: some View {
        VStack {
            OutlineGroup(data, id: \.id, children: \.children) { item in
                Text("\(item.description)")
            }.padding()
        }
    }

Picker

enum Flavor: String, CaseIterable, Identifiable {
    case chocolate
    case vanilla
    case strawberry

    var id: String { self.rawValue }
}

enum Topping: String, CaseIterable, Identifiable {
    case nuts
    case cookies
    case blueberries

    var id: String { self.rawValue }
}

extension Flavor {
    var suggestedTopping: Topping {
        switch self {
        case .chocolate: return .nuts
        case .vanilla: return .cookies
        case .strawberry: return .blueberries
        }
    }
}

struct PickerView: View {
    @State private var selectedFlavor = Flavor.chocolate
    @State private var suggestedTopping: Topping = .cookies

    var body: some View {
        VStack {
            Picker(selection: $selectedFlavor, label: Text("Flavor")) {
                ForEach(Flavor.allCases) { flavor in
                    Text(flavor.rawValue.capitalized)
                }
            }
            Text("Selected flavor: \(selectedFlavor.rawValue)")
            Divider()
            Picker(selection: $selectedFlavor, label: Text("Suggest a topping for:")) {
                ForEach(Flavor.allCases) { flavor in
                    Text(flavor.rawValue.capitalized).tag(flavor.suggestedTopping)
                }
            }
            Text("suggestedTopping: \(suggestedTopping.rawValue)")
        }
    }
}

    @State private var selectedFlavor1 = Flavor.chocolate
    @State private var selectedFlavor2 = Flavor.chocolate
    @State private var selectedFlavor3 = Flavor.chocolate
    @State private var selectedFlavor4 = Flavor.chocolate

    var body: some View {
        ScrollView(.vertical) {
            VStack {
                Picker(selection: $selectedFlavor1, label: Text("Flavor: MenuPickerStyle")) {
                    Text("Chocolate").tag(Flavor.chocolate)
                    Text("Vanilla").tag(Flavor.vanilla)
                    Text("Strawberry").tag(Flavor.strawberry)
                }.pickerStyle(MenuPickerStyle())
                Text("Selected flavor: \(selectedFlavor1.rawValue)")

                Picker(selection: $selectedFlavor2, label: Text("Flavor: WheelPickerStyle")) {
                    Text("Chocolate").tag(Flavor.chocolate)
                    Text("Vanilla").tag(Flavor.vanilla)
                    Text("Strawberry").tag(Flavor.strawberry)
                }.pickerStyle(WheelPickerStyle())
                Text("WheelPickerStyle Selected flavor: \(selectedFlavor2.rawValue)")

                Picker(selection: $selectedFlavor3, label: Text("Flavor: WheelPickerStyle")) {
                    Text("Chocolate").tag(Flavor.chocolate)
                    Text("Vanilla").tag(Flavor.vanilla)
                    Text("Strawberry").tag(Flavor.strawberry)
                }.pickerStyle(InlinePickerStyle())
                Text("InlinePickerStyle Selected flavor: \(selectedFlavor3.rawValue)")

                Spacer(minLength: 50)
                Picker(selection: $selectedFlavor4, label: Text("Flavor: SegmentedPickerStyle")) {
                    Text("Chocolate").tag(Flavor.chocolate)
                    Text("Vanilla").tag(Flavor.vanilla)
                    Text("Strawberry").tag(Flavor.strawberry)
                }.pickerStyle(SegmentedPickerStyle())
                Text("SegmentedPickerStyle Selected flavor: \(selectedFlavor4.rawValue)")
        }
   }

ProgressView

    @State private var progress = 0.0
    private let total = 1.0

    var body: some View {
        VStack {
            ProgressView("DefaultProgressViewStyle", value: progress, total: total)
                .padding()
            Button("More", action: {
                if (progress + 0.05) < total {
                    progress += 0.05
                } else {
                    progress = total
                }
            })

            ProgressView("LinearProgressViewStyle", value: 0.25, total: total)
                .progressViewStyle(LinearProgressViewStyle())
                .padding()

            ProgressView("CircularProgressViewStyle", value: 0.75, total: total)
                .progressViewStyle(CircularProgressViewStyle())
                .padding()

        }
    }

ScrollView

        VStack {
            ScrollView(.horizontal) {
                Text(".horizontal test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test")
            }.padding()

            ScrollView(.horizontal, showsIndicators: false) {
                Text(".horizontal showIndicators: false test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test")
            }.padding()

            ScrollView {
                ScrollViewReader { value in
                    Button("Jump to 30") {
                        withAnimation {
                            value.scrollTo(30, anchor: .top)
                        }
                    }
                    ForEach(1..<51) { index in
                        Image(systemName: "\(index).square")
                            .font(.largeTitle)
                            .frame(height: 70)
                            .id(index)
                    }
                }
            }
        }

Section

    @State private var selectedValue = "C++"
    var body: some View {
        VStack {
            List {
                Section(header: Text("header 果物"), footer: Text("footer 果物")) {
                    Text("桃")
                    Text("りんご")
                    Text("みかん")
                }
                Section(header: Text("header 野菜"), footer: Text("footer 野菜")) {
                    Text("きゅうり")
                    Text("トマト")
                    Text("なす")
                }
            }.frame(height:450)
            Form {
                Section(header: Text("header プログラミング言語"), footer: Text("footer プログラミング言語")) {
                    Picker("プログラミング言語", selection: $selectedValue) {
                        Text("C++").tag("C++")
                        Text("Kotlin").tag("Kotlin")
                        Text("Swift").tag("Swift")
                    }
                }
            }
        }
    }

SecureField / TextField

    @State private var username: String = ""
    @State private var password: String = ""

    var body: some View {
        VStack {
            TextField(
                "User name (email address)",
                text: $username)
                .autocapitalization(.none)
                .disableAutocorrection(true)
                .border(Color(UIColor.separator))
                .padding()
            SecureField(
                "Password",
                text: $password
            ) {
                print("ログイン")
            }
            .border(Color(UIColor.separator))
            .padding()
        }
    }

Scroll

    @State private var speed = 50.0
    @State private var isEditing = false

    var body: some View {
        VStack {
            Slider(
                value: $speed,
                in: 0...100,
                step: 5,
                onEditingChanged: { editing in
                    isEditing = editing
                },
                minimumValueLabel: Text("0"),
                maximumValueLabel: Text("100")
            ) {
                Text("Speed")
            }
            Text("\(speed)")
                .foregroundColor(isEditing ? .red : .blue)
        }.padding()
    }

Stepper

    @State private var value1 = 0
    @State private var value2 = 0
    let colors: [Color] = [.orange, .red, .gray, .blue,
                           .green, .purple, .pink]

    func incrementStep() {
        value1 += 1
        if value1 >= colors.count { value1 = 0 }
    }

    func decrementStep() {
        value1 -= 1
        if value1 < 0 { value1 = colors.count - 1 }
    }

    var body: some View {
        VStack {
            Stepper(onIncrement: incrementStep,
                onDecrement: decrementStep) {
                Text("Value: \(value1) Color: \(colors[value1].description)")
            }
            .padding(10)
            .background(colors[value1])

            Stepper(value: $value2,
                    in: 1...50,
                    step: 5) {
                Text("Current: \(value2) in 1...50 stepping by 5")
            }.padding(10)
        }
    }

TabView

    @State private var selection = 1
    var body: some View {
        VStack {
            Text("selection: \(selection)")

            TabView(selection: $selection) {
                Text("The First Tab")
                    .tabItem {
                        Image(systemName: "1.square.fill")
                        Text("First")
                    }
                    .tag(1)
                Text("Another Tab")
                    .tabItem {
                        Image(systemName: "2.square.fill")
                        Text("Second")
                    }
                    .tag(2)
                Text("The Last Tab")
                    .tabItem {
                        Image(systemName: "3.square.fill")
                        Text("Third")
                    }
                    .tag(3)
            }
            .font(.headline)

        }
    }

Text

Text

    var body: some View {
        VStack {
            Text("Hamlet")
                .font(.title)
                .padding()

            Text("by William Shakespeare")
                .font(.system(size: 12, weight: .light, design: .serif))
                .italic()
                .padding()

            Text("Brevity is the soul of wit.")
                .frame(width: 100)
                .lineLimit(1)
                .padding()
        }
    }

TextEditor

    @State private var fullText: String = "This is some editable text..."

    var body: some View {
        TextEditor(text: $fullText)
            .foregroundColor(Color.gray)
            .font(.custom("HelveticaNeue", size: 18))
            .lineSpacing(5)
    }

Toggle

    @State private var vibrateOnRing = true

    var body: some View {
        Toggle("Vibrate on Ring", isOn: $vibrateOnRing)
            .toggleStyle(SwitchToggleStyle())
            .padding()
    }

最後に

最後まで閲覧いただきありがとうございました。
今後時間を見つけて残りのStructについてもまとめていく予定です。

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5