ScrollViewReader scrollTo with .center anchor bug? - swiftui

So I'm try to use ScrollViewReader to programmatically scroll a horizontal scroll view. I thought it would work like scrollToItem with .centeredHorizontally in UIKit, and for the most part it does, but the last few elements in the scroll view are being forcefully scrolled to the center of the screen, despite the fact that the scroll view isn't normally able to scroll that far over (without snapping back after releasing the drag, at least). This ends up creating white space across the trailing half of the screen.
I've seen some other questions about this and it seems like the general opinion is that it's not a bug? On the one hand I suppose we're telling the scroll view to center the item, and it's doing just that -- so, not a bug? On the other hand, that's not how similar functionality worked in UIKit. Also, this behavior is only happening on the trailing end of the scroll view! If it was the intended behavior I would expect that scrolling to the first element in the scroll view using .center anchor would force it into the center of the screen and leave leading white space, but this doesn't happen.
Is there an elegant solution to this? Or do we have to calculate the width of our elements + spacing and figure out based on the screen width whether we should anchor .center or just scroll to the last element with anchor .trailing in order to replicate the UIKit behavior?

I found a package (Amzd/ScrollViewProxy) that was made before ScrollViewReader was released that functions much the same as ScrollViewReader, but also seems to not have the bug (if it is a bug) detailed in the question.
Usage examples can be seen on the repository page, but here's a quick minimal example.
ScrollView(.horizontal) { scrollProxy in
ForEach(sections) { section in
Text(section.text)
.scrollId(section.id)
}
.onChange(of: index) {
scrollProxy.scrollTo(
sections[index].id,
alignment: .center
)
}
}
The package adds a convenience init to ScrollView to give access to the scrollProxy.

I can confirm this behavior and think it should be considered a bug. Especially since the scroll view will "jump" into position on the first touch event.
As of iOS 15.4 Beta 1 this is fixed for me. Maybe give it another try.

Related

How to make a Famo.us Scrollview not bounce

I have a client that doesn't like the bounce effect on the edge hit of the scrollview. So I'm looking to make the scrollview not bounce and act more 'normal'. In truth I'd really like it to bounce but only on the top.
From looking at the scrollview I've got no idea how to do this with a scrollview without heavily modifying it. At that point I'm not sure that using a scroller and a draggable wouldn't be a better solution.
Any thoughts?
Edit: why was this down-voted?
Note that on OS X or iOS this is not possible, as Apple likes the bounce of a page and it is native behaviour. Famous does add on top of that, however, and THAT can be turned off:
for a ScrollContainer:
new ScrollContainer({
scrollview : {
edgeGrip : 1
}
});
for a Scrollview:
new Scrollview({
edgeGrip : 1
});
It's as simple as that ;-)
The scrollview will not bounce anymore unless the operating system wants it to bounce.
I tried Stephan's suggestion to use edgeGrip and it doesn't stop the edge bouncing running under Chrome. The other edge parameters didn't improve the behavior either. However I did find that speedLimit helps to reduce the bounce. Not a perfect solution but it might be enough depending on your requirements.
new Scrollview({
speedLimit: 0.6
});
Update: This doesn't seem to help as much with mobile Chrome :-/

Famo.us' Scrollview pagination: How to snap only when NEAR an edge?

The Famo.us Scrollview has a pagination feature that allows you to snap to the closest item.
Imagine you have a small container which has items with lots of content.
As soon as you want to scroll down to read the content outside the container, it either snaps back to the top, or snaps to the next item.
Does anybody know how to activate pagination only within a thresshold (X pixels) of an edge? That would be awesome.
Codepen demonstrating the problem here: http://codepen.io/markmarijnissen/pen/AGxaC?editors=001
var scroll = new Scrollview({
paginated: true,
pagePeriod: 500,
pageStopSpeed: 0.01, // mysterious option which might provide solution
pageSwitchSpeed: 100, // mysterious option which might provide solution
});
https://github.com/Famous/famous/blob/master/views/Scrollview.js
The TOLERANCE constant is not configurable yet. But you could easily contribute to make it configurable ;)

Absolute positioning of child views in a Famo.us ScrollView

I've a ScrollView of images, while clicking on an image (read imageSurface), I would like that one to smoothy scale to an absolute location of the screen (for example a fullscreen) this independently of the scroll state. Here is an example of a similar behaviour.
In my understanding, I should find a way to retrieve the current imageSurface location and apply a modifier with an opposite location in order to virtually detach the surface from the ScrollView. Then I might apply the modifier I would like (for example a full screen modifier).
Another option would be to override the ScrollView's render() function but I'm not sure it is a good/safe idea.
Removing the image from the sequence to quickly add it somewhere else but attached to another modifier (not in the scrollview) is also an alternative but I fear having glitches and not being able to fade it back to the sequence correctly.
Any idea on how to achieve this ?

Nest scrollviews with exclusive direction

I want to nest two scrollviews. The outer one should allow only scrolling in x-drection the inner one only y-direction.
It seems that the MouseSync of the inner scrollview always takes the mouse-event and invokes prevent-default regardless of the direction-settings.
How can such behavior be implemented?
I tried to comment first to see your use case but didn't get a response.
I needed something similar to display a list of customers and their data where to see the next customers info the design wanted to be able to scroll right or left while still being able to scroll up or down for more details on that customer. Now you can just pipe the scrollviews together but that gives an odd effect where when you slide your finger down unless its directly down no left right the whole page swivels around. I ended up using a paginated scroll view for x-direction populated by views that where a standard scrollview in the y-direction. Doing it this way I was able to set a some rules that made the left right transition not kick in till after so many pixel drag in that direction.
The codes here:
https://github.com/vizidrix/famous/blob/master/page-swaper/PageSwaper.js
If that isn't what your looking for let me know your use case.

Popover resizing erraticly

I have a UITabBarController inside a UIPopoverController, which I am displaying solely from one UIBarButtonItem. When shown I want the popover to take up the maximum vertical height allowed. It works fine if I tap to display it, then dismiss, and then rotate. However if I have the popover displayed in landscape, and then rotate to portrait, it no longer will fill the entire vertical distance. I have the tab bar controller's content size property set to 320 by 1000, and I have even tried resetting this every time the device rotates. Worse yet, when the user activates the search bar the popover shrinks up extremely small, and stays that way until the app is restarted.
http://cl.ly/3JdC to http://cl.ly/3JdC
Also http://cl.ly/3JVF
How can I stop this, and have the popover always fill up the max vertical size?
I was just having the same problem and found out that it only happens when I present the UIPopoverController using the method:
- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated
but it works fine when I use:
- (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated
Unfortunately UIBarButtonItem does not have a frame Rect you can use with this last method so my fix was to use the UIToolbar's frame and modify frame.origin.x and frame.size.width accordingly to make the popover appear on the right place next to the UIBarButtonItem.
Hopefully Apple will fix this in next releases of iOS.
Regards