omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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.TextView, detect if virtual keyboard is open/visible

    Pythonista
    5
    15
    4266
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • stephen
      stephen @rownn last edited by

      This post is deleted!
      1 Reply Last reply Reply Quote 0
      • cvp
        cvp @rownn last edited by

        @rownn test this

        from objc_util import *
        import ui
        
        tv =ui.TextView()
        
        def x(sender):
        	resp = ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder()
        	tv.name = 'keyboard is visible = ' + str(resp == ObjCInstance(tv))
        
        b = ui.ButtonItem()
        b.title = 'test'
        b.action = x
        tv.right_button_items = (b,)
        tv.present() 
        
        1 Reply Last reply Reply Quote 2
        • cvp
          cvp @rownn last edited by cvp

          @rownn if you have multiple TextFields/ TextViews you could compare the first responder with ObjCInstance(all of them) to determine which one has the keyboard/cursor

          1 Reply Last reply Reply Quote 1
          • stephen
            stephen @rownn last edited by stephen

            @rownn i annotated with comments.

            
            class MyTextView(ui.TextView):
            	def __init__(self, *args, **kwargs):
            		self.delegate = self
            	
            	def begin_editing(self):
            		# forces keyboard to present
            		pass
            
            	def end_editing(self):
            		# forces keyboard to close
            		pass
            
            	def replace_range(self, range, text):
            		pass
            		
            	### start of delegate methods ###
            	
                def TextView_should_begin_editing(self, textview):
                	# resize and reposition for keyboard
                    return True
                    
                def TextView_did_begin_editing(self, textview):
                	# keyboard presented
                    pass
                    
                def TextView_did_end_editing(self, textview):
                    pass
                    
                def TextView_should_return(self, textview):
                    # resize and reposition for no keyboard
                    textfield.end_editing()
                    # keyboard not presented
                    return True
                    
                def TextView_should_change(self, textview, range, replacement):
                    return True
                    
                def TextView_did_change(self, textview):
                    pass
            
            
            1 Reply Last reply Reply Quote 2
            • stephen
              stephen last edited by

              @rownn to follow along @cvp if you have multiple TextViews you can use a separate object class with the methods and set that to the delegate for each and each will get their own so you wouldnt need to find out who is currently active

              
              class MyTextViewDelegate(object):
                  def TextView_should_begin_editing(self, textview):
                  	# resize and reposition for keyboard
                      return True
                      
                  def TextView_did_begin_editing(self, textview):
                  	# keyboard presented
                      pass
                      
                  def TextView_did_end_editing(self, textview):
                      pass
                      
                  def TextView_should_return(self, textview):
                      # resize and reposition for no keyboard
                      textfield.end_editing()
                      # keyboard not presented
                      return True
                      
                  def TextView_should_change(self, textview, range, replacement):
                      return True
                      
                  def TextView_did_change(self, textview):
                      pass
              
              
              1 Reply Last reply Reply Quote 1
              • stephen
                stephen last edited by

                @rownn both methoods should work. but if you want my opinion i would suggest usung @cvp 's objC route. i know mine works but i personally wish i learned objc_util when i was learning python. and this sounds like a perfect time to for yourself if you havnt already. you can even do my method using objc_util. using th UITextView if i recall correctly πŸ€“

                1 Reply Last reply Reply Quote 0
                • JonB
                  JonB last edited by

                  Of course you can always hook into the keyboard frame change notifications by implementing custom view for your root.

                  https://forum.omz-software.com/topic/5189/moving-the-keyboard-input-text-view-to-be-visible/4

                  stephen 1 Reply Last reply Reply Quote 3
                  • stephen
                    stephen @JonB last edited by

                    @JonB i completely forgot about those methods Thank you πŸ˜ŽπŸ˜…

                    1 Reply Last reply Reply Quote 1
                    • rownn
                      rownn last edited by rownn

                      Hi everyone,

                      my first idea was to detect if the TextView is focused or not, but sometimes I work with an external keyboard, so JonBs hint is perfect. It works perfectly fine for me. Hope there wonβ€˜t be any unexpected issues. Here the reduced code:

                      from scene import *
                      import ui
                      
                      class MyScene (Scene):
                      	def setup(self):
                      		v = V(scene=self)
                      		self.view.add_subview(v)
                      		
                      		background = Node(parent=self)
                      		background.position = (self.size.w/2,self.size.h/2)#(self.size.w/2, self.size.h/2)
                      		background.add_child(ShapeNode(ui.Path.rect(0,0,self.size.w,self.size.h), fill_color='#dddddd', stroke_color='clear'))
                      		
                      		self.add_child(background)
                      		
                      class V(ui.View):
                      	def __init__(self, *args, **kwargs):
                      		self.scene = kwargs["scene"]
                      		self.textView_H = 200
                      		self.frame=(0, self.scene.size.h-self.textView_H, self.scene.size.w, self.scene.size.h)
                      		
                      		self.tv=ui.TextView(frame=(10, 0, self.scene.size.w-20, self.textView_H), font=('Courier', 17.0), background_color='#333333', text_color = '#ffffff')
                      		self.tv.text = 'Heyhey.'
                      		self.tv.delegate=self
                      		self.add_subview(self.tv)
                      	
                      	def keyboard_frame_will_change(self, frame):
                      		self.animate(frame)
                      		
                      	def animate(self, frame):
                      		def animation():
                      			self.y = self.scene.size.h-self.textView_H-frame[3]
                      		ui.animate(animation, duration=0.25)
                      	
                      		
                      if __name__ == '__main__':
                      	run(MyScene(), PORTRAIT, show_fps=True)
                      

                      Thank you guys. Amazing fast replying forum!

                      1 Reply Last reply Reply Quote 0
                      • rownn
                        rownn last edited by

                        The animation part of the code seems to be not needed.
                        So...

                        def keyboard_frame_will_change(self, frame):
                        	self.y = self.scene.size.h-self.textView_H-frame[3]
                        	#self.animate(frame)
                        		
                        #def animate(self, frame):
                        	#def animation():
                        	    #self.y = self.scene.size.h-self.textView_H-frame[3]
                        	#ui.animate(animation, duration=0.25)
                        	 ```
                        1 Reply Last reply Reply Quote 0
                        • stephen
                          stephen last edited by

                          @rownn what JonB gave shoudnt give any issues. this is made exactly for what you need. i personally forgot all about theme lol

                          1 Reply Last reply Reply Quote 0
                          • rownn
                            rownn last edited by

                            Great! Thanks:)

                            mikael 1 Reply Last reply Reply Quote 0
                            • mikael
                              mikael @rownn last edited by

                              @rownn, the keyboard reveal delegates used to have serious issues, at least on the iPhone.

                              If you tried to use the exact frame height values they were very confusing, probably not properly handling the safe area. And also the handlers kept running after your script was done.

                              Would be happy to hear if these issues have been resolved in the intervening years.

                              1 Reply Last reply Reply Quote 0
                              • JonB
                                JonB last edited by

                                Yes, also issues with landscape vs portrait vs upside-down, etc.

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post
                                Powered by NodeBB Forums | Contributors