LoginSignup
45
23

More than 3 years have passed since last update.

【Swift】SwiftUIのListでダイナミックな高さを実現する方法

Last updated at Posted at 2019-08-08

SwiftUIでListを使用していて
UITableViewCellのように各行をダイナミックな高さで表示をしようとする際に
layoutPriorityを使うと簡単に実現することができます。
https://developer.apple.com/documentation/swiftui/view/3278584-layoutpriority

実際に行っているのはQiitaAPIから取得したデータをリストに表示しています。
左側にユーザのアイコン
真ん中に記事のタイトルとユーザ名
右側に静的ないいねマークの画像といいねの数
を表示します。

まずはlayoutPriorityがない状態です。


struct QiitaView: View {
    let item: QiitaItemViewModel
    var body: some View {
        HStack {
            ImageLoadingView(loader: ImagePath(path: item.profileImageURL))
                .frame(width: 44, height: 44)
                .clipShape(Circle())
                .overlay(Circle().stroke(Color.white, lineWidth: 4))
                .shadow(radius: 10)

            VStack(alignment: .leading) {
                Text(item.title)
                    .lineLimit(nil)
                    .padding([.bottom], 12)

                Text(item.userName)
                    .lineLimit(nil)
            }
            .padding([.leading, .trailing], 12)

            Spacer()

            VStack(alignment: .center) {
                Image(systemName: "faceid")
                    .resizable()
                    .frame(width: 44, height: 44)

                Text("\(item.likesCount)")
            }
            .frame(width: 60)
        }
    }
}

これを表示すると下記のようになります。
スクリーンショット 2019-09-23 14.16.15.png

真ん中のラベルの横幅は想定よりも狭くなってしまっています。

これをlayoutPriorityを用いて改善していきます。

まずは真ん中のVStacklayoutPriorityを設定します。
layoutPriorityはデフォルトが0で
1を設定することで優先度を他よりも高くすることができます。


struct QiitaView: View {
    let item: QiitaItemViewModel
    var body: some View {
        HStack {
            ImageLoadingView(loader: ImagePath(path: item.profileImageURL))
                .frame(width: 44, height: 44)
                .clipShape(Circle())
                .overlay(Circle().stroke(Color.white, lineWidth: 4))
                .shadow(radius: 10)

            VStack(alignment: .leading) {
                Text(item.title)
                    .lineLimit(nil)
                    .padding([.bottom], 12)

                Text(item.userName)
                    .lineLimit(nil)
            }
            .padding([.leading, .trailing], 12)
            .layoutPriority(1) // ← ここに追加

            Spacer()

            VStack(alignment: .center) {
                Image(systemName: "faceid")
                    .resizable()
                    .frame(width: 44, height: 44)

                Text("\(item.likesCount)")
            }
            .frame(width: 60)
        }
    }
}

すると下記のイメージのような状態になります。

スクリーンショット 2019-09-23 14.17.07.png

横幅は改善されました。

しかし、まだタイトルが切れてしまっている状態です。

そこでTextにもlayoutPriorityを設定します。


struct QiitaView: View {
    let item: QiitaItemViewModel
    var body: some View {
        HStack {
            ImageLoadingView(loader: ImagePath(path: item.profileImageURL))
                .frame(width: 44, height: 44)
                .clipShape(Circle())
                .overlay(Circle().stroke(Color.white, lineWidth: 4))
                .shadow(radius: 10)

            VStack(alignment: .leading) {
                Text(item.title)
                    .lineLimit(nil)
                    .padding([.bottom], 12)
                    .layoutPriority(1) // ← ここに追加

                Text(item.userName)
                    .lineLimit(nil)
            }
            .padding([.leading, .trailing], 12)
            .layoutPriority(1)

            Spacer()

            VStack(alignment: .center) {
                Image(systemName: "faceid")
                    .resizable()
                    .frame(width: 44, height: 44)

                Text("\(item.likesCount)")
            }
            .frame(width: 60)
        }
    }
}

すると下記のような形になります。

スクリーンショット 2019-09-23 14.18.30.png

もし何か参考になりましたら幸いです。

逆に間違いや他に良い方法があれば
教えていただけると嬉しいです🙇🏻‍♂️

45
23
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
45
23