[Autolayout] サンプルケース - 親ビューの下半分に子ビューを配置 (2) アニメーション

2015年6月12日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

前回のやつにアニメーションを加えてみる。子ビューが下からシュッと出てくるやつ。

これは制約を使えば簡単。子ビューの上のラインを画面下端から、最終位置(この場合親ビューのCenterY)まで引き上げてやれば良い。
まず子ビューの初期位置を最終下端で作る。
let v1c = NSLayoutConstraint(item: tableView, attribute: .Top, relatedBy: .Equal,
     toItem: parentView, attribute: .CenterY, multiplier: 1.0, constant: parentView.frame.size.height)

一旦 parentView.layoutIfNeeded()で初期描画させた後、アニメーションのコードを走らせる。
v1c.constant = 0.0
        UIView.animateWithDuration(0.5) {
            parentView.layoutIfNeeded()
        }

こうすると子ビューの上の制約の値(constraint)が下端(parentView.frame.size.height)から 0.0へアニメーションしながら変化する。

なおこのままだと制約のワーニングが出る。
2015-06-11 08:10:18.938 LKMenu_Example[89282:6908924] Unable to simultaneously satisfy constraints.
 Probably at least one of the constraints in the following list is one you don't want.
 Try this: (1) look at each constraint and try to figure out which you don't expect; 
(2) find the code that added the unwanted constraint or constraints and fix it.
 (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer
 to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "",
    "",
    ""
)
  :

これは子ビューの上の制約(v1c)と下の制約(v2c)の値が初期状態では等しくなる(逆転する?)ため。こんな時は優先順位(priority)をつけてやればいい。
let v2c = NSLayoutConstraint(item: tableView, attribute: .Bottom, relatedBy: .Equal,
      toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
        v2c.priority = 750   // 追加
        parentView.addConstraint(v2c)
親ビューに制約を追加する前につけるのを忘れずに。これでワーニングが消える。priorityは大きい方が優先順位が高い。IBでプロパティ欄を見ると 1000(Required), 750(High), 250(Low)となっている。
デフォルト値は 1000(最大値も 1000)。


最終的なコード。
parentView.addSubview(tableView)

        tableView.setTranslatesAutoresizingMaskIntoConstraints(false)
        
        let h1c = NSLayoutConstraint(item: tableView, attribute: .Left, relatedBy: .Equal,
            toItem: parentView, attribute: .Left, multiplier: 1.0, constant: 0.0)
        parentView.addConstraint(h1c)
        let h2c = NSLayoutConstraint(item: tableView, attribute: .Right, relatedBy: .Equal,
            toItem: parentView, attribute: .Right, multiplier: 1.0, constant: 0.0)
        parentView.addConstraint(h2c)
        
        let v1c = NSLayoutConstraint(item: tableView, attribute: .Top, relatedBy: .Equal,
            toItem: parentView, attribute: .CenterY, multiplier: 1.0, constant: parentView.frame.size.height)
        parentView.addConstraint(v1c)
        let v2c = NSLayoutConstraint(item: tableView, attribute: .Bottom, relatedBy: .Equal,
            toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
        v2c.priority = 750
        parentView.addConstraint(v2c)
        parentView.layoutIfNeeded()
        
        v1c.constant = 0.0
        UIView.animateWithDuration(0.5) {
            parentView.layoutIfNeeded()
        }

Autolayoutはコツがわかってくると楽しい。


(おまけ)animateWithDuration:usingSpringWithDamping: を使えばアニメーションにバネ効果(バウンス効果っぽい)をつけられる。
UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 0.7,
            initialSpringVelocity: 0.0, options: UIViewAnimationOptions.CurveEaseInOut,
            animations: { () -> Void in
            parentView.layoutIfNeeded()
        }) { (Bool) -> Void in
        }

[Autolayout] サンプルケース - 親ビューの下半分に子ビューを配置

2015年6月11日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

メニュー作成中。Autolayoutでこんな感じのビュー配置をしたい。
ランドスケープで。

親ビューが parentView、子ビューが tableViewとするとこんな感じ。
        parentView.addSubview(tableView)

        tableView.setTranslatesAutoresizingMaskIntoConstraints(false)
        
        let h1c = NSLayoutConstraint(item: tableView, attribute: .Left, relatedBy: .Equal, toItem: parentView, attribute: .Left, multiplier: 1.0, constant: 0.0)
        parentView.addConstraint(h1c)
        let h2c = NSLayoutConstraint(item: tableView, attribute: .Right, relatedBy: .Equal, toItem: parentView, attribute: .Right, multiplier: 1.0, constant: 0.0)
        parentView.addConstraint(h2c)
        
        let v1c = NSLayoutConstraint(item: tableView, attribute: .Top, relatedBy: .Equal, toItem: parentView, attribute: .CenterY, multiplier: 1.0, constant: 0.0)
        parentView.addConstraint(v1c)
        let v2c = NSLayoutConstraint(item: tableView, attribute: .Bottom, relatedBy: .Equal, toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
        parentView.addConstraint(v2c)

        parentView.layoutIfNeeded()

ポイントは v1c のところで、親のCenterYに 子ビューのTOPを紐付けているところ。ここの constantを変更すれば高さを調整することもできる。


[CocoaPods] use_frameworks! で作ったライブラリのバンドル

2015年6月1日月曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

CocoaPodsで自作ライブラリを作っているケースで、swift対応のためにフレームワーク化(use_framework!)するとバンドルはその中に入ってしまう。

Example.app
 ├── LKPostingQueueManager.framework
 │   ├── Info.plist
 │   ├── LKPostingQueueManager
 │   └── Resources.bundle ←ここにくる(以前はもっと上の階層)


プログラムでこれを参照するにはメインバンドル配下では見つからない。
let path = NSBundle.mainBundle().pathForResource("Resource", ofType: "bundle")! → ここで nilでクラッシュ
let bundle = NSBundle(path: path)

最初にフレームワークのバンドル(クラスが含まれるバンドル)を取って、そこから引き出すのがポイント。
let frameworkBundle = NSBundle(forClass: LKPostingQueueManager.self)
let path = frameworkBundle.pathForResource("Resources", ofType: "bundle")!
let bundle = NSBundle(path: path)


関連

Resource Bundle の作り方と CocoaPodsでの配布
※上記はフレームワーク化する前の話。フレークワーク化するとこんな面倒は入らず設定だけで済む。
s.resource_bundles = { 
    'Resources' => ['Pod/Assets/*']
  }
みたいな。

人気の投稿(過去 30日間)