Keyboard frame change view methods oddness...
@JonB well, I guess these issues still exist. Honestly, the situations where this is an actual problem are relatively unlikely to occur in the real-world use of my app, especially when I just ignore the repeated calls by comparing stored state and discarding superfluous ones.
It's good to know that it isn't something I'm doing wrong, and I'll just hope that the next release of Pythonista fixes the issue. Thanks for the info, though!
@shinyformica, reminder: the keyboard change events keep firing after your script ends, so be sure to check ui.on_screen before doing anything.
So now that I'm a little less timid about reaching into objc when necessary...looks like if I just register to be notified of the:
they are delivered in a much more reliable fashion than the window change methods available in ui.View. You get a single pair of notifications for each change in keyboard size, which means as long as you know which widget is receiving keyboard input, you can easily place it at the right location with a nice ui.animate().
Seems to work reliably.
@mikael I am definitely tracking whether my app is active or not, but important safety tip there.
JonB last edited by
I am only seeing one keyboard_did_change call -- however if you run multiple views, or run a a script multiple times, you can seem to get multiple call backs.
The bug seems to be related to how the view is first presented -- it is right when first presented, but after rotation it is wrong.
I started writing up a UINotifocationCenter approach. Seems to be reliable. The trick is you need to make sure you unregister your observer when the python object is deleted -- I'm playing around with some ideas that uses a "canary" object and a weakref.finalize-r to deregister observers in a more robust manner..
JonB last edited by
By the way, you might also consider using
in leui of delegates to keep track of which control asked for the keyboard.
I'm not sure which order these get called, but you can use objc_setAssociatedObject(app, ns('currentTextField'), current_textfield_objcinstance, 0) to basically store the current field at the UIApplication.sharedApplication() level, making it easy to retrieve whenever. You could also store the kb frame in a similar way, to allow a working get_keyboard_frame method.
@JonB yep, I traced it to the multiple-run issue as well...which meant my unregister wasn't properly happening either. I've gotten that mostly fixed, but I still actually prefer the NSNotificationCenter way of receiving keyboard change notifications better...since it's more app-global, and not view-specific.
I am using UITextViewTextDidBeginEditingNotification, UITextFieldTextDidBeginEditingNotification, etc. to track which widget is the active one, that seems to be really the only way...without iterating over views to find the firstResponder view. What I have now works quite well, but I need to make the unregistering part more robust.
shinyformica last edited by shinyformica
Actually, to be clear, it seems like the multiple-keyboard-change call thing was not simply multiple-run, but also having multiple views which implement those methods. The combination made it so more than one view would end up fiddling with global state, using the plain notifications and a single receiver for them, I am guaranteed single notification.
@shinyformica, would be much appreciated if you package this up as something reusable. The lack of reliable keyboard size notifications has always been a pain.
@mikael yes, I think it would be good to package it. Or at least post template code for how to do it. I'll do that when I get a moment to this thread. What do we normally use to put up reusable code snippets? Is it this Gist thing I keep seeing?
@shinyformica, gist seems good if it is clear that it is not going to need many revisions, issues, a Readme or collaboration. Otherwise, a git repo is not that much more work.