如何在时间轴中显示多个条目内容?

Posted

技术标签:

【中文标题】如何在时间轴中显示多个条目内容?【英文标题】:How to show multiple entry content in a timeline? 【发布时间】:2021-11-18 08:23:25 【问题描述】:

我正在为我的应用程序创建一个小部件。

对于大尺寸的小部件,我想显示 4 个具有不同内容的单元格,这些单元格是我从 API 调用中获取的。但我无法做到。这是我的小部件当前的样子:

我应该为每个单元格创建不同的条目结构吗?或者有没有办法将数组/列表放入入口结构并附加我从请求中获得的 4 个数据?

关于如何实现这一点的任何建议?

我的入口结构:

struct NewsEntry: TimelineEntry 
    var date: Date
    let configuration: ConfigurationIntent
    let header: String
    let imageUrl: String

我的 getTimeline 函数:

func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) 
    var entries: [NewsEntry] = []
    let currentDate = Date()
    let later = Calendar.current.date(byAdding: .minute, value: 5, to: Date())!
    
    NewsProvider.request()  (data, error) in
        guard let data = data else 
            if let error = error 
                print(error)
            
            return
        
        
        let entry = NewsEntry(date: currentDate, configuration: configuration, header: data[0].title!, imageUrl: data[0].imageUrlDetail!)
        entries.append(entry)
        
        let timeline = Timeline(entries: entries, policy: .after(later))
        completion(timeline)
    

我的条目视图:

struct WidgetEntryView : View 
    var entry: Provider.Entry
    
    @Environment(\.widgetFamily)
    var widgetFamily

    var body: some View 
        VStack(alignment: .trailing, spacing: 6) 
            Image("logo")
                .frame(maxWidth: .infinity, alignment: .leading)

            if widgetFamily == .systemLarge 
                var columns: [GridItem] =
                         Array(repeating: .init(), count: 2)

                LazyVGrid(columns: columns) 
                    ForEach((0..<4))  index in
                        ZStack (alignment: .bottomLeading) 
                            if let url = URL(string: entry.imageUrl), let imageData = try? Data(contentsOf: url),
                            let uiImage = UIImage(data: imageData) 
                            Image(uiImage: uiImage)
                                .centerCropped()
                                .frame(maxHeight: 150, alignment: .center)
                                .cornerRadius(10)
                                        .overlay(RoundedRectangle(cornerRadius: 10)
                                        .stroke(Color.gray, lineWidth: 1))
                                        .shadow(radius: 10)
                             else 
                                Image("ph_background")
                                    .centerCropped()
                                    .frame(maxHeight: 150, alignment: .center)
                                    .cornerRadius(10)
                                            .overlay(RoundedRectangle(cornerRadius: 10)
                                            .stroke(Color.gray, lineWidth: 1))
                                            .shadow(radius: 10)
                            
                                
                            Text(entry.header)
                                    .font(.system(size: 12))
                                    .foregroundColor(.white)
                                    .fontWeight(.light)
                                    // .frame(maxHeight: 50)
                                    .background(Rectangle().fill(Color.black).blur(radius: 20))
                                    .padding(.bottom, 5)
                                    .padding(.leading, 5)
                                    .padding(.trailing, 5)
                                    .padding(.top, 5)
                        
                    
                    .frame(height: 160)
                
            
        
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        .padding()
        .background(LinearGradient(gradient: Gradient(colors: [Color(red:0.2, green:0.2, blue:0.2), .black]), startPoint: .top, endPoint: .bottom))
    

【问题讨论】:

【参考方案1】:

在 TimelineEntry 中将变量更改为 [String],我实现了我想要的。

我像这样更新了我的结构和入口行:

var newsList: [String] = [] // First, appending the fetched data here
var imageList: [String] = []

struct NewsEntry: TimelineEntry 
    var date: Date
    let configuration: ConfigurationIntent
    let header: [String]
    let imageUrl: [String]

for index in 0 ..< 5 
    newsList.append(data[index].title!)
    imageList.append(data[index].imageUrlDetail!)


// Then using passing the arrays to TimelineEntry as [String]
for hourOffset in 0 ..< 5 
    let entryDate = Calendar.current.date(byAdding: .minute, value: hourOffset, to: currentDate)!
    let entry = NewsEntry(date: entryDate, configuration: configuration, header: newsList, imageUrl: imageList)
    entries.append(entry)

现在唯一的问题是我不知道我是否正确使用它,因为我在entry.imageUrl[index] 上出现“索引超出范围”而崩溃。这是我更新的 View 函数的 LazyVGrid:

LazyVGrid(columns: columns) 
    ForEach((0..<4))  index in
        ZStack (alignment: .bottomLeading) 
            if let url = URL(string: entry.imageUrl[index]), let imageData = try? Data(contentsOf: url),
            let uiImage = UIImage(data: imageData)  // Thread 1: Fatal error: Index out of range
            Image(uiImage: uiImage)
                .centerCropped()
                .frame(maxHeight: 150, alignment: .center)
                .cornerRadius(10)
                        .overlay(RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.gray, lineWidth: 1))
                        .shadow(radius: 10)
             else 
                Image("ph_background")
                    .centerCropped()
                    .frame(maxHeight: 150, alignment: .center)
                    .cornerRadius(10)
                            .overlay(RoundedRectangle(cornerRadius: 10)
                            .stroke(Color.gray, lineWidth: 1))
                            .shadow(radius: 10)
            
                
            Text(entry.header[index])
                    .font(.system(size: 12))
                    .foregroundColor(.white)
                    .fontWeight(.light)
                    // .frame(maxHeight: 50)
                    .background(Rectangle().fill(Color.black).blur(radius: 20))
                    .padding(.bottom, 5)
                    .padding(.leading, 5)
                    .padding(.trailing, 5)
                    .padding(.top, 5)
        
    
    .frame(height: 160)

【讨论】:

我建议您遍历 entry.imageUrl 而不是固定的索引范围。 如果我按照您的建议进行迭代,如何将不同索引上的内容用于不同的单元格?小部件不应该只为所有单元格显示相同的内容吗? 您应该将headerimageUrl 组合在一个模型中,然后只拥有一个数组。喜欢struct Model let header: String let imageUrl: URL Entry models: [Model]。然后遍历所有模型

以上是关于如何在时间轴中显示多个条目内容?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 vis.js 时间轴中使用自定义语言环境

如何在 vis.js 时间轴中对嵌套组进行排序?

在 Chrome 开发工具时间轴中:红色标记是啥意思?

AngularJS:在时间轴中解析 HTML 事件

如何使用 R 中的 timevis 更改时间轴中每个组的背景颜色

在时间轴中切换图像小部件