Search code examples
swiftswiftuiswiftui-list

UI alignment not looks good and is shows dots, how can I fix it


I am trying to achieve the one design that is already completed using UIKit.

The same approach is followed to complete it, but the output does not look good.

Please find my code below:

    struct LoanHistoryView: View {
    let listContorller = LoanHistoryController()

    var body: some View {
        return NavigationView {
             List{

                 ForEach(listContorller.listOfValues, id: \.self){text in
                     HistoryContentView()
                         .background(Color.white)
                 }
                 .cornerRadius(10)
                 .listRowBackground(Color.clear)
                 .listRowSeparator(.hidden)
             }
             .background(.green.opacity(0.6))
             .listStyle(.plain)
             .navigationTitle("LOAN HISTORY")

        }

    }
}




 struct HistoryContentView: View {
    var body: some View {

       VStack {
            HStack{
                VStack(alignment: .leading){
                    Text("KW123456789066788")
                        .foregroundColor(.red)
                    Text("KARTHI | 7502875893")
                        .foregroundColor(.black)
                }
                
                Spacer()
                HStack{
                    VStack{
                        Image(systemName: "menucard")
                        Text("REPORT")
                    }
                    VStack{
                        Image(systemName: "menucard")
                        Text("DOCUMENTS")
                    }
                    VStack{
                        Image(systemName: "menucard")
                        Text("CONTACT")
                    }
                }
            }
           VStack(spacing: 10.0) {
               Divider()
                   .frame(height: 1)
               .background(.gray)
               HStack(){
                   Text("HYNDAI CRETA 1.5 - CHENNAI")
                       .foregroundColor(.black)
                   Spacer()
                   Text("NEW-PRIVATE")
                       .foregroundColor(.cyan)
               }
               HStack(){
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("REGNO")
                       Text("TN09CQ0925")
                           .bold()
                   }
                   Spacer()
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("TENURE")
                       Text("60 MONTHS")
                           .bold()
                   }
                   Spacer()
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("EMI")
                       Text("23456")
                           .bold()
                   }
                   Spacer()
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("LOAN AMOUNT")
                       Text("3446667")
                           .bold()
                   }
               }.foregroundColor(.black)

               HStack(){
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("DEALER")
                       Text("KUWY001")
                           .bold()
                   }
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("LOS NUMBER")
                       Text("5678JKSKS888")
                           .bold()
                   }
                   Spacer()

               }.foregroundColor(.black)
               HStack {
                   VStack(alignment: .leading, spacing: 10.0){
                       Text("AXIS BANK")
                       Text("TEST CASE REJECED BY KAMS")
                           .foregroundColor(.red)
                   }
                   Spacer()
               }
               VStack{
                   HStack {
                       Spacer()
                       Text("22-04-2024")
                   }
                   HStack {
                       Spacer()
                       Button(action: {
                           // Button action
                       }) {
                           Text("HELP")
                               .foregroundColor(.blue)
                               .underline()
                       }
                   }
               }
           }
           Spacer()
       }
        
       .padding(10)

//       .scaledToFit()
//       .padding(.all, 5)

//        HStack {
//            VStack(alignment: .leading) {
//                Text("KW123456789066788")
//                    .foregroundColor(.red)
//                    .font(.title3)
//                Text("KARTHIKEYAN | 7502875893")
//                    .foregroundColor(.black)
//                    .font(.title3)
//            }
//            Spacer()
//            Button(action: {
//                // Action for DOCUMENT button
//                print("DOCUMENT button tapped")
//            }) {
//                VStack {
//                    Image(systemName: "doc.text")
//                        .font(.title)
//                    Text("DOCUMENT")
//                        .foregroundColor(.black)
//                        .font(.title3)
//                }
//                .padding()
//            }
//
//            Button(action: {
//                // Action for OFFER button
//                print("OFFER button tapped")
//            }) {
//                VStack {
//                    Image(systemName: "indianrupeesign.arrow.circlepath")
//                        .font(.title)
//                    Text("OFFER")
//                        .foregroundColor(.black)
//                        .font(.title3)
//                }
//                .padding()
//            }
//            Button(action: {
//                // Action for CONTACT button
//                print("CONTACT button tapped")
//            }) {
//                VStack {
//                    Image(systemName: "phone.connection")
//                        .font(.title)
//                    Text("CONTACT")
//                        .foregroundColor(.black)
//                        .font(.title3)
//                }
//                .padding()
//            }
//
//        }.padding(.all, 20)
    }
}

Desired output:

Actual Design

Current Output: Result


