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.
Ui woes
-
Been doing some heavy UI work, and Here are a few quirks/bugs I've found:
keyboard_get_frame
and associated methods don't work in fullscreen, except in portrait, and only the view was started in portrait. In landscape, or if device is rotated, we get bad values.
Here is a sequence dumping out keyboard frame starting in portrait, and rotating clockwise
start portrait kb frame ... = (0.0, 760.0, 768.0, 264.0) correct kb frame ... = (416.0, 0.0, 352.0, 1024.0) maybe correct if x,y,w,h are really y,x,h,w kb frame ... = (0.0, 0.0, 768.0, 264.0). Incorrect y kb frame ... = (0.0, 0.0, 352.0, 1024.0) also incorrect kb frame ... = (0.0, 760.0, 768.0, 264.0) correct again, original orientation
Next, I restarted in landscape, and repeated the test
start in landscape kb frame ... = (416.0, 0.0, 352.0, 768.0) hmmm. That's not right, should be 1024 width kb frame ... = (0.0, 0.0, 768.0, 264.0) nope...y is wrong kb frame ... = (0.0, 0.0, 352.0, 768.0). Still wrong kb frame ... = (0.0, 760.0, 768.0, 8.0). Nope kb frame ... = (416.0, 0.0, 352.0, 768.0)
Things seem to work ok in sheet, panel, etc. but,
-
in sheet view, the view's frame property lies about the x,y position. I guess this is because the view cannot be repositioned, however, it makes it tricky to figure out where the keyboard frame is relative to the view.
-
callbacks like
keyboard_frame_will_change
continue to be called even after the view is closed. I'm not sure if this is a desirable situation, it can lead to funny situations that require restart ( an exception in the will change function ends up in and endless cycle that can't be fixed by going back to console, etc. -
changing a views size within
draw()
can cause strange problems. Like it seems the drawing context is set to original bounds. The issue is that, sincemeasure_string
can only be called from within draw(), if I want to resize the view to hold the string, there is no way to do it.
-
Try using
ui.convert_point
andui.convert_rect
. Both functions take a point/rect tuple and two views as arguments, and will translate the point/rect's coordinates from the first view's system into the second view's system. SettingNone
as one of the views will convert from/to absolute screen coordinates, so you might want to runui.convert_rect(ui.get_keyboard_frame(), None, your_view)
to get correct relative coordinates. -
Thanks, that solves item 2, as it should let me get the keyboard relative to a sheet.
But in fullscreen, the keyboard frame returns garbage!
-
When are you checking the keyboard frame? You may have to wait a second or two after selecting the text field, otherwise you may be measuring the keyboard while the sliding animation is still happening. If you're using iOS 8, the keyboard size may also vary because of the word preditction bar above the keyboard.
-
I am using the argument to
keyboard_frame_
did_change
, which seems to trigger after the animation is complete. The will and the did change method always get the same argument, onlyget_keyboard_frame
is subject to a delay.... I have done experiments using delays, and the result is the same. See below. When running fullScreen landscape, this always reports a height of 1024, instead of width of 1024. The top box shows the delayed version, the second shows the frame passed to the did change method.Otherwise works perfectly in panel, sheet,etc
import ui class testkb(ui.View): def __init__(self): self.bg_color=(1,1,0) self.t1=ui.Label(frame=(0,0,400,20)) self.t2=ui.Label(frame=(0,30,400,20)) self.t3=ui.Label(frame=(0,60,400,20)) self.t4=ui.Label(frame=(0,90,400,20)) self.t5=ui.TextView(frame=(0,120,400,20)) [self.add_subview(s) for s in [self.t1,self.t2,self.t3,self.t4,self.t5]] self.t5.begin_editing() def keyboard_frame_did_change(self,frame): if self.on_screen: self.t2.text='kb frame ... = {0:3}'.format(frame) self.t3.text='frame = {0:3}'.format(self.frame) self.t4.text='biunds = {0:3}'.format(self.bounds) ui.delay(self.update_frame,3.0) def update_frame(self): self.t1.text='delayed ={0:3}'.format(ui.get_keyboard_frame()) #print self.t1.text T=test() T.present('fullscreen')
-
'kay, I didn't even know that the
keyboard_frame_did_change
method is a thing. Thanks for telling me.