1
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftUI で List の height を中身に合わせて動的に変化させる

Last updated at Posted at 2021-07-22

追記: NavigationView の中だと上手くいかない場合がありました。


SwiftUI で List の高さを中身に合わせて変える方法です。
下の画像の様に、 List の高さを中身と同じにします。(グレーの部分は List の背景です。)

高さ設定前
スクリーンショット 2021-07-23 午前4.50.38.png

高さ設定後
スクリーンショット 2021-07-23 午前4.50.22.png

List と同じ様に表示される(高さが同じになる) VStack を作成して、その高さを List に設定しています。

import SwiftUI
import Combine

struct Item: Identifiable {
    var id = UUID()
    var name:String
}

class ViewModel: ObservableObject {
    var items:[Item] = { (0..<2).map { i in Item(name: "item\(i)") } }()

    @Published var listHidden = true
    var listHeight:CGFloat = 0

    var publisher = PassthroughSubject<Bool, Never>()
    
    func setHeight(_ height: CGFloat) {
        listHeight = height
        // 5. List を表示
        listHidden = false
    }
}


struct MyView: View {
    @ObservedObject var viewModel = ViewModel()

    init() {
        // 分かりやすい用に List の背景色を付けます
        UITableView.appearance().backgroundColor = UIColor.lightGray
    }

    var body: some View {

        // 1. VStack の方が表示される
        if viewModel.listHidden {
            ZStack {
                VStack(spacing: 0) {
                    ForEach(viewModel.items) { item in
                        Row(item: item)
                    }
                }
                .background(
                    GeometryReader { geo in
                        Color.white
                            // 4. viewModel の listHeight に高さをセット
                            .onReceive(viewModel.publisher) { _ in
                                viewModel.setHeight(geo.size.height)
                            }
                    }
                )
                // 2. VStack が見えないようにする
                Color.white
            }
            // 3. 表示したら publisher から通知
            .onAppear { viewModel.publisher.send(true) }

        // 6. 表示される
        } else {
            List {
                ForEach(viewModel.items) { item in
                    Row(item: item)
                }
            }
            // 7. 高さを設定
            .frame(height: viewModel.listHeight)
        }
    }
}

struct Row: View {
    var item:Item
    var body: some View {
        Text(item.name)
            .listRowInsets(.init()) // 余白を消しておく
            .padding()
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
            .background(Color.orange)
    }
}

struct MyView_Previews: PreviewProvider {
    static var previews: some View {
        MyView()
    }
}


バージョン
Swift 5.4

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?