【问题标题】:SwiftUI WidgetKit: How to anchor views to the topSwiftUI WidgetKit:如何将视图锚定到顶部
【发布时间】:2021-01-25 03:22:03
【问题描述】:

我正在尝试使用 SwiftUI 和 WidgetKit 来布局 tableView,并希望获得与 Apple 的 Notes 小部件类似的结果。

我当前的实现成功地在.systemLarge 小部件中布置视图,但在.systemMedium 小部件中没有。我想将视图固定到小部件的顶部,这样“FAVOURITES”的标题在.systemMedium 中可见。

struct PlacesWidgetEntryView : View {
    var entry: Provider.Entry

    let places = [
        Place(name: "Place 1", imageName: "baseline_star_black_24pt"),
        Place(name: "Place 2", imageName: "baseline_star_black_24pt"),
        Place(name: "Place 3", imageName: "baseline_star_black_24pt"),
        Place(name: "Place 4", imageName: "baseline_star_black_24pt"),
        Place(name: "Place 5", imageName: "baseline_star_black_24pt"),

    ]
    
    var body: some View {
        VStack {
            //Header
            HStack {
                Text("FAVOURITES")
                    .bold()
                    .frame(height: 8)
                Spacer()
            }
            .padding()
            .background(Color.blue)

            //TableView
            LazyVStack {
                ForEach(places, id: \.self) { place in
                    PlaceRow(place: place)
                }
            }
            Spacer()
        }
    }
}

struct PlaceRow: View {
    let place: Place
    
    var body: some View {
        HStack {
            Text(place.name)
                .font(.body)
            Spacer()
            Image(place.imageName)
                .resizable()
                .frame(width: 28, height: 28, alignment: .center)
        }
        .padding(.horizontal)
        .padding(.vertical, 4)
    }
}

实施结果:

上面是.systemLarge,很好,符合我的预期。

上面是.systemMedium,这不是我所期待的。我希望看到“收藏夹”锚定在 widgetView 的顶部,并且 tableView 可能会溢出到底部。

【问题讨论】:

    标签: ios swift swiftui widgetkit


    【解决方案1】:

    这是可能的布局解决方案。使用 Xcode 12 测试。

    var body: some View {
        VStack(spacing: 0) {
            HStack {
                Text("FAVOURITES")
                    .bold()
                    .frame(height: 8)
                Spacer()
            }
            .padding()
            .background(Color.blue)
            
            Color.clear
                .overlay(
                    LazyVStack {
                        ForEach(places, id: \.self) { place in
                            PlaceRow(place: place)
                        }
                    },
                    alignment: .top)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    

    【讨论】:

      【解决方案2】:

      因此,在 WidgetKit 中玩耍时,似乎如果小部件中有太多视图,它就会开始将上方的视图推离屏幕。如果您向数组中添加更多位置,您会看到大型小部件也会发生同样的事情。您可以做的是创建单独的视图:一个用于中型,一个用于大型小部件,对于中型,只需使用 1-3 个地点对象来填充它。

      您可以在 PlacesEntryWidgetView 中使用 switch 语句和 widgetFamily 来决定要在视图上显示什么。我还将图像的高度从 28 略微降低到 24。

      struct PlacesWidgetEntryView : View {
          var entry: Provider.Entry
          @Environment(\.widgetFamily) var family
          
          let places = [
                  Place(name: "Place 1", imageName: "blackStar"),
                  Place(name: "Place 2", imageName: "blackStar"),
                  Place(name: "Place 3", imageName: "blackStar"),
                  Place(name: "Place 4", imageName: "blackStar"),
                  Place(name: "Place 5", imageName: "blackStar"),
                  Place(name: "Place 6", imageName: "blackStar"),
                  Place(name: "Place 7", imageName: "blackStar"),
                  Place(name: "Place 8", imageName: "blackStar")
              ]
      
          @ViewBuilder
          var body: some View {
              switch family {
              case .systemMedium:
                  // widget can only show so many views so I only took first 3 places
                  WidgetView(places: Array(places.prefix(3)))
              case .systemLarge:
                  WidgetView(places: places)
              // I only have it set to show system medium so you can ignore
              // the last case
              case .systemSmall:
                  Text("")
              @unknown default:
                  Text("")
              }
          }
      }
      
      struct WidgetView: View {
          let places: [Place]
          
          var body: some View {
              VStack {
                  //Header
                  HStack {
                      Text("FAVOURITES")
                          .bold()
                          .frame(height: 8)
                      Spacer()
                  }
                  .padding()
                  .background(Color.blue)
      
                  //TableView
                  LazyVStack {
                      ForEach(places, id: \.self) { place in
                          PlaceRow(place: place)
                      }
                  }
                  Spacer()
              }
          }
      }
      
      struct PlaceRow: View {
          let place: Place
          
          var body: some View {
              HStack {
                  Text(place.name)
                      .font(.body)
                  Spacer()
                  Image(place.imageName)
                      .resizable()
                      .frame(width: 28, height: 24, alignment: .center)
              }
              .padding(.horizontal)
              .padding(.vertical, 4)
          }
      }
      

      这是预览:

      请记住,您可能希望在模拟器之间切换,以确保您的小部件在所有设备上看起来都不错。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-16
        • 1970-01-01
        • 1970-01-01
        • 2021-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-04
        相关资源
        最近更新 更多