SwiftUI HStack with Wrap

后端 未结 4 600
孤街浪徒
孤街浪徒 2020-11-29 07:08

Is it possible that the blue tags (which are currently truncated) are displayed completely and then it automatically makes a line break?

NavigationLink(desti         


        
4条回答
  •  感情败类
    2020-11-29 07:35

    I have something like this code (rather long). In simple scenarios it works ok, but in deep nesting with geometry readers it doesn't propagate its size well.

    It would be nice if this views wraps and flows like Text() extending parent view content, but it seems to have explicitly set its height from parent view.

    https://gist.github.com/michzio/a0b23ee43a88cbc95f65277070167e29

    Here is the most important part of the code (without preview and test data)

    [![private func flow(in geometry: GeometryProxy) -> some View {
    
            print("Card geometry: \(geometry.size.width) \(geometry.size.height)")
    
            return ZStack(alignment: .topLeading) {
                //Color.clear
                ForEach(data, id: self.dataId) { element in
                    self.content(element)
                        .geometryPreference(tag: element\[keyPath: self.dataId\])
                        /*
                        .alignmentGuide(.leading) { d in
                            print("Element: w: \(d.width), h: \(d.height)")
                            if (abs(width - d.width) > geometry.size.width)
                            {
                                width = 0
                                height -= d.height
                            }
    
                            let result = width
    
                            if element\[keyPath: self.dataId\] == self.data.last!\[keyPath: self.dataId\] {
                                width = 0 //last item
                            } else {
                                width -= d.width
                            }
                            return result
                        }
                        .alignmentGuide(.top) { d in
                            let result = height
                            if element\[keyPath: self.dataId\] == self.data.last!\[keyPath: self.dataId\] {
                                height = 0 // last item
                            }
                            return result
                        }*/
    
                        .alignmentGuide(.top) { d in
                            self.alignmentGuides\[element\[keyPath: self.dataId\]\]?.y ?? 0
                        }
                        .alignmentGuide(.leading) { d in
                            self.alignmentGuides\[element\[keyPath: self.dataId\]\]?.x ?? 0
                        }
                }
            }
            .background(Color.pink)
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
            //.animation(self.loaded ? .linear(duration: 1) : nil)
    
            .onPreferenceChange(_GeometryPreferenceKey.self, perform: { preferences in
    
                    DispatchQueue.main.async {
                        let (alignmentGuides, totalHeight) = self.calculateAlignmentGuides(preferences: preferences, geometry: geometry)
                        self.alignmentGuides = alignmentGuides
                        self.totalHeight = totalHeight
                        self.availableWidth = geometry.size.width
                    }
            })
        }
    
        func calculateAlignmentGuides(preferences: \[_GeometryPreference\], geometry: GeometryProxy) -> (\[AnyHashable: CGPoint\], CGFloat) {
    
            var alignmentGuides = \[AnyHashable: CGPoint\]()
    
            var width: CGFloat = 0
            var height: CGFloat = 0
    
            var rowHeights: Set = \[\]
    
            preferences.forEach { preference in
                let elementWidth = spacing + preference.rect.width
    
                if width + elementWidth >= geometry.size.width {
                    width = 0
                    height += (rowHeights.max() ?? 0) + spacing
                    //rowHeights.removeAll()
                }
    
                let offset = CGPoint(x: 0 - width, y: 0 - height)
    
                print("Alignment guides offset: \(offset)")
                alignmentGuides\[preference.tag\] = offset
    
                width += elementWidth
                rowHeights.insert(preference.rect.height)
            }
    
            return (alignmentGuides, height + (rowHeights.max() ?? 0))
        }
    }][1]][1]
    

提交回复
热议问题