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.


    Moving the keyboard input text view to be visible?

    Pythonista
    input textfield keyboard
    3
    7
    6176
    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.
    • shinyformica
      shinyformica last edited by

      Is there any way to force whatever text view is currently receiving keyboard input into view, if it is covered up by the keyboard? So, for example, there's a text input field at the bottom of a form, user taps in it to begin entering information, but the keyboard pops up and covers the text field, so they can type, but can't see what they're typing.

      In many iOS apps, the view slides up to make sure the input field is visible...is that kind of thing possible in Pythonista? Perhaps someone has a clever way to display a proxy text view to get the input and then send the value to the view which was tapped?

      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp @shinyformica last edited by

        @shinyformica Quick and dirty code of "put your textview in a scroll_view"

        import ui
        
        class my_View(ui.View):
        		def __init__(self):
        			self.frame = (0,0,400,600)
        			sv = ui.ScrollView(name='sv')
        			sv.border_width = 1
        			sv.frame = (10,10,self.width-20,self.height-20)
        			self.original_height = sv.height
        			self.add_subview(sv)
        			tv = ui.TextView()
        			tv.frame = (0,0,sv.width,sv.height)
        			tv.text = ''
        			for i in range(0,50):
        				tv.text = tv.text + str(i) + '\n'
        			sv.add_subview(tv)
        			tv.delegate = self
        		def textview_did_begin_editing(self, textview):
        			self['sv'].height = self.original_height-120
        		def textview_did_end_editing(self, textview):
        			self['sv'].height = self.original_height			
        			
        v = my_View()
        v.present('sheet')
        
        1 Reply Last reply Reply Quote 0
        • shinyformica
          shinyformica last edited by

          Yeah, I thought about putting the whole thing inside a scrollview which only is there for this purpose...I just might do that.

          Trouble is, I'm not actually in control, necessarily, of the location/contents of widgets in the view that the user might tap on to enter text. Those views will be constructed by other people, and displayed in this main view...so when the keyboard pops up it could be that the text box would have to be placed in a scrollview dynamically, or hard to scroll to for other reasons. I'll think on it, but thanks for the sample code!

          I should actually just resize the whole main view when the keyboard shows up...but I don't yet have a global way to access and connect to the keyboard notifications:

          UIKeyboardWillShowNotification
          UIKeyboardDidShowNotification
          UIKeyboardWillHideNotification
          UIKeyboardDidHideNotification
          UIKeyboardWillChangeFrameNotification
          UIKeyboardDidChangeFrameNotification

          I got pointed to good info on that front by you and @JonB, just haven't had a chance to actually try and build something that hooks into the notification center.

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

            Custom Views have the following:

             def keyboard_frame_will_change(self, frame):
                    # Called when the on-screen keyboard appears/disappears
                    # Note: The frame is in screen coordinates.
                    pass
            
                def keyboard_frame_did_change(self, frame):
                    # Called when the on-screen keyboard appears/disappears
                    # Note: The frame is in screen coordinates.
                    pass
            

            You then have to search through the view heirarchy for textfield or textview that are editing... which is easiest done by using the textfield delegates and setting an attribute. or, you can check whether the objc_instance is first responder, i think.

            then you determine the location of the textfield, and set the scrollview content_inset to the y location of the textfield.

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp @shinyformica last edited by cvp

              @shinyformica As you can test with this little script, the keyboard_frame_will/did_change is only called when the keyboard is displayed or dismissed. Thus, if you change of field while the keyboard is already displayed, these functions will not been called and you will not see which field has really the focus.

              import ui
              from objc_util import *
              
              class my_View(ui.View):
              	def __init__(self):
              		self.frame = (0,0,400,600)
              		tv1 = ui.TextView(name='tv1')
              		tv1.frame = (10,10,180,300)
              		tv1.text = ''
              		for i in range(0,50):
              			tv1.text = tv1.text + str(i) + '\n'
              		self.add_subview(tv1)
              		tv2 = ui.TextView(name='tv2')
              		tv2.frame = (210,10,180,300)
              		tv2.text = ''
              		for i in range(0,50):
              			tv2.text = tv2.text + str(i) + '\n'
              		self.add_subview(tv2)
              		
              	def search_editing(self):
              		for subv in self.subviews:
              			if type(subv) is ui.TextView:
              				subvo = ObjCInstance(subv)
              				#print(dir(subvo))
              				#return
              				if subvo.isFirstResponder():
              					print(subv.name)
              			
              	def keyboard_frame_will_change(self, frame):
              		# Called when the on-screen keyboard appears/disappears
              		# Note: The frame is in screen coordinates.
              		print('keyboard_frame_will_change',frame)
              		self.search_editing()
              
              	def keyboard_frame_did_change(self, frame):
              		# Called when the on-screen keyboard appears/disappears
              		# Note: The frame is in screen coordinates.
              		self.search_editing()
              		pass
              		print('keyboard_frame_did_change',frame)
              		
              			
              v = my_View()
              v.present('sheet')
              
              1 Reply Last reply Reply Quote 0
              • shinyformica
                shinyformica last edited by

                Once again, had I just looked at the docs more closely, I would have seen those custom View methods are available...that will definitely do what I need @cvp, so thanks!

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

                  Good point about this only getting called when keyboard is first shown. Ideally, you would attach textfield did_begin_editing delegates that scroll the textfield to the top of the scroll view. Even if you don't own those, you could basically store the original delegate within your custom delegate, and then call the original delegate methods after you scroll into place.

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