pythonista3 の ui モジュールを色々いじる

iOSのPythonista3についてくるuiモジュールの挙動を理解するために試したことを逐次書いていく。

#最初に

##Pythonista3 とは？
iOS 上で動く Python 実行環境 & エディタ & インタプリンタです。補間機能や変数の内容を確認できる Console など、痒いところに手が届く優れものです。

##ui モジュール とは？
Pythonistaに標準で入ってるモジュールです。
多機能ではありませんが、必要最低限のものが入っています。

UIデザイナというGUIツールがありますが、スクリプトのみで色々いじってみたいと思います。

#一番シンプルなui描画

何も画面にでませんが立派(?)な UI プログラムです

```python:ui01.py
import ui

v = ui.View()
v.present('panel')
```

実行しても画面には何もでません。

<img width="300" alt="740B9E3B-FFB2-4CB4-AC1F-880BDA972034.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/c9a63131-dc47-5921-ee3e-dd831656eec3.png">

#Hello Worldを表示

何もでてないと寂しいので hello World と表示させてみます。

```python:ui02.py

import ui

#Hello World
v = ui.View()

l = ui.Label()
l.text = 'Hello World'
v.add_subview(l)

v.present('panel')
```

<img width="300" alt="845D2E9F-1AA4-4BD6-B9E3-702BFE20801E.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/1f61dbf7-3586-8172-7b3d-e83263bba6dc.png">

#子供Viewがどのような大きさなんだろう

枠線をつけてわかりやすくしてみる。

```python:ui03.py
import ui

#Hello World
v = ui.View()

l = ui.Label()
l.text = 'Hello World'
l.border_width = 2
v.add_subview(l)

v.present('panel')
```
まさか正方形とは思っていませんでした。
<img width="300" alt="A65C5AB4-02C5-41EF-A23B-8C9707F0F8CD.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/1aa229a2-9fa2-2615-e9af-52ffcb8df75f.png">

#二つ子供を追加してみる

そのままだと重なって表示されてしまったので、二つ目は座標を指定した。

```python:ui04.py
import ui

#Hello World
v = ui.View()

l = ui.Label()
l.text = 'Hello'
l.border_width = 2
v.add_subview(l)

l2 = ui.Label()
l2.text = 'World'
l2.border_width = 2
l2.x = 50
l2.y = 110
v.add_subview(l2)

v.present('panel')
```

<img width="300" alt="26A2154E-E959-4062-BA65-4674D5BDD96A.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/e5445a31-62b4-129e-6a7c-91fef68dc3a0.png">

#全体に広げる
パネル全体に広げてみる。

追記
flex に’WH’を指定するのは全体に広げるという意味では無かった。。。
詳しくは後ほど

```python:ui05.py
import ui

#Hello World
v = ui.View()

l = ui.Label()
l.text = 'Hello World'
l.border_width = 2
l.flex = 'WH'
v.add_subview(l)

v.present('panel')
```

文字が左に寄っているのは Label の alignment を指定していないから。

<img width="300" alt="1A8AD87D-36CF-43C1-BC9E-8FA16EABE05B.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/040b456f-7edd-18fb-f162-b84c887efc25.png">

#スクロールバーを表示

コンテンツ領域 (content_size ) が View の領域より大きくなったらスクロールできるような感じみたい。
flex 使って自動で伸縮するのは View の領域を見ているっぽいので、 contnt_size の指定の仕方は気をつける必要があるかも。

```python:ui06.py
import ui

label_count = 10
label_height = 100

v = ui.ScrollView()
v.content_size = (100, label_count * label_height)

for i in range(label_count):
	l = ui.Label()
	l.text = 'TestLabel:' + str(i)
	l.y = i * label_height
	l.border_width = 2
	l.flex = 'W'
	
	v.add_subview(l)

v.present('panel')
```

<img width="300" alt="20304A95-3A36-43E7-A054-F8E31434537F.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/f7a4718a-bf4b-4a24-8368-f1edef5a1a4a.png">

#カスタムビューを作成する際のイベント調査

再描画のタイミングやイベントが飛んでくる頻度を確認するためのものを作って確認。
present が panel だとタッチイベントがうまく取れない事があったので fullscreen で確認。(左右スワイプで画面切り替えしている影響と思われる)

```python:ui07.py
import ui

class MyView(ui.View):
	def __init__(self):
		l = ui.Label(name='poslabel')
		l.background_color = '#dddddd'
		l.flex = 'W'
		l.height = 50
		self.add_subview(l)
		
		l2 = ui.Label(name='loglabel')
		l2.background_color = '#ddddff'
		l2.flex = 'W'
		l2.number_of_lines = 0
		l2.y = l.height
		l2.height = 600 - l.height
		self.add_subview(l2)
		
		self.m_logs = []
		pass
		
	def log_msg(self, msg):
		self.m_logs.append(msg)
		self['loglabel'].text = "\n".join(self.m_logs[-20:])
		
	def log_touch(self, touch):
		self['poslabel'].text = str(touch.location)
		
	def did_load(self):
		self.log_msg('did_load called.')
		
	def will_close(self):
		self.log_msg('will_close called.')
		
	def draw(self):
		self.log_msg('draw called.')
		
	def layout(self):
		self.log_msg('layout called.')
		
	def touch_began(self, touch):
		self.log_msg('touch_began called.' + str(touch.location))
		self.log_touch(touch)
		
	def touch_moved(self, touch):
		self.log_msg('touch_moved called.' + str(touch.location))
		self.log_touch(touch)
	
	def touch_ended(self, touch):
		self.log_msg('touch_ended called.' + str(touch.location))
		self.log_touch(touch)
		
v = MyView()
v.present('fullscreen')
```

<img width="300" alt="DE1C78A0-0B71-4D75-A460-DAA9B300B693.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/c5ddfa32-6ea2-184a-8d3e-270426a43b5a.png">

#flex に ‘WH’ を指定しても画面全体に広がらない！？

flex を完全に勘違いしていました。
flex は親のサイズが変わった時に自動的に自分のサイズを調整するか？という機能で、’WH’ を指定した時も、親のサイズ変化にあわせて自分のサイズを変えるという意図で、親のサイズに合わせるわけではありませんでした。

ui06.py で画面全体に広がったように見えたのは、デフォルトの大きさが100x100のViewの子供に、大きさ100x100のLabelを追加したので、presentで親のサイズが全画面になると子供も引き伸ばされて大きくなるだけでした。

下記を実行するとよくわかります。
width と height を代入する部分のコメントアウトを無くすと、多分ほとんどの人が期待したであろう挙動になります。

```python:ui08.py
import ui

v = ui.View()
v.border_color = '#ff0000'
v.border_width = 2
v.background_color = '#999999'

v.present('fullscreen')

l = ui.Label()
l.border_width = 2
l.flex = 'WH'
l.text = 'Label'
#l.width = v.width
#l.height = v.height
v.add_subview(l)
```

<img width="300" alt="DC39039F-ADB4-480F-9724-4C78C7869FB8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36064/a755acce-904c-31ae-545e-6f7a643f072c.png">