Solution

  • You can get closer to your desired output with a few small changes:

    1. Scale the images to the required size

    Something like:

    Image(systemName: "menucard")
       .resizable()
       .scaledToFit()
       .frame(width: 30, height: 30)
    

    2. Set a smaller overall font size and set the width to .compressed

    VStack {
        // ...
    }
    .padding(10)
    .font(.subheadline)
    .fontWidth(.compressed)
    

    You might want to apply the compressed font style more selectively instead (in other words, only apply it to selected parts of the content, where it is actually needed).

    3. Use even smaller fonts for detail rows

    For example, use .footnote or even .caption where a smaller font is needed.

    4. Prevent text truncation where necessary

    Text truncation (with ellipses) can be prevented by setting a line limit and then allowing the font to be scaled to fit in the space available. Taking the HStack with the icons as an example:

    HStack{
        // ...
    }
    .font(.caption)
    .allowsTightening(true)
    .lineLimit(1)
    .minimumScaleFactor(0.5)
    

    5. Use a Grid for the detail rows

    By using a Grid, the second row of detail can be brought into alignment with the first row of detail.

    • Use Grid as the outer container for the rows, like a VStack.
    • Replace the nested HStack with GridRow.
    • Apply .gridCellColumns(2) to content that should occupy a width of 2 cells.
    • Include the Divider() as the first grid row, as this forces the grid to use the full screen width.

    6. Remove the last Spacer

    This spacer was adding unnecessary space at the bottom.

    Here is the fully-updated code:

    VStack {
        HStack {
            VStack(alignment: .leading) {
                Text("KW123456789066788")
                    .foregroundColor(.red)
                Text("KARTHI | 7502875893")
                    .foregroundColor(.black)
            }
            Spacer()
            HStack {
                VStack {
                    Image(systemName: "menucard")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 30, height: 30)
                    Text("REPORT")
                }
                VStack {
                    Image(systemName: "menucard")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 30, height: 30)
                    Text("DOCUMENTS")
                }
                VStack {
                    Image(systemName: "menucard")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 30, height: 30)
                    Text("CONTACT")
                }
            }
            .font(.caption)
            .allowsTightening(true)
            .lineLimit(1)
            .minimumScaleFactor(0.5)
        }
        VStack(spacing: 10) {
            Grid(alignment: .leading, verticalSpacing: 10) {
                Divider()
                    .frame(height: 1)
                    .background(.gray)
                    .gridCellColumns(4)
                GridRow {
                    Text("HYNDAI CRETA 1.5 - CHENNAI")
                        .foregroundColor(.black)
                        .gridCellColumns(3)
                    Text("NEW-PRIVATE")
                        .foregroundColor(.cyan)
                }
                GridRow {
                    VStack(alignment: .leading, spacing: 10.0) {
                        Text("REGNO")
                        Text("TN09CQ0925")
                            .bold()
                    }
                    VStack(alignment: .leading, spacing: 10.0) {
                        Text("TENURE")
                        Text("60 MONTHS")
                            .bold()
                    }
                    VStack(alignment: .leading, spacing: 10.0) {
                        Text("EMI")
                        Text("23456")
                            .bold()
                    }
                    VStack(alignment: .leading, spacing: 10.0) {
                        Text("LOAN AMOUNT")
                        Text("3446667")
                            .bold()
                    }
                }
                GridRow {
                    VStack(alignment: .leading, spacing: 10.0) {
                        Text("DEALER")
                        Text("KUWY001")
                            .bold()
                    }
                    .gridCellColumns(2)
    
                    VStack(alignment: .leading, spacing: 10.0) {
                        Text("LOS NUMBER")
                        Text("5678JKSKS888")
                            .bold()
                    }
                    .gridCellColumns(2)
                }
                .foregroundColor(.black)
                .font(.footnote)
            }
            HStack {
                VStack(alignment: .leading, spacing: 10.0) {
                    Text("AXIS BANK")
                    Text("TEST CASE REJECED BY KAMS")
                        .foregroundColor(.red)
                }
                Spacer()
            }
            VStack {
                HStack {
                    Spacer()
                    Text("22-04-2024")
                }
                HStack {
                    Spacer()
                    Button(action: {
                        // Button action
                    }) {
                        Text("HELP")
                            .foregroundColor(.blue)
                            .underline()
                    }
                }
            }
        }
    }
    .padding(10)
    .font(.subheadline)
    .fontWidth(.compressed)
    

    And here's how it looks:

    Screenshot

    If the text items were mixed case (instead of all uppercase) then it might be easier to read and you could probably take off the compressed font style in some places. Uppercase text requires more width than mixed case.