@mikael And with that all the changes are implemented.
Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Best posts made by Samer
-
RE: UIPageControl (Paging scrollview with page indicators)
-
RE: UIPageControl (Paging scrollview with page indicators)
@stephen A bit of both, I have a project in the works that started out as a way to explore the ui module, it then morphed into learning about the objc_utils module a bit (MapView, ProgressView, UIPageControl) and then finally into wanting to create an app for the app store. This is just one part of a larger project. However I have probably had the most fun on this one part then all the others combined.
-
RE: UIPageControl (Paging scrollview with page indicators)
I just edited the post with v0.4. Let me know what you people think!
-
RE: UIPageControl (Paging scrollview with page indicators)
I have just edited the post with a new version. (v0.3 as i’m calling it).
-
UIPageControl (Paging scrollview with page indicators)
Hello!
For a project i’m currently working on I needed a UIPageControl view, I thought I would share this here in case anyone else needed it. I apologize for my terrible code style. I am very open to criticism on anything I should change.
import ui from objc_util import ObjCClass, CGRect, create_objc_class, ObjCInstance, UIColor UIPageControl = ObjCClass('UIPageControl') def changePage(_self, _cmd): self = ObjCInstance(_self) self.page_control.set_page(self.page_control.pageControl.currentPage()) ChangePageClass = create_objc_class("ChangePageClass", methods=[changePage]) class PageControl(ui.View): def __init__(self, **kwargs): self.scrollView = ui.ScrollView( delegate=self, paging_enabled=True, shows_horizontal_scroll_indicator=False, bounces=False, frame=self.bounds, flex='WH', ) self.pageControl = UIPageControl.alloc().init().autorelease() self._target = ChangePageClass.new().autorelease() self._target.page_control = self self.pageControl.addTarget_action_forControlEvents_(self._target, 'changePage', 1 << 12) #1<<12 = 4096 self.pageControl.numberOfPages = len(self.scrollView.subviews) self.pageControl.currentPage = 0 self.pageControl.hidesForSinglePage = True self._prev_page = 0 super().add_subview(self.scrollView) ObjCInstance(self).addSubview_(self.pageControl) super().__init__(**kwargs) def present(self, *args, **kwargs): if 'hide_title_bar' in kwargs and kwargs['hide_title_bar']: #Temp work around for possible bug. background = ui.View(background_color=self.background_color) background.present(*args, **kwargs) self.frame = background.bounds background.add_subview(self) else: super().present(*args, **kwargs) def layout(self): self.scrollView.content_size = (self.scrollView.width * len(self.scrollView.subviews), 0) safe_bottom = self.bounds.max_y - self.objc_instance.safeAreaInsets().bottom size = self.pageControl.sizeForNumberOfPages_(self.pageControl.numberOfPages()) self.pageControl.frame = CGRect( (self.bounds.center().x - self.bounds.width / 2, safe_bottom - size.height), (self.bounds.width, size.height)) for i, v in enumerate(self.scrollView.subviews): v.x = i * self.bounds.width self.set_page(self.pageControl.currentPage()) def scrollview_did_scroll(self, scrollView): pageNumber = round(self.scrollView.content_offset[0] / (self.scrollView.content_size.width/len(self.scrollView.subviews)+1)) self.pageControl.currentPage = pageNumber self._trigger_delegate() def add_subview(self, page): self.pageControl.numberOfPages = len(self.scrollView.subviews) + 1 page.frame = self.scrollView.bounds page.flex = 'WH' self.scrollView.add_subview(page) self.layout() def _objc_color(self, color): return UIColor.colorWithRed_green_blue_alpha_(*ui.parse_color(color)) def _py_color(self, objc_color): return tuple([c.floatValue() for c in objc_color.arrayFromRGBAComponents()]) if objc_color else None def _trigger_delegate(self): try: callback = self.delegate.page_changed except AttributeError: return if self.pageControl.currentPage() is not self._prev_page: callback(self, self.pageControl.currentPage()) self._prev_page = self.pageControl.currentPage() def set_page(self, page_number): if page_number < self.pageControl.numberOfPages() and page_number > -1: x = page_number * self.scrollView.width self.scrollView.content_offset = (x, 0) else: raise ValueError("Invalid Page Number. page_number is zero indexing.") @property def page_count(self): return self.pageControl.numberOfPages() @property def current_page(self): return self.pageControl.currentPage() @property def hide_on_single_page(self): return self.pageControl.hidesForSinglePage() @hide_on_single_page.setter def hide_on_single_page(self, val): self.pageControl.hidesForSinglePage = val @property def indicator_tint_color(self): """Returns un-selected tint color, returns None as default due to .pageIndicatorTintColor() returning that""" return self._py_color(self.pageControl.pageIndicatorTintColor()) @indicator_tint_color.setter def indicator_tint_color(self, val): self.pageControl.pageIndicatorTintColor = self._objc_color(val) @property def indicator_current_color(self): """Returns selected tint color, returns None as default due to .currentPageIndicatorTintColor() returning that""" return self._py_color(self.pageControl.currentPageIndicatorTintColor()) @indicator_current_color.setter def indicator_current_color(self, val): self.pageControl.currentPageIndicatorTintColor = self._objc_color(val) if __name__ == '__main__': class SampleDelegate(): def __init__(self): pass def page_changed(self, sender, page_number): """Gets called every time the page changes.""" print(f'Sender: {sender}, Delegate: {page_number}') pages = PageControl() sv = ui.View() sv.background_color = 'red' sv1B = ui.Button() sv1B.title = "Go To Page 3 (index 2)" sv1B.frame = (100,100,200,100) def btn_action(sender): pages.set_page(2) sv1B.action = btn_action sv.add_subview(sv1B) sv2 = ui.View() sv2.background_color = 'blue' sv3 = ui.View() sv3.background_color = 'yellow' pages.indicator_tint_color = 'brown' pages.indicator_current_color = 'black' pages.add_subview(sv) pages.add_subview(sv2) pages.add_subview(sv3) pages.delegate = SampleDelegate() print(pages.indicator_tint_color) print(pages.indicator_current_color) print(pages.page_count) print(pages.current_page) print(pages.hide_on_single_page) pages.present('fullscreen')
Gist: https://gist.github.com/samerbam/8062c6075283a2c190812ddc925c015a
Changelog:
v0.2:
m.scrollView.add_subview(view)
->m.add_subview(view)
m.tintColor
to set un-selected dot colourm.currentTintColor
to set selected dot colour- No longer need to manually set x position on each page
— x and y pos acts as offset from edge of screen (like normal) - Moved some objc class creations out of __init__ (still working on this)
- Mirrored to gist
v0.3:
- Finished moving objc class creations out of
__init__
m.TintColor
->m.tint_color
m.currentTintColor
->m.current_tint_color
m.current_page
returns the current page your onm.page_count
returns total amount of pages- Switched from
ui.get_screen_size()
to usingself.bounds
— Should allow for compatibility with more advanced UI’s
v0.4
- Fixed bug where tapping on either side of dots to change page would only work on first launch.
m.tint_color
->m.indicator_tint_color
m.current_tint_color
->m.indicator_current_color
- Added delegate callback
page_changed
set delegate to class that includespage_changed(self, page_number)
- Added
set_page
method to change the page programmatically - Added
hide_on_single_page
attribute (defaults to true) hides dots with only one page.
v0.5
- Changed example slightly to include a weirdly placed button.
- Added explicit call to
self.layout()
inadd_subview
- Removed call to
_trigger_delegate
fromset_page
, asset_page
triggersscrollview_did_scroll
which calls_trigger_delegate
v0.6
- Switched from
hasattr
totry: except AttributeError:
- Implemented a work around for a bug involving the view jumping down ~20 pixels. (Really dislike this, however it seems like the best I could do at the moment)
- Removed unnecessary attribute
pNum
- Switched from setting
width
andheight
of each subview manually to usingflex
- Renamed
PageControl
instance in example topages
fromm