1
votes

Swift UI - Xcode

Problem: I have extra cells when my list is initialized. However, unlike other posts I do not have a navigation view. Is it mandatory to have a NavigationView in order to remove the extra cells from my list.

I have tried to implement a Navigation View but im not sure if its mandatory and how to properly implement.

.navigationBarTitle("List")
.listStyle(GroupedListStyle())

I would like to start a new Text or UIButton directly below the last "Current" cell without extra white spaces.

enter image description here

var body: some View {


    VStack(alignment: .leading) {


        Image("covidImage")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .cornerRadius(5)

        Text("COVID DATA")
            .font(.system(.title, design: .rounded))
            .bold()
            .lineLimit(3)
            .padding(.bottom, 3)
            .padding(.leading, 10)

        Text("Represented by Sate in the United States")
            .font(.subheadline)
            .foregroundColor(.secondary)
            .padding(.leading, 10)
            .padding(.bottom, 0)

        Text("Current State: CA")
        .font(.subheadline)
        .foregroundColor(.secondary)
        .padding(.leading, 10)
        .padding(.bottom, 10)

      //List to Initialize TableView Data
        List(covid) { covidData in
            Image(systemName: "photo")
                .padding()
            HStack {
                Text(covidData.dataTitle).frame(maxWidth: .infinity, alignment: .leading)

                Text(covidData.dataValue)
                    .font(.subheadline)
                .frame(maxWidth: .infinity, alignment: .trailing)
                    //.color(.gray)


            }


        }//END List


    }//END Original VStack



}//END Some View
1
Use UITableView.appearance().separatorColor = .clear e.g after END List add .onAppear { UITableView.appearance().separatorColor = .clear }`Norman

1 Answers

1
votes

They are not empty cells. The List just fills all available space and draws empty rows placeholders where there is no content. In your scenario is needed to limit height of List to its content.

Here is a solution. Tested with Xcode 11.4 / iOS 13.4

For better visibility let's separate your list into own view named CovidDataList, then here is in your provided body:

  //List to Initialize TableView Data
    CovidDataList(covid: self.covid)

    }//END List

Note1: The height of list updated in run-time so should be tested in running application (not in Preview)

Note2: I tested with replicated cover data model so some adapting might be needed to your code

struct CovidDataList: View {
    @Environment(\.defaultMinListRowHeight) var minRowHeight

    let covid: [CovidData]
    @State private var listHeight = CGFloat.infinity

    var body: some View {
        List {
            ForEach(covid, id: \.self) { covidData in
                HStack {
                    Image(systemName: "photo")
                        .padding()
                    HStack {
                        Text("Title").frame(maxWidth: .infinity, alignment: .leading)

                        Text("Value")
                            .font(.subheadline)
                            .frame(maxWidth: .infinity, alignment: .trailing)
                    }
                }
                .listRowInsets(EdgeInsets()).padding(.horizontal)
            }
            .anchorPreference(key: BoundsPreferenceKey.self, value: .bounds) { [$0] }
        }
        .backgroundPreferenceValue(BoundsPreferenceKey.self) { rects in
            GeometryReader { gp in
                self.updateListFrame(gp: gp, anchors: rects)
            }
        }.frame(maxHeight: listHeight)
    }

    private func updateListFrame(gp: GeometryProxy, anchors: [Anchor<CGRect>]) -> some View {
        let contentHeight = anchors.reduce(CGFloat.zero) { $0 + gp[$1].size.height }
        DispatchQueue.main.async {   // << required !!
            self.listHeight = max(contentHeight, self.minRowHeight * CGFloat(self.covid.count))
        }
        return Color.clear
    }
}

Note: BoundsPreferenceKey is taken from this my answer