簡要

上次做完上面的封面照片的連動
接下來下面有一個特殊的View
上滑到一定程度後
就會隨著距離
最後變成navigation bar
但我不知道是不是可以這樣
這次我是想用簡單的
使用一個View
配合和監聽scrollViewDidScroll做變化
這裡來看一下原生Uber eat效果

基本設置

tableView設置按照上一篇做設定
[Day 14] Swift TableView 下拉放大頂部圖片 下拉放大封面照 (上)

這裏在tableView新增過後
在加一個topView在上面
以及其他label來顯示一些餐廳資訊

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addSubview(self.tableView)
    self.view.addSubview(self.topView)
}
lazy var topView: UIView = {
    //底部的View
    let topView = UIView()
    topView.frame = CGRect.init(x: 15, y: 100, width: KScreenWidth - 15*2, height: 200)
    topView.backgroundColor = UIColor.white
    //標題
    titleLabel = UILabel()
    titleLabel.frame = CGRect.init(x: 20, y: 25, width: topView.frame.width-20*2, height: 75)
    titleLabel.font = UIFont(name: "Arial", size: 23)
    titleLabel.numberOfLines = 2;
    titleLabel.text = "麥當勞 S161中復興二 McDonald's Fu Sing II, Taichung"
    topView.addSubview(titleLabel)
    //分類
    stateLabel = UILabel()
    stateLabel.frame = CGRect.init(x: 20, y: titleLabel.frame.maxY, width: topView.frame.width-20*2, height: 20)
    stateLabel.font = UIFont(name: "Arial", size: 13)
    stateLabel.text = "美式美食・$"
    topView.addSubview(stateLabel)
    //其他資訊
    otherLabel = UILabel()
    otherLabel.frame = CGRect.init(x: 20, y: stateLabel.frame.maxY+20, width: topView.frame.width-20*2, height: 20)
    otherLabel.textColor = UIColor.darkGray
    otherLabel.font = UIFont(name: "Arial", size: 13)
    otherLabel.text = "5-15分鐘 4.8(500+) 15.00TWD 費用"
    topView.addSubview(otherLabel)

    return topView
}()

scrollViewDidScroll

scrollViewDidScroll 部分要把y跟著滑動距離
就可以使底層View 跟著滑動

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offsetY = scrollView.contentOffset.y
    let radius = -offsetY/200
    if (-offsetY > 200){
        headImageView.transform = CGAffineTransform.init(scaleX: radius, y: radius)
        var frame = headImageView.frame
        frame.origin.y = offsetY
        headImageView.frame = frame
    }

    //本篇新增
    let topViewX:CGFloat = 15*radius
    topView.frame = CGRect.init(x: topViewX, y: 100-200-offsetY, width: KScreenWidth - topViewX*2, height: 200)
}

Demo

但要符合原生APP
還需要三點
– 滑動時 根據滑動距離連動透明度(漸變)
– 標題行數會從2行 變成 1行
– 標題會移動到中間
– 底層View滑動到頂部會有一半會在上面停住

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offsetY = scrollView.contentOffset.y
    let radius = -offsetY/200
    if (-offsetY > 200){
        headImageView.transform = CGAffineTransform.init(scaleX: radius, y: radius)
        var frame = headImageView.frame
        frame.origin.y = offsetY
        headImageView.frame = frame
    }


    let topViewX:CGFloat = 15*radius

    if radius > 0 {
        titleLabel.frame = CGRect.init(x: 20, y: 25 + (105*(1-radius)), width: topView.frame.width-20*2, height: 75)
        stateLabel.frame = CGRect.init(x: 20, y: titleLabel.frame.maxY, width: topView.frame.width-20*2, height: 20)
        otherLabel.frame = CGRect.init(x: 20, y: stateLabel.frame.maxY+20, width: topView.frame.width-20*2, height: 20)

        stateLabel.alpha = radius
        otherLabel.alpha = radius

        topView.frame = CGRect.init(x: topViewX, y: 100-200-offsetY, width: KScreenWidth - topViewX*2, height: 200)
        titleLabel.numberOfLines = 2;
    }else{
        stateLabel.alpha = 0
        otherLabel.alpha = 0
        titleLabel.numberOfLines = 1;
    }
}

這樣根據radius來判斷是否已經超過頂部
並且來控制alpha慢慢變化
到頂部的時候記得把標題numberOfLines改變為1
並且標題的y也要快速移動到定點
就這樣來看看完成品

Demo

Github
https://github.com/Bgihe/TableViewHeaderTest


Categorized in: