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.


    Pythonista View (question)

    Pythonista
    4
    32
    6062
    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.
    • mikael
      mikael @DavinE last edited by

      @DavinE, I assume you are talking about the buttons at the bottom.

      Without any of your code, all I can suggest is using the center property for placement, after making sure that the width has been set. And calculating the position using the bounds of the parent view, not the frame.

      Where are you doing the placement? In layout?

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

        for the better understanding i create a text Page how i place my UI Elements...
        but i need to create for every Device parameters....

        heres my example:

        import ui
        from objc_util import ObjCClass, UIColor, ObjCInstance
        
        view = ui.View(name='Barcode Scanner', bg_color='#3664a8')
        
        
        SCREEN = ui.get_screen_size()
        if min(SCREEN) >= 768:
        	# iPad
        	WIDTH = ''
        	for i in SCREEN:
        		if not WIDTH:
        			WIDTH = i
        		else:
        			HEIGHT = i
        else:
        	# iPhone
        	WIDTH = ''
        	for i in SCREEN:
        		if not WIDTH:
        			WIDTH = i
        		else:
        			HEIGHT = i
        			
        def get_font():
        	return 'Optima'
        
        # Senkrecht
        # Label - Willkommen
        lb1_width = (WIDTH - 50)
        lb1_height = 32
        lb1_y = 0.84
        lb1_font_size = 22
        
        # TextView - Benutzercode angabe
        tv1_width = (WIDTH - 50)
        tv1_height = 60
        tv1_y = 19.09
        tv1_font_size = 18
        
        # SegmentedControl - Scanner|Manuell
        sc1_width = (WIDTH - 50)
        sc1_height = 30
        sc1_y = 30.09
        sc1_font_size = 17
        
        # Label - debugMode
        lb1_1_width = 350
        lb1_1_height = 32
        lb1_1_y = 48.09
        lb1_1_font_size = 16
        
        # Switch - debugMode Aus/Ein
        sw1_width = 51
        sw1_height = 31
        sw1_y = 53.42
        
        # Button - Benutzercode Abfrage Starten
        bt1_width = 300
        bt1_height = 30
        bt1_y = 80.42
        bt1_font_size = 18
        			
        lb1 = ui.Label(name='Label1', bg_color='#3664a8')
        lb1.text_color = 'white'
        lb1.width = lb1_width
        lb1.height = lb1_height
        lb1.alignment = 1
        lb1.text = 'Willkommen auf der Startseite'
        lb1.x = ((WIDTH - lb1.width) / 2)
        lb1.y = ((HEIGHT * lb1_y) / 100)
        lb1.font = (get_font(), lb1_font_size)
        
        tv1 = ui.TextView(name='textview1', bg_color='#3664a8')
        tv1.text_color = 'white'
        tv1.width = tv1_width
        tv1.height = tv1_height
        tv1.alignment = 1
        tv1.text = 'Bitte gib deinen Benutzer Code an.\nAngabe über:'
        tv1.x = ((WIDTH - tv1.width) / 2)
        tv1.y = ((HEIGHT * tv1_y) / 100)
        tv1.font = (get_font(), tv1_font_size)
        tv1.editable = False
        
        sc1 = ui.SegmentedControl(name='Barcode_input', bg_color='#3664a8')
        sc1.corner_radius = 20
        sc1.width = sc1_width
        sc1.height = sc1_height
        sc1.x = ((WIDTH - sc1.width) / 2)
        sc1.y = ((HEIGHT * sc1_y) / 100)
        UIFont = ObjCClass('UIFont').fontWithName_size_(get_font(), sc1_font_size)
        Color = UIColor.orangeColor()
        attributes = {'NSFont': UIFont, 'NSColor': Color}
        setFont = ObjCInstance(sc1).segmentedControl()
        setFont.setTitleTextAttributes_forState_(attributes, 0)
        sc1.segments = ('Scanner', 'Manuell')
        sc1.selected_index = 0
        
        lb1_1 = ui.Label(name='Label1_1', bg_color='#3664a8')
        lb1_1.text_color = 'white'
        lb1_1.width = lb1_1_width
        lb1_1.height = lb1_1_height
        lb1_1.alignment = 1
        lb1_1.text = 'debugMode {AUS / EIN}'
        lb1_1.x = ((WIDTH - lb1_1.width) / 2)
        lb1_1.y = ((HEIGHT * lb1_1_y) / 100)
        lb1_1.font = (get_font(), lb1_1_font_size)
        
        sw1 = ui.Switch(name='debugMode')
        sw1.tint_color = 'white'
        sw1.x = ((WIDTH - sw1_width) / 2)
        sw1.y = ((HEIGHT * sw1_y / 100))
        
        bt1 = ui.Button(name='Button_get_user_id', bg_color='#3664a8')
        bt1.border_color = '#808080'
        bt1.tint_color = 'white'
        bt1.border_width = 5
        bt1.corner_radius = 50
        bt1.width = bt1_width
        bt1.height = bt1_height
        bt1.alignment = 1
        bt1.title = 'Benutzercode Abfrage Starten'
        bt1.x = ((WIDTH - bt1.width) / 2)
        bt1.y = ((HEIGHT * bt1_y / 100))
        bt1.font = (get_font(), bt1_font_size)
        
        
        view.present('fullscreen')
        
        
        view.add_subview(lb1)
        view.add_subview(tv1)
        view.add_subview(sc1)
        view.add_subview(lb1_1)
        view.add_subview(sw1)
        view.add_subview(bt1)
        

        or is there no better way to solve that ?

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

          SCREEN = ui.get_screen_size()
          if min(SCREEN) >= 768:
              # iPad
              WIDTH = ''
              for i in SCREEN:
                  if not WIDTH:
                      WIDTH = i
                  else:
                      HEIGHT = i
          else:
              # iPhone
              WIDTH = ''
              for i in SCREEN:
                  if not WIDTH:
                      WIDTH = i
                  else:
                      HEIGHT = 
          

          Could be written simply as WIDTH, HEIGHT = ui.get_screen_size(). Python let's you split up tuples easily that way

          There are some methods using flex to create one size view that will resize automatically, but it can be hard to get right, plus you still have to manually set font sizes, etc.

          @mikael has some code for writing better constraints, which can make it easier to write views that adapt to screen sizes. His grid view class also makes it easy to build very simple ui's..

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

            i will have a look at this

            ty

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

              @DavinE, the more recent and better version of UI constraints is here.

              But even without going there, as @JonB said, you can get quite a lot done with just a GridView, which is now bundled with uiutils (pip install pythonista-uiutils).

              The following short example demostrates 3 things that may be of interest if you are trying to create flexible UIs targeting both iPads and iPhones, and want your UI to survive someone rotating the device:

              • Define an area to fill a percentage of the screen (plain ui flex).
              • Avoid the controls at the edges of phone displays by using the SafeAreaView.
              • Use GridView to layout views (buttons) automatically.
              import ui
              
              from uiutils.safearea import SafeAreaView
              from uiutils.gridview import GridView
              
              def create_button_slot(title):
                  slot = ui.View(
                      background_color='darkgrey',
                  )
                  btn = ui.Button(
                      title=title,
                      background_color='white',
                      tint_color='black',
                      flex='TWB'
                  )
                  btn.size_to_fit()
                  btn.height = btn.height + 16
                  btn.width = slot.width
                  btn.corner_radius = btn.height/2
                  btn.center = slot.bounds.center()
                  slot.add_subview(btn)
                  return slot
              
              root = SafeAreaView(
                  background_color='lightgrey'
              )
              
              button_area_percentage = 23
                          
              button_area = GridView(
                  pack=GridView.FILL,
                  background_color='grey',
                  frame=(0, 100-button_area_percentage, 100, button_area_percentage),
                  flex='TWH',
              )
              
              root.add_subview(button_area)
              
              for i in range(6):
                  button_area.add_subview(create_button_slot(f'Button {i+1}'))
              
              root.present("fullscreen", animated=False)
              
              DavinE 1 Reply Last reply Reply Quote 0
              • DavinE
                DavinE last edited by

                @mikael thanks for the example

                next week i will try this to get it :D

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

                  @mikael said:

                  @DavinE, the more recent and better version of UI constraints is here.

                  But even without going there, as @JonB said, you can get quite a lot done with just a GridView, which is now bundled with uiutils (pip install pythonista-uiutils).

                  The following short example demostrates 3 things that may be of interest if you are trying to create flexible UIs targeting both iPads and iPhones, and want your UI to survive someone rotating the device:

                  • Define an area to fill a percentage of the screen (plain ui flex).
                  • Avoid the controls at the edges of phone displays by using the SafeAreaView.
                  • Use GridView to layout views (buttons) automatically.
                  import ui
                  
                  from uiutils.safearea import SafeAreaView
                  from uiutils.gridview import GridView
                  
                  def create_button_slot(title):
                      slot = ui.View(
                          background_color='darkgrey',
                      )
                      btn = ui.Button(
                          title=title,
                          background_color='white',
                          tint_color='black',
                          flex='TWB'
                      )
                      btn.size_to_fit()
                      btn.height = btn.height + 16
                      btn.width = slot.width
                      btn.corner_radius = btn.height/2
                      btn.center = slot.bounds.center()
                      slot.add_subview(btn)
                      return slot
                  
                  root = SafeAreaView(
                      background_color='lightgrey'
                  )
                  
                  button_area_percentage = 23
                              
                  button_area = GridView(
                      pack=GridView.FILL,
                      background_color='grey',
                      frame=(0, 100-button_area_percentage, 100, button_area_percentage),
                      flex='TWH',
                  )
                  
                  root.add_subview(button_area)
                  
                  for i in range(6):
                      button_area.add_subview(create_button_slot(f'Button {i+1}'))
                  
                  root.present("fullscreen", animated=False)
                  

                  i have a Problem with the UI constraints..
                  i Installed anchors but i get the message that the Module named 'anchor' is not found...

                  EDIT: i found the solution:

                  observer.py
                  this code is wrong:

                  import anchor.objc_plus as objc_plus
                  

                  this is right:

                  import anchors.objc_plus as objc_plus```
                  mikael 1 Reply Last reply Reply Quote 0
                  • mikael
                    mikael @DavinE last edited by

                    @DavinE, thanks! I pushed an update to PyPI.

                    1 Reply Last reply Reply Quote 0
                    • GxAl2aa
                      GxAl2aa @DavinE last edited by

                      This post is deleted!
                      1 Reply Last reply Reply Quote 0
                      • DavinE
                        DavinE last edited by

                        @mikael no Problem ;)

                        i Have an Question about the UI constraints..

                        When i use Buttons with corner radius = 50 my text is cutted.....
                        i tried to fix this with the Width... but it didn't worked.....

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

                          you could probably change horizontal alignment to center. i think the right way to do it would be to adjust the

                          contentEdgeInsets

                          objc attribute of the underlying uibutton, to allow at least the edge radius amount of inset in left and right sides (or maybe edge radius divided by sqrt(2) on all 4 sides).

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

                            @JonB thanks for the fast reply but i understand nothing.. :(

                            do you have an example for me where i can see what your mean ?

                            an other Thing what i don't understand is when i use for example the dock element top_center at 2 Buttons its overlapping

                            how can i fix this.....

                            thanks for your help!

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

                              @DavinE, can you share a small example of your problem case?

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

                                i think this shows the problem, and a potential solution:

                                import ui
                                from objc_util import *
                                
                                v=ui.View(bg_color='white')
                                
                                b=ui.Button(title='press to resize with insets')
                                
                                b.border_width=1
                                b.corner_radius=50
                                
                                @on_main_thread
                                def a(sender):
                                	sender.objc_instance.button().contentEdgeInsets=(0, 50,0, 50) #t,l,b,r
                                	sender.size_to_fit()
                                
                                b.action=a
                                
                                v.add_subview(b)
                                v.present()
                                
                                

                                The height changes when using this method, so i assume that those edgeinsets are overriding some other sort of anchor or layout constraint that i don't get.

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

                                  @JonB, sorry to be thick, but I still do not understand what the problem is or what the insets are for. In the example above I used corner radius to create buttons with rounded ends, but this must be about something else.

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

                                    @DavinE, if you use dock top_center on two buttons, their top centers will be placed in the same place and they will overlap.

                                    If you want them one above the other, you can still dock both top_center, and then adjust the second view as follows:

                                    at(second).top = at(first).bottom
                                    
                                    DavinE 1 Reply Last reply Reply Quote 0
                                    • DavinE
                                      DavinE last edited by

                                      i'll Show you tomorrow or on the Weekend my Examples for my two Problems

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

                                        @mikael said:

                                        @DavinE, if you use dock top_center on two buttons, their centers will be placed in the same place and they will overlap.

                                        If you want them one above the other, you can dock both top_center, and then adjust the second view as follows:

                                        at(second).top = at(first).bottom
                                        

                                        Yes Thats My issue...
                                        They will overlap....

                                        I will have a Look at this in the Weekend.

                                        Short and stupid Question:
                                        First second are my two Buttons ??

                                        Thanks a looooot for the great help here!!

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

                                          @DavinE said:

                                          First second are my two Buttons ??

                                          Yes, just example names.

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

                                            @JonB said:

                                            i think this shows the problem, and a potential solution:

                                            import ui
                                            from objc_util import *
                                            
                                            v=ui.View(bg_color='white')
                                            
                                            b=ui.Button(title='press to resize with insets')
                                            
                                            b.border_width=1
                                            b.corner_radius=50
                                            
                                            @on_main_thread
                                            def a(sender):
                                            	sender.objc_instance.button().contentEdgeInsets=(0, 50,0, 50) #t,l,b,r
                                            	sender.size_to_fit()
                                            
                                            b.action=a
                                            
                                            v.add_subview(b)
                                            v.present()
                                            
                                            

                                            The height changes when using this method, so i assume that those edgeinsets are overriding some other sort of anchor or layout constraint that i don't get.

                                            thats a good example...
                                            but is it Possible to set the size at begin ?
                                            not over an action....

                                            is this example okay to do this so ?:

                                            import ui
                                            from objc_util import *
                                            
                                            v=ui.View(bg_color='white')
                                            
                                            b=ui.Button(title='press to resize with insets')
                                            
                                            b.border_width=5
                                            b.corner_radius=50
                                            b.objc_instance.button().contentEdgeInsets=(5, 50,5, 50)
                                            b.size_to_fit()
                                            
                                            v.add_subview(b)
                                            v.present()
                                            
                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors