From a bit of searching it seems like prefersStatusBarHidden
(source) returns true/false if the view controller is requesting the status bar to be hidden. Not sure if this would work, just thought I would through in what I found.
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.
Posts made by Samer
-
RE: Title Bar and Objc_util
-
RE: UIPageControl (Paging scrollview with page indicators)
@stephen There are two problems I encountered with that solution, the first is that when
hide_title_bar=True
The whole view is shifted down 20px. The second is that on my iPad it still jumps down a few pixels, yet it doesn’t on my iPhone. I wish the solution was that simple however it is unfortunately not. -
RE: UIPageControl (Paging scrollview with page indicators)
I took a few days to think about this bug/feature. I implemented a workaround for it which at the very least hides the problem. I don’t like it, but it works. If anyone has a better solution then overriding the present method, I would be happy to replace my current solution with it.
-
RE: UIPageControl (Paging scrollview with page indicators)
@mikael huh, thats very strange I get the same effect using your example on my IPad Pro 11” (2018). It seems like initially the view overlaps with the info bar at the top of the screen (time, wifi, battery, etc) and upon touching the screen the view shifts down to not overlap with it. It’s hard to tell in your example due to the black text on black background. However if you set
hide_title_bar
to true in the built in example a similar effect happens. I will look into a fix in the next day or two. -
RE: UIPageControl (Paging scrollview with page indicators)
@mikael And with that all the changes are implemented.
-
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)
@mikael Thank you again for this feedback.
What do you mean by:
- Exposing a
page_changed
callback with adelegate
parameter forself
.
I have not played around with callbacks very much and would appreciate some guidance on how to implement something like this.
- Exposing a
-
RE: UIPageControl (Paging scrollview with page indicators)
I have just edited the post with a new version. (v0.3 as i’m calling it).
-
RE: UIPageControl (Paging scrollview with page indicators)
I have a quick question about:
- The color properties are convenient, but return None if the defaults are not changed. I would prefer just to use a "reverse" color function, see below. It would have the additional benefit of removing the extra internal variables.
def _py_color(self, objc_color): return tuple([c.floatValue() for c in objc_color.arrayFromRGBAComponents()])
Specifically what you were referring to witharrayFromRGBAComponents()
I wasn’t able to find a reference to it anywhere. Also i’m assuming that by objc_color I would be passing in the UIColor that _objc_color creates.
Scratch that, Turns out I was passing in the wrong thing.Thank you everyone for all the help, I really appreciate it!
-
RE: UIPageControl (Paging scrollview with page indicators)
@mikael I really enjoy this type of programming as well, It gives me an external view and makes me aware of certain use cases I was not aware of.
- Thanks for letting me know of super().add_subview() wish I had known about that earlier :|
- Could you explain what you mean by a
layout
method? I’m relatively new to pythonista (not so much python itself) and the UI module.
-
RE: UIPageControl (Paging scrollview with page indicators)
After a few week break, I have just updated this post with a new version that implements some of the great feedback I got.
-
RE: UIPageControl (Paging scrollview with page indicators)
@mikael Thanks for the feedback! I have a few questions about how I would go about overriding
add_subview
. How would I add the subview to the view.This snippet:
def add_subview(self, v): self.scrollView.add_subview(v)
Gives me the error:
ValueError: Cannot add self as subview
. -
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