Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
365 views
in Technique[技术] by (71.8m points)

ios - How to use GeometryReader in an extracted RowView of a List while having correct row height?

I need to use GeometryReader to size views based on screen width. This is what I had before refactoring. (Zoom in to the pic to see the code and preview side by side).

enter image description here Code here:

import SwiftUI

struct WorkingView: View {
    var data = ["Hit the Edit button to reorder", "Practice Coding", "Grocery shopping", "Get tickets", "Clean house", "Do laundry", "Cook dinner", "Paint room"]
    
    var body: some View {
        NavigationView {
            GeometryReader { geometry in
                List {
                    ForEach(data, id: .self) { content in
                        HStack {
                            Text(String(content.count))
                                .frame(width: geometry.size.width * 0.10)
                            VStack {
                                Text(content)
                                    .underline()
                                Text(content)
                                    .bold()
                                Text(content)
                                    .foregroundColor(.yellow)
                            }
                        }
                    }
                }
                .navigationTitle(Text("Home"))
            }
        }
    }
}

This is what I had after refactoring the rows into an extracted View. Now the row heights are getting messed up, when using GeometryReader here.

enter image description here

import SwiftUI

struct NotWorkingView: View {
    var data = ["Hit the Edit button to reorder", "Practice Coding", "Grocery shopping", "Get tickets", "Clean house", "Do laundry", "Cook dinner", "Paint room"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(data, id: .self) { content in
                    GeometryReader { geometry in
                        NotWorkingRowView(content: content)
                    }
                }
            }
            .navigationTitle(Text("Home"))
        }
    }
}

struct NotWorkingRowView: View {
    var content: String
    var body: some View {
        VStack {
            GeometryReader { geometry in
                HStack {
                    Text(String(content.count))
                        .frame(width: geometry.size.width * 0.10)
                    VStack {
                        Text(content)
                            .underline()
                        Text(content)
                            .bold()
                        Text(content)
                            .foregroundColor(.yellow)
                    }
                }
            }
        }
    }
}

This is a simplified version, my extracted subview itself is pretty big. But since it needs screen width to size subviews, I have to use GeometryReader.

What is messing up the row heights when I am extracting it into a subview?

question from:https://stackoverflow.com/questions/65651501/how-to-use-geometryreader-in-an-extracted-rowview-of-a-list-while-having-correct

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You could put the GeometryReader at the top level and pass the width that it gets to the NotWorkingRowView. Something like this:

struct NotWorkingView: View {
    var data = ["Hit the Edit button to reorder", "Practice Coding", "Grocery shopping", "Get tickets", "Clean house", "Do laundry", "Cook dinner", "Paint room"]

    var body: some View {
        NavigationView {
            GeometryReader { geometry in. // <- Move Geometry reader here
                List {
                    ForEach(data, id: .self) { content in
                        NotWorkingRowView(content: content, 
                                          width: geometry.size.width) // <- Pass width
                    }
                }
            }
            .navigationTitle(Text("Home"))
        }
    }
}

Then you can just use the width inside your row like this:

struct NotWorkingRowView: View {

    var content: String
    var width: CGFloat

    var body: some View {
        VStack {
            HStack {
                Text(String(content.count))
                    .frame(width: width * 0.10) // <- use the width you passed here
                VStack(alignment: .leading) {
                    Text(content)
                        .underline()
                    Text(content)
                        .bold()
                    Text(content)
                        .foregroundColor(.yellow)
                }
            }
        }
    }
}

Which gives the following result on screen:

enter image description here

Tested in Xcode 12.3 on iOS 14.3


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...