I couldn't fully understand the behavior of pythonista3, so I tried various flex attributes of ui.View to deepen my understanding.
Dragging the four corners of the screen changes the size, so you can visually check the changes in each movement.
ui_flex01.py
import ui
class ResizableView(ui.View):
	
	STA_IDLE = 1  #Wait
	STA_MOVE_LT = 2  #Move to the upper left
	STA_MOVE_LB = 3  #Move to the lower left
	STA_MOVE_RT = 4  #Move to the upper right
	STA_MOVE_RB = 5
	STA_MOVE = 6
	
	
	def __init__(self):
		self.m_state = self.STA_IDLE
		
	def touch_began(self, touch):
		l = self.width * 0.1
		r = self.width * 0.9
		t = self.height * 0.1
		b = self.height * 0.9
		
		self.m_state = self.STA_IDLE
		
		if touch.location.x < l:
			if touch.location.y < t:
				self.m_state = self.STA_MOVE_LT
			if touch.location.y >= b:
				self.m_state = self.STA_MOVE_LB
		if touch.location.x >= r:
			if touch.location.y < t:
				self.m_state = self.STA_MOVE_RT
			if touch.location.y >= b:
				self.m_state = self.STA_MOVE_RB
		
		if self.m_state == self.STA_IDLE:
			self.m_state = self.STA_MOVE
		
		
	def touch_moved(self, touch):
		s = self.m_state
		vx = touch.location.x - touch.prev_location.x
		vy = touch.location.y - touch.prev_location.y
		
		if s == self.STA_IDLE:
			pass
		elif s == self.STA_MOVE_LT:
			self.x += vx
			self.y += vy
			self.width -= vx
			self.height -= vy
		elif s == self.STA_MOVE_RT:
			self.width += vx
			self.y += vy
			self.height -= vy
		elif s == self.STA_MOVE_LB:
			self.x += vx
			self.width -= vx
			self.height += vy
		elif s == self.STA_MOVE_RB:
			self.width += vx
			self.height += vy
		elif s == self.STA_MOVE:
			self.x += vx
			self.y += vy
		
	def touch_ended(self, touch):
		self.m_state = self.STA_IDLE
datas = (
	('RB',0,0,30,30),
	('LB',270,0,30,30),
	('RT',0,370,30,30),
	('LT',270,370,30,30),
	('W',50,40,200,50),
	('H',50,100,50,250),
	('R',100,100,100,50),
	('L',100,100,100,50),
	('LR',100,100,100,50),
	('RW',100,160,100,50),
	('LW',100,220,100,50),
	('RTW',110,300,50,50),
	('LTH',200,300,50,50),
	('',150,220,100,50),
	('RW',100,280,30,50),
	('RW',150,280,30,50),
	('RW',200,280,30,50),
	('RLW',100,340,30,50),
	('RLW',150,340,30,50),
	('RLW',200,340,30,50),
)
p = ui.View()
v = ResizableView()
v.width = 300
v.height = 400
v.background_color = '#808080'
p.add_subview(v)
for d in datas:
	l = ui.Label()
	l.border_width = 2
	l.alignment = ui.ALIGN_CENTER
	l.text = l.flex = d[0]
	l.frame = (d[1],d[2],d[3],d[4])
	v.add_subview(l)
p.present('fullscreen')
v.width = p.width
v.height = p.height
 
You can set flex to automatically change your position (x, y) and width (width, height) as the parent View resizes.
The characters R, B, L, T, W, and H can be specified, and multiple combinations can be specified.
If you specify an empty string for flex, x, y, width, and height are not affected by resizing the parent View. This is the same behavior as when ‘R’ or ‘RB’ is specified.
Specifying ‘L’ for flex gives a flexible left margine. Translated literally, the left margin changes flexibly. If you translate it freely, it will stick to the right edge of the parent View.
This means that this View will remain to the right when the size of the parent View changes.
Like ‘L’
‘R’ is attached to the left edge of the parent View ‘B’ is attached to the top of the parent View. (Default behavior) ‘T’ sticks to the bottom edge of the parent View
It will be.
Personally, the meaning of LRBT is the exact opposite, but am I the only one who thinks so?
If you specify ‘W’, the width will change according to the size change of the parent. If you specify ‘H’, the height will change according to the size change of the parent.
I want to arrange multiple buttons at equal intervals even if the size of the parent changes. I will use it at that time. In most cases, it is necessary to change the size as well, so I think that ‘RLW’ and ‘BTH’ are often used in addition to WH.