Ui.ScrollView (changing what a page stop is)
does anyone know if it's possible to change the behavior of the ScrollView.paging_enabled As described below. I need/want to be able to change what it considers a page without changing the bounds of the ScrollView.
I would prefer some undocumented attr, but if can do it with objc, still ok
From the Pythonista documentation
If the value of this attribute is True, the scroll view stops on multiples of the scroll view’s bounds when the user scrolls. The default value is False.
This seems to have been a topic long enough that Apple really should have implemented a setting in UIScrollView for this.
All the solutions I found involve placing another view on top to handle interaction while clipsToBounds is used to show more of the content than what the paging thinks is visible.
One description here.
This does require a little bit of objc for setting the clipping and re-assigning the pan gesture recognizer.
Interesting, I wasn't aware of the gesture recognizer technique in @mikael's link.
Here's a little demo of using that with
objc_util. It's far from perfect, more of a proof-of-concept... The biggest limitation I see is that while scrolling works everywhere, other touches on pages that aren't the current page are ignored, i.e. if you have a button or something like that on one of the pages, it'll only work if that page is selected (in the middle of the screen in this demo). There are probably ways around that, I haven't investigated this much further.
import ui from objc_util import * from random import random class PagingScrollContainer (ui.View): def __init__(self, scroll_view, **kwargs): ui.View.__init__(self, **kwargs) self.scroll_view = scroll_view # Center the scroll view horizontally: scroll_view.frame = (self.bounds.w/2 - scroll_view.bounds.w/2, 0, scroll_view.bounds.w, self.bounds.h) scroll_view.flex = 'HLR' scroll_view.shows_horizontal_scroll_indicator = False self.add_subview(scroll_view) # Turn off clipping: _scroll_view = ObjCInstance(scroll_view) _scroll_view.clipsToBounds = False # Make sure paging is enabled (that's the point after all) _scroll_view.pagingEnabled = True # Add the scroll view's gesture recognizer to this view: _self = ObjCInstance(self) _self.addGestureRecognizer_(_scroll_view.panGestureRecognizer()) def main(): # Create a ScrollView with some colored "pages" as a demo... page_w = 200 scroll_view = ui.ScrollView(frame=(0, 0, page_w, 500)) scroll_view.content_size = (50 * page_w, 0) for i in range(50): swatch_frame = (i*page_w, 0, page_w, 500) swatch = ui.View(bg_color=(random(), random(), random()), frame=swatch_frame) scroll_view.add_subview(swatch) # Wrap it in the custom container view, and present that: container = PagingScrollContainer(scroll_view, frame=(0, 0, 500, 500)) container.present('sheet') if __name__ == '__main__': main()
Thanks guys. It's a shame it is implemented. Can see a lot of good uses for it avoiding tricky guesture coding. I thought I was on to something. Lazy mans guestures 😁
Still a useful technique though.
I was Just trying create a view like the one below. Have seen it in apps were they are advertising thier other products/apps. It's very effective having the the partial panels either side with a reduced alpha and the middle page with a alpha of 1. Would also look nicer sitting inside the blur view @omz recently posted. I am not going to try and do anything too funky. There will be other ways to to work around I am sure.