【Swift】UIViewの使い方。部品はみんなこのクラスを継承している。(Swift 2.1、XCode 7.2)
UIViewとは
本記事では、Swiftで使える部品のUIViewについて説明する。
UIView(以下、ビュー)とは、デバイス画面上の描画やイベント受信をつかさどる部品で、デバイス画面に配置するすべての部品はUIViewを継承している。
ビューを使ってみる
ビューをデバイス画面に配置すると表示される透明な枠がビューである。
透明だと見づらいので背景色を変更しておこう。黄緑枠のアトリビュートインスペクタボタンから設定画面を開き、Backgroundを青色に変更する。
これだけだと単純な四角枠で終わってしまうので、簡単な使用例を1つ。
下図のように、ビュー内の左上にラベルを配置する。ラベルが選択された状態で、黄緑枠のアトリビュートインスペクタボタンを押して設定画面を開き、Colorを白に変更する。
続いて、黄枠のPinボタンを押して吹き出しの設定画面を表示し、紫枠のアイコンを押して水平方向と垂直方向の制約を追加する。そして、「Add 2 Constraints」ボタンを押せばビューの中のラベルの制約が追加される。同じ手順で、ビュー内の右下にもう1つのラベルを追加する。
これにより、ビューとラベル2個で1セットととなり、ビューを移動すればラベル2個も一緒に移動する。また、デバイス画面内の位置はビューのみに制約を追加するだけで良くなるなどの利点がある。
ビューの設定項目
次に、ビューの設定項目を確認してみよう。ビューを選択した状態で、下図黄緑枠のアトリビュートインスペクタボタンを押して設定画面を表示する。
Mode
ビューの領域に対して部品をどのように表示するかの設定。以下の13項目から選択する。
■ Scale To Fit
ビューの領域ぴったりに部品を拡大縮小する。縦横比は維持しない。
■ Aspect Fit
ビュー領域の縦横の短い方の長さと部品の長さが一致するまで縦横比を維持しながら部品を拡大縮小する。下図の灰色箇所はビューの領域。
■ Aspect Fill
ビュー領域の縦横の長い方の長さと部品の長さが一致するまで縦横比を維持しながら部品を拡大縮小する。ビュー領域と部品の縦横比が異なる場合、部品はビュー領域からはみ出すことになる。
■ Redraw
拡大縮小の方法はAspect Fillと同じ。ビュー領域の拡大縮小が行われたあとに再描画が行われる。
■ Center
ビュー領域の中央に部品を配置する。
■ Top
ビュー領域内の垂直方向「上端」、水平方向「中央」に配置する。
■ Bottom
ビュー領域内の垂直方向「下端」、水平方向「中央」に配置する。
■ left
ビュー領域内の垂直方向「中央」、水平方向「左端」に配置する。
■ Right
ビュー領域内の垂直方向「中央」、水平方向「右端」に配置する。
■ Top left
ビュー領域内の垂直方向「上端」、水平方向「左端」に配置する。
■ Top Right
ビュー領域内の垂直方向「上端」、水平方向「右端」に配置する。
■ Bottom Left
ビュー領域内の垂直方向「下端」、水平方向「左端」に配置する。
■ Bottom Right
ビュー領域内の垂直方向「下端」、水平方向「右端」に配置する。
Semantic
iOS9から追加。使い方が分かり次第ここに追記する。
Tag
ソースコードから部品にアクセスするための識別番号。使い方のサンプルは次の記事を参照されたし。⇒「記事」
User Interaction Enabled
チェックを入れると、ビューをタップしたときのイベント検知が有効になる。
実際に試してみよう。以降の手順はページ前半の手順の続きである。
下図赤枠のアシスタントエディタボタンを押してViewController.swiftを開く。Ctrlキーを押しながらビューをドラック&ドロップでソースコードまで運んで吹き出しの設定画面を開く。Connectionに「Outlet」、Nameに「testView」を入力してConnectボタンを押す。これでビューをソースコードで操作できるようになった。
ViewController.swiftを以下のように修正する。ビューがタップされたときに呼び出されるメソッドをGestureRecognizerで登録し、呼び出されたメソッドの中でビューの背景色を赤に変更している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testView: UIView! //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() //タップされたときの呼び出すメソッドをビューに登録する。 let myTap:UITapGestureRecognizer = UITapGestureRecognizer(target:self, action:"changeColor" ) testView.addGestureRecognizer(myTap) } func changeColor() { //ビューの背景色を赤に変更する。 testView.backgroundColor = UIColor.redColor() } } |
以下は実際のプレイ動画
Multiple Touch
チェックを入れると、部品に触れた複数の指を検知できるようになる。
ビューに触れた指の数をラベルに表示するコードを作ってみよう。Multiple Touchにチェックを入れたあと、ビューの中のラベルをクリックする。下図赤枠のTagに1を入力する。これで識別番号を使ってソースコードからラベルを操作できるようになった。
View Controller.swiftを以下のように修正する。オーバーライドしているtouchesBeganメソッドはUIViewが継承しているUIResponderクラスのメソッドで、画面に指が触れたときに呼び出される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testView: UIView! //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() } override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { //部品に触れた指の数をラベルに表示する。 let testLabel = testView.viewWithTag(1) as! UILabel testLabel.text = "\(touches.count)本の指" } } |
以下は実際のプレイ動画。ちなみに、シュミレーターで2本の指を表現するにはOptionキーを押しながらクリックする。
Alpha
部品の透過度を0から1の間で設定する。0が完全に透明で見えなくなり、1は透過しない。下図は0.35に設定した結果。
Background
ビューの背景色
Tint
テキストの文字色
Opaque
公式リファレンスを読むと、チェックを入れると描画機能はこのビューは透過されていないと認識し、処理が最適化されてパフォーマンスが向上するといった内容が記載されている。⇒「UIViewリファレンス」
また、ビューの中に透過されているものが混ざっている場合は、このチェックを外した方がが良いいうようなことが記載されているが、チェックを入れたままでも透過されるので、チェックの有無はパフォーマンスのみに影響するようだ。また、システムが提供しているクラス(UIButton, UILabel, UITableViewCellなど)でこのプロパティを設定しても影響しないといったことも書かれている。
何やらこの機能を使うには、UIViewのサブクラスを作りdrawRectメソッドをオーバーライドして独自コンテンツを作る必要があるようなことが書かれているので以下のコードを動かしてみたがOpaqueuのチェック有り無しで特に変わった様子はない。今後何か分かったら追記する。
以下はUIViewクラスのサブクラス。drawRectメソッドをオーバーライドして線を描画する処理を記述した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// // TestDrawRect.swift // import UIKit class TestDrawRect: UIView { override func drawRect(rect: CGRect){ let bezie = UIBezierPath() //図形に黄色い縦線を入れる。 bezie.moveToPoint(CGPointMake(50,0)) bezie.addLineToPoint(CGPointMake(50, 100)) UIColor.yellowColor().setStroke() bezie.lineWidth = 10 bezie.stroke() } } |
以下は上記のサブクラスを画面に表示する処理をViewControllerクラスに記述した結果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() //図形を画面に表示する。 let testDraw = TestDrawRect(frame:CGRectMake(20,20, 100, 100)) self.view.addSubview(testDraw) } } |
Hidden
チェックを入れると、部品が見えない状態から始まる。ソースコードからhiddenプロパティを変更すれば表示、非表示を切り替えれる。
Clears Graphics Context
チェックを入れると、ビュー領域内をクリアしてから描画を開始するようになる。
Clip Subview
チェックを入れると、ビューに追加したサブビューは親ビューの領域内のみに描画される。
試しに、以下のコードのようにビューからはみ出す位置にサブビューを追加して、Clip Subviewのチェック有無で表示の変化を確認してみよう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// // ViewController.swift // import UIKit class ViewController: UIViewController { @IBOutlet weak var testView: UIView! //最初からあるメソッド override func viewDidLoad() { super.viewDidLoad() //ビューからはみ出す位置に赤い正方形を配置する。 let testDraw = UIView(frame:CGRectMake(180,-50, 100, 100)) testDraw.backgroundColor = UIColor.redColor() testView.addSubview(testDraw) } } |
下図はClip Subviewのチェックを外したときの実行結果。サブビューが親ビューの領域をはみ出して表示されている。
下図はチェックをつけたときの実行結果。はみ出した部分が表示されなくなった。
Autoresize Subviews
チェックを入れると、ビューを拡大縮小したときに、サブビューも一緒に拡大縮小される。
Stretching
部品が拡大されるときにどの部分を拡大するのかを指定する。
設定項目はX、Y、Width、Heightの4項目。部品の辺の長さを1.0として0から1.0の間の数値を入力する。下図のように、部品の左上を基準点としたX座標、Y座標から、右にWidth、下にHeightに囲まれた領域が拡大対象になる。
イメージしづらいので例題を解いてみよう。
下図はイメージビューの中に画像を表示した画面である。Modeは「Center」で、灰色部分はイメージビューの領域である。Modeを「Scale To Fill」にすると、
下図のように画像全体が横に引き伸ばされて表示される。これを中央の茶色い線だけ横に伸ばしたい。Stretchingに設定する値を挙げよ。
X座標は0.45、Y座標は0、Widthは0.1、Heightは1.0を設定すると茶色の領域のみ拡大対象になる。