SwiftUI WidgetKit:如何将视图锚定到顶部

时间:2020-10-10 05:29:06

标签: ios swift swiftui widgetkit

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

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

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)
    }
}

执行结果:

Parse JSON from JQuery.ajax success data

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

enter image description here

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

2 个答案:

答案 0 :(得分:2)

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

demo

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)
}

答案 1 :(得分:0)

因此,通过在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)
    }
}

这是预览:

enter image description here

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

相关问题