Need UI layout help
I’m trying to create a simple UI in Pythonista for my iPhone 6.
I’d like to have a single line text box and a button at the top of the screen. The button should be at the upper right and be sized to fit the button’s name text.
The text box should be the same height as the button and be located to the left of the button and fill the remaining width. I will then fill the remainder of the screen with a SceneView (not yet added).
The idea is that you can type some text into the text field and then click the button to apply the text to the scene. I would rather not use a layout file and keep it all in a single script file so I’m trying to do it from code.
I’ve experimented with this using the UI module docs but can’t get it quite working.
Here’s what I have. Any suggestions on how to get this to do what I want?
view = ui.View()
view.name = 'test UI'
view.background_color = 'black'
r = ui.Button(title='Add Item')
r.background_color = 'orange'
r.flex = 'BL'
s = ui.TextField()
s.flex = 'BR'
@nerdtron, I think the below gives you what you want. I didn't try and get your flex values correct. If you look in the ui.designer, this will help get the settings correct. But you still need to size and position your ui objects for flex to work. Hope it helps.
Also the + 2 and +4 etc in the code is for some margins between the view frame and the ui objects.
import ui view = ui.View() view.name = 'test UI' view.background_color = 'black' r = ui.Button(title='Add Item', bg_color='orange', width=100, height=100, corner_radius=6) r.size_to_fit() # resizes the button, but a little tight r.width += 4 # add a few extra pixels # using get_window_size(), could use ui.get_screen_size() # get_window_size should work on split screens also r.x = ui.get_window_size() - r.width - 2 # returns a tuple (w,h) r.y = 2 #r.background_color = 'orange' #r.flex = 'BL' view.add_subview(r) s = ui.TextField(width=r.frame.min_x - 4, height=r.height) s.x = 2 s.y = 2 #s.flex = 'BR' view.add_subview(s) s.begin_editing() # This gets the text field ready for input. # You can comment this out, if you dont want # it to behave like this view.present('fullscreen')
@Phuket2 thank you very much for the reply and help! Been tied up with other stuff and so have been delayed in getting back to this. I gave that a try and it looked great! I'm curious, though, any thoughts on how to set it up so that when you rotate the device its still correct? I see you're not using flex and from the docs it seems that this is how dynamic layout is normally done. Maybe its a matter of just re-computing using your code when the orientation changes?
@nerdtron , no problems. I think for this example that flex would be the best and easiest. However, when I tried doing it, I had a brain freeze! Its been a long time since I have done it. Pls dont take that as it is hard to do. Once you have it in your head, normally its simple.
I am sure someone else here will chime in with the correct way to set the flex settings.
The example I have put below is still a good a good way to know. Its using a custom view. One of the callbacks you get when you have a Custom View Class is layout. Its called by the ui automatically (if you have a method called layout) when you need to respond to changes in your views height or width. Its worth having a read through the docs about Custom Views.
They are easy to make and give you a lot more flexibility and some extra functionality.
Anyway, I hope this also helps
import ui class MyClass(ui.View): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # create the field and button self.in_fld = ui.TextField() self.post_btn = ui.Button(title='Add Item', bg_color='orange', corner_radius=6, action=self.btn_action, ) # do some static adjustments to button and field properites # properties that we dont need to calculate in layout self.post_btn.size_to_fit() self.post_btn.width += 4 self.post_btn.y = 2 self.in_fld.x = 2 self.in_fld.y = 2 self.in_fld.height = self.post_btn.height self.add_subview(self.in_fld) self.add_subview(self.post_btn) def btn_action(self, sender): # just to show its working append '@' to the in_fld text self.in_fld.text += '@' def layout(self): ''' This method is called by the ui automatically when required, such as orientation change. ''' # only need to adjust the width of the fld and the x pos # of the btn for this case self.in_fld.width = self.width - self.post_btn.width - 6 self.post_btn.x = self.in_fld.frame.max_x + 2 if __name__ == '__main__': mc = MyClass() mc.present() ''' This would also work as expected if __name__ == '__main__': f=(0, 0, 320, 480) mc = MyClass(frame=f) mc.present('sheet') '''