Post

Replies

Boosts

Views

Activity

Infinite scrolling view
Even though SwiftUI offers a lot of features for building a UI, I found my self missing something. I'm trying to display a list with calendar information, one item pr. day. I want to scroll this fluently and by the nature of a calendar, there is not a specific start or end to the list, so a standard ScrollView or List does not suit the task.I've therefore tried to put a custom control together. My approach is to have 2 items more that needed, initially positioned off screen (at the top and bottom). All items have the same height to keep the layout simple. I scroll by offsetting the items. Once the offset is greater than the height of an item, I shift the contents by 1 and reposition the items so I again have the first and last item placed off screen.This method works quite well, as long a the item views are simple. When the individual items get complex, I see a stuttering effect when I drag it up and down. I suspect that the delay causing the stutter comes from the view being regenerated.Is this approach good, and if so, what can I do to optimize it to reduce/remove the stuttering effect? If not, are there any alternate ideas for a solution?I included a rough version of the source code here to give an idea of the design:struct InfinityScroller<Item:View> : View { @State private var offset : CGFloat = 0 @State private var itemIndex : Int = 0 @State private var itemOffset : CGFloat private let itemHeight : CGFloat private let zero : CGFloat private let item : (Int,CGFloat,CGFloat) -> Item private let itemCount : Int = 7 private let offScreenCount : Int = 1 init(location:ObservedObject<InfinityLocation>,zero:CGFloat,_ height:CGFloat=121,@ViewBuilder item : @escaping (Int,CGFloat,CGFloat) -> Item) { self._location = location self.zero = zero self.itemHeight = height self.item = item self._itemOffset = State(initialValue: zero) } var body : some View { GeometryReader { g in ZStack(alignment:.top) { Color.clear.frame(width:0) Color.clear.frame(height:0) self.makeItems(g.size.width) } .contentShape(Rectangle()) .gesture(DragGesture(minimumDistance: 0) .onChanged { g in self.updatePosition(g.translation.height) } .onEnded { g in self.offset += g.translation.height self.updatePosition() } ) } } func updatePosition(_ scroll:CGFloat=0) { let off = offset + scroll + zero itemIndex = -Int((off/itemHeight).rounded(.down)) itemOffset = off.mod(itemHeight) } func makeItems(_ w:CGFloat) -> some View { return ForEach (-offScreenCount...itemCount+offScreenCount,id:\.self) { i in self.item(i+self.itemIndex,w,self.itemHeight) .position(x:0,y:CGFloat(i) * self.itemHeight + self.itemOffset) .offset(x:w/2,y:self.itemHeight/2) } } }
1
0
2.2k
Feb ’20
Longpress and list scrolling
Hi,Using SwiftUI I'm trying to implement a long press gesture on items in a list, to allow user interaction with the individual items. The problem is that when I set "onLongPressGesture" anywhere in the list (on items, on the list itself), the list cannot be scrolled anymore. I can easily get a simple tap to work but a long press blocks scrolling.I've been Googling this for a couple of days now without any success. Hope someone can point me in the right direction.Yours,Jens
3
1
7.2k
Dec ’19