【Swift】boundsとframeの違いと使い分け!Viewの座標と領域を取得

この記事からわかること

  • SwiftUIViewboundsframe違いとは?
  • 座標領域取得する方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

UIViewのboundsとframeについて

SwiftでViewの座標や領域(横幅や縦幅)を取得できるプロパティboundsframeの2つ用意されています。両者ともUIViewクラスのプロパティとして定義されており、CGRect型で値を取得することが可能です。

var frame: CGRect { get set }
var bounds: CGRect { get set }

CGRect型は長方形(Rectangle)のサイズや座標を定義するための構造体です。CGRect型のプロパティからViewのX座標やY座標、横幅(width)、縦幅(height)などそれぞれの取得することができます。

CGRect(x: 100, y: 100, width: 200, height: 150)

iOSデバイスは以下画像のように左上を(x:0,y:0)としたX軸/Y軸として管理されています。

iOSデバイス画面の座標の見方とX軸Y軸の方向

frameプロパティ

公式リファレンス:frameプロパティ

var frame: CGRect { get set }

frame親ビュー(superview)の座標系における対象ビュー(subview)の位置とサイズを表すプロパティです。基準となるのは親ビューなのでX/Y座標に格納される値は対象のViewの左隅上が親ビューのX/Y座標のどこにあるかを示します。self.viewを親Viewとする場合、以下のように指定すると親View(self.view)は画面いっぱいに広がっているので(x:100,y:100)の位置に対象View(area)の左隅上が来るように配置されます。

let area = UIView()
area.frame = CGRect(x: 100, y: 100, width: 200, height: 150)
area.backgroundColor = .gray
self.view.addSubview(area)
【Swift/UIKit】UIViewControllerの役割とは?ビュー階層とviewDidLoadメソッド

さらにsubviewを追加した場合

親Viewの座標なので親Viewをareaとしてさらにsubviewを追加する場合は親View(area)の左隅上を(x:0,y:0)として対象ビュー(label)が配置されます。

let label = UILabel()
label.frame = CGRect(x: 10, y: 10, width: 180, height: 130)
label.text = "HELLO"
label.backgroundColor = .orange
area.addSubview(label)
【Swift】boundsとframeの違いと使い分け!Viewの座標と領域を取得

値を取得する

そのため取得できる値も親Viewを起点とした時の座標になります。

print("area.frame:\(area.frame)")
print("label.frame:\(label.frame)")

// area.frame:(100.0, 100.0, 200.0, 150.0)
// label.frame:(10.0, 10.0, 180.0, 130.0)

変更時にdraw(_:)は呼ばれない

frameに変更を加えた際はdraw(_:)メソッド(描画処理)は呼ばれずに自動更新されるようです。変更時にdraw(_:)メソッドを呼ばれるようにしたい場合はcontentModeプロパティにredrawを指定します。

area.contentMode = .redraw

アニメーション対応

frameはアニメーション対応しているプロパティなので値が変更された時に変化を滑らかに実行することが可能です。

UIView.animate(withDuration: 1.0) {
    // 1秒後に値を変更する
    area.frame = CGRect(x: 50, y: 50, width: 200, height: 150)
}

frameプロパティ〜まとめ〜

boundsプロパティ

公式リファレンス:boundsプロパティ

bounds自身の座標系における対象ビュー(subview)の位置とサイズを表すプロパティです。基準となるのは自分自身なのでX/Y座標に格納される値(x:0,y:0)になりますが、サイズはframeプロパティで指定されている値と同じになります。

そのためboundsプロパティにCGRect型で値を指定しても変更されるのはサイズのみになります。

let area = UIView()
area.frame = CGRect(x: 100, y: 100, width: 200, height: 150)
area.bounds = CGRect(x: 0, y: 0, width: 300, height: 150)
area.backgroundColor = .gray
self.view.addSubview(area)

値を取得する

またboundsプロパティの値を更新してもframeプロパティの値も更新されます。

print("area.frame:\(area.frame)")
print("area.bounds:\(area.bounds)")

// area.frame:(50.0, 100.0, 300.0, 150.0)
// area.bounds:(0.0, 0.0, 300.0, 150.0)

変更時にdraw(_:)は呼ばれない

boundsframe同様に変更を加えた際はdraw(_:)メソッド(描画処理)は呼ばれずに自動更新されるようです。変更時にdraw(_:)メソッドを呼ばれるようにしたい場合はcontentModeプロパティにredrawを指定します。

area.contentMode = .redraw

アニメーション対応

boundsもアニメーション対応しているプロパティなので値が変更された時に変化を滑らかに実行することが可能です。

UIView.animate(withDuration: 1.0) {
    // 1秒後に値を変更する
    area.bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
}

boundsプロパティ〜まとめ〜

frameとboundsの違い

frame

bounds

Viewを変更(拡大/縮小)してもサイズは取得できる値は変わらない

Viewをスケーリング(拡大/縮小)した場合にframeboundsプロパティに違いが現れます。frameプロパティの値は2倍されたViewの座標とサイズになりますが、boundsプロパティは元のサイズのままです。

let area = UIView()
area.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
area.backgroundColor = .gray
self.view.addSubview(area)
// 2倍にスケーリング
area.transform = CGAffineTransform(scaleX: 2, y: 2)

print("area.frame:\(area.frame)")
print("area.bounds:\(area.bounds)")

// area.frame:(50.0, 50.0, 200.0, 200.0)
// area.bounds:(0.0, 0.0, 100.0, 100.0)

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index