LoginSignup
4
6

More than 1 year has passed since last update.

【SwiftUI】Listの超基本的なこと

Last updated at Posted at 2022-08-20

はじめに

SwiftUIのListについて公式ドキュメントの内容をまとめてみました

環境

Xcode 13.4.1

内容

Listとは、1つの列に並んだデータの行を表示するコンテナで、オプションで1つ以上のメンバーを選択する機能を提供する

struct List<SelectionValue, Content> where SelectionValue : Hashable, Content : View
var body: some View {
    List {
        Text("A List Item")
        Text("A Second List Item")
        Text("A Third List Item")
    }
}

一般的には、Identifiableに準拠したデータから動的にリストを作成する

struct Ocean: Identifiable {

    let name: String
    let id = UUID()
}

private var oceans = [
    Ocean(name: "Pacific"),
    Ocean(name: "Atlantic"),
    Ocean(name: "Indian"),
    Ocean(name: "Southern"),
    Ocean(name: "Arctic")
]

var body: some View {
    List(oceans) {
        Text($0.name)
    }
}

選択可能なリスト

リストのメンバーを選択可能にするには、選択変数へのバインディングを提供する。リストデータのIdentifiable.ID型の単一のインスタンスにバインドすると、単一選択のリストが、セットへのバインディングは、複数の選択をサポートするリストを作成する

struct Ocean: Identifiable, Hashable {
    let name: String
    let id = UUID()
}

private var oceans = [
    Ocean(name: "Pacific"),
    Ocean(name: "Atlantic"),
    Ocean(name: "Indian"),
    Ocean(name: "Southern"),
    Ocean(name: "Arctic")
]

@State private var multiSelection = Set<UUID>()

var body: some View {
    NavigationView {
        List(oceans, selection: $multiSelection) {
            Text($0.name)
        }
        .navigationTitle("Oceans")
        .toolbar { EditButton() }
    }
    Text("\(multiSelection.count) selections")
}

タップやクリックで1つ選択すると、選択されたセルの外観が変わり、選択されたことが示される。タップ操作で複数選択できるようにするには、editModeの値を変更するか、アプリのインターフェースにEditButtonを追加して、リストを編集モードにする。リストを編集モードにすると、各リスト項目の横に丸印が表示され、ユーザーが関連する項目を選択すると、円にはチェックマークが入る

リストの更新

標準のrefreshコントロールを使ってリストの内容を更新可能にするには、 refreshable(action:)を使用する
ユーザーがリストのトップを下にドラッグすると、リフレッシュコントロールを表示し、指定されたアクションを実行する。データをリフレッシュするためにアクションクロージャの内部でawait式を使用、リフレッシュインジケータは待機している操作の間、表示されたままとなる


struct Ocean: Identifiable, Hashable {
     let name: String
     let id = UUID()
     let stats: [String: String]
 }

 class OceanStore: ObservableObject {
     @Published var oceans = [Ocean]()
     func loadStats() async {
         oceans .append(Ocean(name: "hoge", stats: ["hoge":"hoge"]))
     }
 }

struct ContentView: View {
     @EnvironmentObject var store: OceanStore

     var body: some View {
         NavigationView {
             List(store.oceans) { ocean in
                 HStack {
                     Text(ocean.name)
                     StatsSummary(stats: ocean.stats)
                 }
             }
             .refreshable {
                 await store.loadStats()
             }
             .navigationTitle("Oceans")
         }
     }
}

struct StatsSummary: View {
    @State var stats: [String: String]
    var body: some View {
        Text(stats.description)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(OceanStore())
    }
}

リストのセクション分け

2 次元リストを作成するには、セクションインスタンス内の項目をグループ化する


struct ContentView: View {
    struct Sea: Hashable, Identifiable {
        let name: String
        let id = UUID()
    }

    struct OceanRegion: Identifiable {
        let name: String
        let seas: [Sea]
        let id = UUID()
    }

    private let oceanRegions: [OceanRegion] = [
        OceanRegion(name: "Pacific",
                    seas: [Sea(name: "Australasian Mediterranean"),
                           Sea(name: "Philippine"),
                           Sea(name: "Coral"),
                           Sea(name: "South China")]),
        OceanRegion(name: "Atlantic",
                    seas: [Sea(name: "American Mediterranean"),
                           Sea(name: "Sargasso"),
                           Sea(name: "Caribbean")]),
        OceanRegion(name: "Indian",
                    seas: [Sea(name: "Bay of Bengal")]),
        OceanRegion(name: "Southern",
                    seas: [Sea(name: "Weddell")]),
        OceanRegion(name: "Arctic",
                    seas: [Sea(name: "Greenland")])
    ]

    @State private var singleSelection: UUID?

    var body: some View {
        NavigationView {
            List(selection: $singleSelection) {
                ForEach(oceanRegions) { region in
                    Section(header: Text("Major \(region.name) Ocean Seas")) {
                        ForEach(region.seas) { sea in
                            Text(sea.name)
                        }
                    }
                }
            }
            .navigationTitle("Oceans and Seas")
        }
    }
}

アコーディオン(階層のある)リスト

ツリー構造のデータと、任意のレベルの子ノードを取得するためのキーパスを提供するchildrenパラメータを提供することにより、任意の深さの階層的リストを作成することができる。折りたたみ式のセルを使用して、ユーザーがツリー構造をナビゲートできるようになっている

struct ContentView: View {
    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 fileHierarchyData: [FileItem] = [
      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: [])
           ])
        ]),
        FileItem(name: "private", children: nil)
    ]
    var body: some View {
        List(fileHierarchyData, children: \.children) { item in
            Text(item.description)
        }
    }
}

リストのスタイル

SwiftUI はプラットフォームとリストが表示されるビュータイプに基づいてリストの表示スタイルを選ぶ。ビュー内のすべてのリストに異なる ListStyle を適用するには、listStyle(_:)修飾子を使用する

static var automatic: DefaultListStyle

プラットフォームのデフォルトの動作とリストの外観を記述するリストスタイル

static var grouped: GroupedListStyle

グループ化されたリストの動作と外観を記述するリストスタイル

static var inset: InsetListStyle

インセットリストの動作と外観を記述するリストスタイル

static var insetGrouped: InsetGroupedListStyle

グループ化されたインセットリストの動作と外観を記述するリストスタイル

static var plain: PlainListStyle

プレーンリストの動作と外観を記述するリストスタイル

static var sidebar: SidebarListStyle

サイドバーリストの動作と外観を記述するリストスタイル

おわりに

この記事を見る限りListはすでにLazyであるようなので、カスタマイズに問題がなければListをどんどん使っていこうと思いました

参考

4
6
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
4
6