简体   繁体   中英

listRowBackground UI issue after I add more than 2 list items

I have a project that contains a list where I want to use a blurred async image as the background for each list row. This works fine when I have 2 or less list rows, but when I add a 3rd it messes up the entire UI. I have no idea why it's doing this and it's pretty difficult trying to search for such a specific issue. My code for this view and some screenshots are below. Thanks in advance!

import SwiftUI

struct UserView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(sortDescriptors: []) var users: FetchedResults<CachedUser>
    @FetchRequest(sortDescriptors: []) var reviews: FetchedResults<CachedReview>
    
    @State private var showingAddUserScreen = false
    @State private var showingAddReview = false
    
    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(users, id: \.self) { user in
                        Section(user.wrappedUsername) {
                            ForEach(user.reviewsArray, id: \.self) { review in
                                NavigationLink {
                                    DetailView(review: review)
                                } label: {
                                    HStack {
                                        AsyncImage(url: URL(string: review.wrappedArtwork)) { image in
                                            image
                                                .resizable()
                                                .aspectRatio(contentMode: .fill)
                                                .frame(width: 50, height: 50)
                                        } placeholder: {
                                            Color.gray.blur(radius: 30)
                                        }
                                        VStack(alignment: .leading, spacing: 2) {
                                            Text(review.wrappedAlbumTitle)
                                                .fontWeight(.bold)
                                                .foregroundColor(.yellow)
                                            Text(review.wrappedAlbumArtist)
                                                .font(.caption)
                                                .fontWeight(.bold)
                                                .foregroundColor(.gray)
                                        }
                                    }
                                }
                                .listRowBackground(
                                    AsyncImage(url: URL(string: review.wrappedArtwork)) { image in
                                        image
                                            .resizable()
                                            .aspectRatio(contentMode: .fill)
                                            .edgesIgnoringSafeArea(.all)
                                            .blur(radius: 30)
                                    } placeholder: {
                                        Color.gray.blur(radius: 30)
                                    }
                                )

                            }
                            .onDelete(perform: deleteReview)
                        }
                    }
                    .onDelete(perform: deleteUser)
                }
            }
            .navigationTitle("Critiq")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        showingAddUserScreen.toggle()
                    } label: {
                        Label("Add User", systemImage: "plus")
                    }
                }
                
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        showingAddReview.toggle()
                    } label: {
                        Label("Add User", systemImage: "plus.square")
                    }
                }
            }
            .sheet(isPresented: $showingAddUserScreen) {
                AddUserView()
            }
            .sheet(isPresented: $showingAddReview) {
                AddReviewView()
            }
        }
    }
    
    func deleteUser(at offsets: IndexSet) {
        for offset in offsets {
            let user = users[offset]
            moc.delete(user)
        }

        try? moc.save()
    }
    
    func deleteReview(at offsets: IndexSet) {
        for offset in offsets {
            let review = reviews[offset]
            moc.delete(review)
        }

        try? moc.save()
    }
}

2 or less list items VS 3 or more 当我只有 2 个或更少时

在此处输入图像描述

I was curious about this one as you mentioned it broke when you added a third item, two items would make up a header and footer, a third would be an item...then I started to play around with it.

If you remove the .clipped code from my sample you can see that when there are three or more items, the content in the middle bleeds out.

If you keep the clipped it doesn't look as nice. You could probably get the effect you're after with some other combination of clipping/masking/list styles

import SwiftUI

struct Review {
  let wrappedArtwork: String
  let wrappedAlbumTitle: String
  let wrappedAlbumArtist: String
}

extension Review: Hashable {
  
  static func == (lhs: Review, rhs: Review) -> Bool {
    lhs.wrappedAlbumTitle == rhs.wrappedAlbumTitle &&
    lhs.wrappedAlbumArtist == rhs.wrappedAlbumArtist
  }
  
  func hash(into hasher: inout Hasher) {
    hasher.combine(wrappedAlbumTitle)
    hasher.combine(wrappedAlbumArtist)
  }
}

struct User {
  
  let wrappedUsername: String
  let reviewsArray: [Review]
}

extension User: Hashable {
  
  static func == (lhs: User, rhs: User) -> Bool {
    lhs.wrappedUsername == rhs.wrappedUsername
  }
  
  func hash(into hasher: inout Hasher) {
    hasher.combine(wrappedUsername)
  }
}

class UserObject: ObservableObject {
  @Published var users: [User] = []
  
  init(users: [User]) {
    self.users = users
  }
}

struct UserView: View {
  
  @EnvironmentObject var userObject: UserObject
  
  @State private var showingAddUserScreen = false
  @State private var showingAddReview = false
  
  var body: some View {
    NavigationView {
      VStack {
        List {
          ForEach(userObject.users, id: \.self) { user in
            Section(user.wrappedUsername) {
              ForEach(user.reviewsArray, id: \.self) { review in
                NavigationLink {
                  EmptyView()
                } label: {
                  HStack {
                    AsyncImage(url: URL(string: review.wrappedArtwork)) { image in
                      image
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(width: 50, height: 50)
                        .clipped()
                    } placeholder: {
                      Color.gray.blur(radius: 30)
                    }
                    VStack(alignment: .leading, spacing: 2) {
                      Text(review.wrappedAlbumTitle)
                        .fontWeight(.bold)
                        .foregroundColor(.yellow)
                      Text(review.wrappedAlbumArtist)
                        .font(.caption)
                        .fontWeight(.bold)
                        .foregroundColor(.gray)
                    }
                  }
                }
                .listRowBackground(
                  AsyncImage(url: URL(string: review.wrappedArtwork)) { image in
                    image
                      .resizable()
                      .aspectRatio(contentMode: .fill)
                      .edgesIgnoringSafeArea(.all)
                      .blur(radius: 30)
                      .clipped()
                  } placeholder: {
                    Color.gray.blur(radius: 30)
                  }
                )
                
              }
            }
          }
        }
      }
      .navigationTitle("Critiq")
    }
  }
  
}

struct UserView_Previews: PreviewProvider {
  
  static var review1 = Review(wrappedArtwork: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", wrappedAlbumTitle: "my title 1", wrappedAlbumArtist: "my artist")
  static var review2 = Review(wrappedArtwork: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", wrappedAlbumTitle: "my title 2", wrappedAlbumArtist: "my artist")
  static var review3 = Review(wrappedArtwork: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", wrappedAlbumTitle: "my title 3", wrappedAlbumArtist: "my artist")
  static var review4 = Review(wrappedArtwork: "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", wrappedAlbumTitle: "my title 4", wrappedAlbumArtist: "my artist")
  
  static var fourObjects = UserObject(users: [User(wrappedUsername: "Bob", reviewsArray: [review1, review2, review3, review4])])
  
  static var threeObjects = UserObject(users: [User(wrappedUsername: "Bob", reviewsArray: [review1, review2, review3])])
  
  static var twoObjects = UserObject(users: [User(wrappedUsername: "Bob", reviewsArray: [review1, review2])])
  
  static var previews: some View {
    Group {
      UserView()
        .environmentObject(twoObjects)
        .previewDisplayName("two items")
      UserView()
        .environmentObject(threeObjects)
        .previewDisplayName("three items")
      UserView()
        .environmentObject(fourObjects)
        .previewDisplayName("four items")
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM