效果预览:
思路:
一个简单的VC,里面底层是UIScrollView,其上放置一个UIImageView,紧挨着放置UITableView。UIScrollView下滑时在代理方法里面根据offset.y对UIImageView的width与height设置更改。上滑时UIImageView的约束为默认即可。
View层:
import UIKit
import SnapKit
class SlideView: UIView {
public var CELL_ID = "SLIDE_CELL_ID"
public var rootView: UIScrollView!
public var headerImageView: UIImageView!
public var slideTableView: UITableView!
override init(frame: CGRect) {
super.init(frame: frame)
installRootView()
installUIImageView()
installUITableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK:- Widgets block.
private func installRootView(){
rootView = UIScrollView()
rootView.contentSize = CGSize(width: self.frame.size.width, height: (self.frame.size.height * 2))
rootView.isScrollEnabled = true
self.addSubview(rootView)
rootView.snp.makeConstraints{ make in
make.top.equalTo(self.safeAreaInsets.top)
make.width.equalTo(self.snp.width)
make.height.equalTo(self.snp.height)
}
}
private func installUIImageView(){
headerImageView = UIImageView()
headerImageView.image = UIImage(named: "taylor")
headerImageView.contentMode = .scaleAspectFill
self.rootView.addSubview(headerImageView)
headerImageView.snp.makeConstraints{ make in
make.top.equalTo(self.rootView.snp.top)
make.centerX.equalToSuperview()
make.width.equalTo(self.rootView.frame.size.width)
make.height.equalTo(self.rootView.frame.size.width)
}
NSLog("SNAPKIT.")
}
private func installUITableView(){
slideTableView = UITableView(frame: CGRect(x: 0, y: Int(self.headerImageView.frame.height), width: Int(self.frame.size.width), height: Int((self.frame.size.height * 2) - self.headerImageView.frame.height)), style: UITableView.Style.plain)
slideTableView.isScrollEnabled = false
slideTableView.register(UITableViewCell.self, forCellReuseIdentifier: CELL_ID)
self.rootView.addSubview(slideTableView)
slideTableView.snp.makeConstraints{ make in
make.width.equalTo(self.frame.size.width)
make.height.equalTo(1300)
make.top.equalTo(self.headerImageView.snp.bottom)
}
}
}
DataSource:
我们使用内置的UITableViewCell,style为.plain类型。故省略了Cell的子类创建。
import Foundation
import UIKit
class SlideDataSource: NSObject, UITableViewDataSource{
var CELL_ID = "SLIDE_CELL_ID"
var dataArray: Array<String>!
init(dataArray: Array<String>) {
self.dataArray = dataArray
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: CELL_ID, for: indexPath)
cell = UITableViewCell.init(style: UITableViewCell.CellStyle.default, reuseIdentifier: CELL_ID)
cell.textLabel?.text = dataArray[indexPath.row]
return cell
}
}
ViewController:
import UIKit
class SlideViewController: UIViewController, UITableViewDelegate, UIScrollViewDelegate {
var slideView: SlideView!
var slideDataSource: SlideDataSource!
private func initView(){
let data: Array<String> = ["Blank Space", "Lover", "Style", "Welecome to New York", "Love Story", "ME!", "Shade It Off", "You Need Calm Down", "Safe & Sound", "Delicate", "...Reday For It?", "The Archer", "We Are Never Ever Getting Backing..", "willow"]
slideDataSource = SlideDataSource(dataArray: data)
slideView = SlideView(frame: self.view.frame)
slideView.rootView.delegate = self
slideView.slideTableView.dataSource = slideDataSource
slideView.slideTableView.delegate = self
self.view.addSubview(slideView)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initView()
}
// MARK: - Delegate block.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
print("------> OFFSET: \(offsetY)")
// 下拉判断
if offsetY < 0 {
NSLog("REMAKE.")
print("------> EXECUTE <0")
self.slideView.headerImageView.snp.remakeConstraints{ make in
make.top.equalTo(self.slideView.snp.top)
make.centerX.equalToSuperview()
// 下滑时需放大图片,即witdth与height需增加y轴的偏移量。UIKit中向下为y轴正方向,所以表面上y轴的增加量其实是负值,即操作时需减去offset
make.width.equalTo(self.slideView.rootView.frame.size.width - offsetY + 4)
make.height.equalTo(self.slideView.rootView.frame.size.width - offsetY + 4)
}
// 上滑判断
} else if offsetY > 0 {
print("------> EXECUTE >0")
self.slideView.headerImageView.snp.remakeConstraints{ make in
// 上滑时只需设置headerImageView的width与height与初始值相同即可
make.top.equalTo(self.slideView.rootView.snp.top)
make.centerX.equalToSuperview()
make.width.equalTo(self.slideView.rootView.frame.size.width)
make.height.equalTo(self.slideView.rootView.frame.size.width)
}
}
}
}