スクロールに合わせた他のビューに対する操作
今回はAirbnbのお部屋の詳細ページにあるようなスクロールに合わせて画像を隠したり、拡大させたりする画面を作りたいと思います。
完成イメージはこんな感じ。
処理の流れ
- UIViewControllerにUIScrollViewを設置
- 動かすUIImageViewを用意(今回はxibファイルで作った)
-
scrollViewDidScroll
でスクロール量に応じて画像を変化させる
ソースコードはGithubに上げてありますのでそちらも参考にして頂けるとよろしいかと思います。
実装部分(要点だけ)
1. まずは必要なメインのコンテンツをスクロールさせる画面
とスクロールと同期させる画像
のStoryboardやクラスを用意しましょう。
- ContentMainStoryboard.storyboard
- ContentMainViewController.swift
- ContentMediaView.xib
- ContentMediaView.swift
2. 次にContentMediaView.swift
の処理を書いていきます。
ContentMediaView.swift
import UIKit
class ContentMediaView: UIView {
@IBOutlet var contentMedia: UIView!
@IBOutlet weak var mediaImage: UIImageView!
required init(coder aDecoder:NSCoder) {
super.init(coder: aDecoder)!
sharedInit()
}
override init(frame:CGRect) {
super.init(frame:frame)
sharedInit()
}
private func sharedInit() {
NSBundle.mainBundle().loadNibNamed("ContentMediaView", owner: self, options: nil)
addSubview(contentMedia)
}
}
3. ContentMainViewController.swift
の処理
ここでスクロールとの同期処理を書いていきます。
ContentMainViewController.swift
import UIKit
class ContentMainViewController: UIViewController {
@IBOutlet weak var mainScrollView: UIScrollView!
@IBOutlet weak var contentView: UIView!
var contentMediaView:ContentMediaView!
var mediaFrameHight:CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
mediaFrameHight = (view.frame.width * 3) / 4
contentMediaView = ContentMediaView(frame: CGRectMake(0.0,0.0, view.frame.width, mediaFrameHight))
contentMediaView.backgroundColor = UIColor.blackColor()
mainScrollView.delegate = self
view.insertSubview(contentMediaView, belowSubview: mainScrollView)
self.navigationController?.navigationBarHidden = true
}
override func viewDidLayoutSubviews() {
let inset = UIEdgeInsetsMake(mediaFrameHight, 0.0, 0.0, 0.0)
mainScrollView.contentInset = inset
}
}
// MARK: -UIScrollViewDelegate
extension ContentMainViewController:UIScrollViewDelegate {
func scrollViewDidScroll(scrollView: UIScrollView) {
// スクロール量に応じて見出しの画像のフレームを更新
updateMediaFrame()
}
func updateMediaFrame() {
// 見出しメディアのスクロール両
var scroll = mediaFrameHight + mainScrollView.contentOffset.y
if (mainScrollView.contentOffset.y >= -mediaFrameHight) {
scroll = scroll / 2
}
let offsetY = (mainScrollView.contentOffset.y + mainScrollView.contentInset.top) * -1;
if(mainScrollView.contentOffset.y <= -mediaFrameHight) { // 画像ビヨーン
let scale = (1.0 + offsetY / mediaFrameHight);
contentMediaView.transform = CGAffineTransformMakeScale(scale, scale);
contentMediaView.frame.origin.y = 0.0
contentMediaView.mediaImage.alpha = 1
} else {
contentMediaView.mediaImage.alpha = 1 - (offsetY / mediaFrameHight) * -1
contentMediaView.frame.origin.y = -scroll
}
mainScrollView.scrollIndicatorInsets.top = -mainScrollView.contentOffset.y
}
}
こんな感じです。
4. 完成
ここまでで冒頭のようなAirbnb風のUIが出来上がります。
ソースコードはGithubに上げてありますのでご自由にご覧ください。