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.


    Real numeric pad on iPad

    Pythonista
    3
    14
    9270
    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.
    • cvp
      cvp @DaveClark last edited by cvp

      @DaveClark change only one line

      	keys = '123x|456|789y| 0.'
      

      If SetTextFieldAsNumeric.py resides in site-packages, you will have to restart Pythonista.

      The decimal point key is appended like the digits but no check is done, for instance if you type 12..34 instead of 12.34

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

        @cvp you might consider creating named "virtual keys" encoded using brackets, instead of using x and y, say [cancel] and [done] or something like that. Or use some sort of Unicode character. I could see people wanting to use this for custom keyboards that include full or abbreviated alphabets. Also, I could agine applications where other custom keys might be desirble, such as arrow keys, "calculator" popups...
        You might have a named custom key dict which lets you define in one place the icon or title, and a function of the to call to do the action.
        Again, this was a great idea and was well executed.

        cvp 2 Replies Last reply Reply Quote 0
        • cvp
          cvp @JonB last edited by cvp

          @JonB I agree with you, we could generalize the function with more parameters but I only have tried something by reading Apple inputview. And I'm not a specialist of args 😢.
          I just want to be sure readers can easily understand my short code and understand how they could add their own keys with their own icons and actions...

          And thousand thanks for your last line, it makes me more happy even than the last match of Belgium (my country) in Russia😂

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

            @cvp Thank you for your help and quick answer on adding the decimal point to your keypad

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

              @JonB like this SetTextFieldPad.py

              import ui
              from objc_util import *
              
              def SetTextFieldPad(tf,pad=None):
              	if not pad:
              		pad = [{'key':'1'},{'key':'2'},{'key':'3'},
              		{'key':'back space','icon':'typb:Delete'},
              		{'key':'new row'},
              		{'key':'4'},{'key':'5'},{'key':'6'},
              		{'key':'delete','icon':'emj:Multiplication_X'},
              		{'key':'new row'},
              		{'key':'7'},{'key':'8'},{'key':'9'},
              		{'key':'done','icon':'emj:Checkmark_3'},
              		{'key':'new row'},
              		{'key':'nul'},{'key':'0'}]
              	tfo = ObjCInstance(tf).textField() # UITextField is subview of ui.TextField
              	
              	def key_pressed(sender):
              
              			tfb = sender.TextField
              			tfobjc = ObjCInstance(tfb).textField()
              			cursor = tfobjc.offsetFromPosition_toPosition_(tfobjc.beginningOfDocument(), tfobjc.selectedTextRange().start())
              			if sender.name == 'delete':
              				if cursor <= (len(tfb.text)-1):
              					tfb.text = tfb.text[:cursor] + tfb.text[cursor+1:]
              			elif sender.name == 'back space':
              				if cursor > 0:
              					#if tfb.text != '':
              					tfb.text = tfb.text[:cursor-1] + tfb.text[cursor:]
              					cursor = cursor - 1
              			elif sender.name == 'done':
              				tfb.end_editing()
              				return
              			else:
              				tfb.text = tfb.text[:cursor] + sender.title + tfb.text[cursor:]
              				cursor = cursor + 1
              				
              			# set cursor
              			cursor_position = tfobjc.positionFromPosition_offset_(tfobjc.beginningOfDocument(), cursor)
              			tfobjc.selectedTextRange = tfobjc.textRangeFromPosition_toPosition_(cursor_position, cursor_position)
              
              	# design your keyboard
              	# pad = [{key='functionnality',title='title',icon='icon'},...]
              	#		new row => new row
              	#		nul => no key
              	#		back space => left delete
              	#		delete => right delete
              	#		done => discard the keyboard
              	#   other => append the character
              	
              	# count the maximum width of rows
              	row_max_length = 0
              	row_length = 0
              	for pad_elem in pad:
              		if pad_elem['key'] == 'new row':
              			if row_length > row_max_length:
              				row_max_length = row_length
              			row_length = 0		
              		else:
              			row_length = row_length + 1
              	if row_length > row_max_length:
              		row_max_length = row_length
              
              	v = ui.View()
              	db = 50
              	dd = 10
              	x0 = (ui.get_screen_size()[0]-row_max_length*db-(row_max_length-1)*dd)/2
              	x = x0
              	y = dd
              
              	for pad_elem in pad:
              		if pad_elem['key'] == 'new row':
              			y = y + db + dd
              			x = x0
              		elif pad_elem['key'] == 'nul':			
              			x = x + db + dd
              		else:			
              			b = ui.Button()
              			b.name = pad_elem['key']
              			b.background_color = 'white'	# or any other color
              			b.tint_color = 'black'
              			b.corner_radius = 10 
              			b.title = ''
              			b.font = ('<system>',32)
              			if 'icon' in pad_elem:
              				b.image = ui.Image.named(pad_elem['icon']).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)
              			elif 'title' not in pad_elem:
              				b.title = pad_elem['key']
              			if 'title' in pad_elem:
              				b.title = pad_elem['title']
              
              			b.frame = (x,y,db,db)
              			b.TextField = tf # store tf as key attribute  needed when pressed
              			if 'action' in pad_elem:
              				b.action = pad_elem['action']
              			else:
              				b.action = key_pressed
              			v.add_subview(b)
              			x = x + db + dd
              	y = y + db + dd
              
              	v.width = ui.get_screen_size()[0]
              	v.height = y
              
              	# view of keyboard
              	retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view
              	tfo.setInputView_(ObjCInstance(v))
              	
              	# color of cursor and selected text
              	tfo.tintColor = UIColor.redColor().colorWithAlphaComponent(0.5)
              
              	# comment both lines to keep undo/redo/paste BarButtons above keyboard
              	tfo.inputAssistantItem().setLeadingBarButtonGroups(None)
              	tfo.inputAssistantItem().setTrailingBarButtonGroups(None)
              

              And

              import ui
              from SetTextFieldPad import SetTextFieldPad
              
              def my_action(sender):
              	sender.TextField.name = 'my_action called'
              	sender.TextField.text = 'auto_filled by my_action'
               
              tf = ui.TextField()
              #pad = [{'key':'','title'=:'','icon':''}]
              pad = [{'key':'1'},{'key':'2'},{'key':'3'},
              		{'key':'back space','icon':'typb:Delete'},
              		{'key':'new row'},
              		{'key':'4'},{'key':'5'},{'key':'6'},
              		{'key':'delete','icon':'emj:Multiplication_X'},
              		{'key':'new row'},
              		{'key':'7'},{'key':'8'},{'key':'9'},
              		{'key':'ole','action':my_action,'icon':'typb:User'},
              		{'key':'done','icon':'emj:Checkmark_3'},
              		{'key':'new row'},
              		{'key':'nul'},{'key':'0'}]
              SetTextFieldPad(tf,pad=pad)
              tf.text = ''
              tf.width = 400
              tf.present('sheet')
              tf.begin_editing()
              tf.wait_modal()
              

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

                exactly, nice

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

                  @JonB Thanks. Did you see I ‘ve added the functionality “delete at (right of) cursor”.

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

                    I have something that works on a iPad, but I would like to incorporate the new number pad in the program. This is where I’m at

                    import ui
                     
                    def getInput(view):
                        textfield = v[view]
                        input = textfield.text
                        return input
                          
                    def calculate(top, bottom): 
                        result = repr(round(1/(1/top + 1/bottom))) + ' pounds per inch'	  
                        return result
                        
                    def button_tapped(sender):
                        top = float(getInput('textfield1'))
                        bottom = float(getInput('textfield2'))
                        v['textfield3'].text = calculate(top, bottom) 
                            
                    v = ui.load_view('uitest')
                    
                    v['textfield1'].keyboard_type = ui.KEYBOARD_DECIMAL_PAD   
                    v['textfield2'].keyboard_type = ui.KEYBOARD_DECIMAL_PAD  
                     
                    button1 = v['button1']
                    button1.action = button_tapped
                    v.present('sheet')
                    

                    How would I make your keypad be the default keypad.

                    Any help would be very much appreciated

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

                      @DaveClark Sorry for the delay but I'm in holidays far from my home.
                      Try

                      import ui
                      from SetTextFieldPad import SetTextFieldPad
                      
                      
                      import ui
                       
                      def getInput(view):
                          textfield = v[view]
                          input = textfield.text
                          return input
                            
                      def calculate(top, bottom): 
                          result = repr(round(1/(1/top + 1/bottom))) + ' pounds per inch'   
                          return result
                          
                      def button_tapped(sender):
                          top = float(getInput('textfield1'))
                          bottom = float(getInput('textfield2'))
                          v['textfield3'].text = calculate(top, bottom) 
                              
                      v = ui.load_view('uitest')
                      
                      #v['textfield1'].keyboard_type = ui.KEYBOARD_DECIMAL_PAD   
                      #v['textfield2'].keyboard_type = ui.KEYBOARD_DECIMAL_PAD  
                      
                      SetTextFieldPad(v['textfield1'])
                      SetTextFieldPad(v['textfield2'])
                       
                      button1 = v['button1']
                      button1.action = button_tapped
                      v.present('sheet')```
                      DaveClark 1 Reply Last reply Reply Quote 0
                      • DaveClark
                        DaveClark @cvp last edited by DaveClark

                        @cvp Oh my God. That’s it, You should see the mess I have got going in trying to incorporate your keypad. I guess I don’t get it yet, but I’m trying.

                        Thank you so much for your help, and thank you for taking the time to help. I really enjoy the little programming projects I have and I am getting there

                        Thanks again

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

                          Added to my SetTextFieldPad support of SFSymbols as icon on keyboard key

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