看到京东的下拉跳到下一页,自己也根据ScrollView的代理方法做一个Swift版本,效果如下:
下边是实现思路
1.创建一个contentView是屏幕高度的2倍
2.创建一个tableView,位置在contentView的第一个屏幕高度中
3.创建一个webview,位置在contentView的第二个屏幕高度中
4.创建两个Label,分别放在tableView的底部和webView的顶部
5.当tableView的偏移量大于tableView的最大偏移量时,将contentView平移到其下半部分,显示webview
6.当webView的偏移量小于其lable的最大偏移量时,平移contentView,显示其上半部分即tableView
详细代码
import UIKit
/// 屏幕的宽
let SCREENW = UIScreen.main.bounds.size.width
/// 屏幕的高
let SCREENH = UIScreen.main.bounds.size.height
let MyInfoTableViewCellIdentifier = "MyInfoTableViewCell"
class LDDetailViewController: UIViewController {
let kEndH: CGFloat = 80.0
var minY: CGFloat = 0.0
var maxY: CGFloat = 0.0
var isShowBottom = false
//容器View
lazy var contentView: UIView = {
let contentView = UIView()
contentView.frame = CGRect(x: 0, y: 0, width: SCREENW, height: SCREENH * 2)
contentView.backgroundColor = UIColor.white
return contentView
}()
//tableView
fileprivate lazy var tableView: UITableView = {[unowned self] in
let tableView = UITableView()
tableView.frame = CGRect(x: 0, y: 0, width: SCREENW, height: SCREENH)
tableView.delegate = self
tableView.dataSource = self
// tableView.rowHeight = 150
// tableView.separatorStyle = .none
tableView.register(UITableViewCell.self, forCellReuseIdentifier: MyInfoTableViewCellIdentifier)
// tableView.register(UINib(nibName: "MassLossVehiceTableViewCell", bundle: nil), forCellReuseIdentifier: kMassLossVehiceTableViewCellIdentifier)
return tableView
}()
//顶部view
lazy var topScrollView: UIScrollView = {[unowned self] in
let topScrollView = UIScrollView()
topScrollView.frame = CGRect(x: 0, y: 0, width: SCREENW, height: SCREENH)
topScrollView.contentSize = CGSize(width: SCREENW, height: SCREENH * 2)
topScrollView.backgroundColor = UIColor.white
topScrollView.delegate = self
return topScrollView
}()
//底部view
lazy var bottomWebView: UIWebView = {[unowned self] in
let bottomWebView = UIWebView()
bottomWebView.frame = CGRect(x: 0, y: SCREENH, width: SCREENW, height: SCREENH)
bottomWebView.scrollView.delegate = self
bottomWebView.loadRequest(URLRequest(url: URL(string: "https://www.baidu.com")!))
return bottomWebView
}()
//顶部View Label
lazy var topViewLabel: UILabel = {[unowned self] in
let topViewLabel = UILabel()
// topViewLabel.frame = CGRect(x: 0, y: self.topScrollView.contentSize.height, width: SCREENW, height: self.kEndH)
topViewLabel.font = UIFont.systemFont(ofSize: 13)
topViewLabel.textAlignment = .center
topViewLabel.text = "上拉显示底部bottomWebView"
topViewLabel.textColor = UIColor.white
topViewLabel.backgroundColor = UIColor.gray
return topViewLabel
}()
//底部View Lable
lazy var bottomViewLabel: UILabel = {[unowned self] in
let bottomViewLabel = UILabel()
bottomViewLabel.frame = CGRect(x: 0, y: -self.kEndH, width: SCREENW, height: self.kEndH)
bottomViewLabel.font = UIFont.systemFont(ofSize: 13)
bottomViewLabel.textAlignment = .center
bottomViewLabel.text = "下拉回到tableView"
bottomViewLabel.textColor = UIColor.white
bottomViewLabel.backgroundColor = UIColor.gray
return bottomViewLabel
}()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// self.navigationController?.isNavigationBarHidden = true
}
override func viewDidLoad() {
super.viewDidLoad()
// self.automaticallyAdjustsScrollViewInsets = false
view.backgroundColor = UIColor.white
setupUI()
}
}
extension LDDetailViewController: UIScrollViewDelegate,UITableViewDelegate,UITableViewDataSource {
fileprivate func setupUI(){
self.view.addSubview(self.contentView)
self.tableView.addSubview(self.topViewLabel)
// self.topScrollView.addSubview(self.topViewLabel)
self.bottomWebView.scrollView.addSubview(self.bottomViewLabel)
self.contentView.addSubview(self.tableView)
// self.contentView.addSubview(self.topScrollView)
self.contentView.addSubview(self.bottomWebView)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset: CGFloat = scrollView.contentOffset.y
if scrollView == self.tableView {
let middViewMAXH: CGFloat = self.tableView.contentSize.height - SCREENH + kEndH
if middViewMAXH > 0 {
topViewLabel.frame = CGRect(x: 0, y: self.tableView.contentSize.height, width: SCREENW, height: self.kEndH)
}
//如果偏移量小于 middleLab对应的最大偏移量 释放回道原有View
if offset <= middViewMAXH {
self.topViewLabel.text = "上拉显示底部bottomWebView↓↓"
} else {//如果偏移量大于 middleLab对应的最大偏移量 释放显示下一个View
self.topViewLabel.text = "释放显示底部bottomWebView"
}
}
if scrollView == self.bottomWebView.scrollView{
if offset <= -kEndH {//当下拉偏移小于释放范围 显示上一个View
self.bottomViewLabel.text = "释放回到tableView"
} else {
self.bottomViewLabel.text = "下拉回到tableView"
}
}
}
///滚动视图并结束拖动 将减速
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate {
let offset: CGFloat = scrollView.contentOffset.y
if scrollView == self.tableView {
if offset < 0 {
minY = myMIN(minY, offset)
} else {
maxY = myMAX(maxY, offset)
}
} else {
minY = myMIN(minY, offset)
}
let middViewMAXH: CGFloat = self.tableView.contentSize.height - SCREENH + kEndH
// 滚到底部视图
////如果偏移量大于 middleLab对应的最大偏移量 释放显示下一个View
if maxY >= middViewMAXH {
//设置是否显示底部View为false
isShowBottom = false
UIView.animate(withDuration: 0.25, animations: {
//原始的基础上偏移
self.contentView.transform = self.contentView.transform.translatedBy(x: 0, y: -SCREENH)
}, completion: {(_) in
//将最大Y值重置为0
self.maxY = 0.0
//设置是否显示底部View为true
self.isShowBottom = true
self.navigationController?.isNavigationBarHidden = true
})
}
//当下拉偏移小于释放范围 显示上一个View
if minY <= -kEndH && isShowBottom {
isShowBottom = false
UIView.animate(withDuration: 0.25, animations: {
//回到原有位置
self.contentView.transform = CGAffineTransform.identity
}, completion: { (_) in
self.minY = 0.0
self.navigationController?.isNavigationBarHidden = false
})
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 50
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MyInfoTableViewCellIdentifier, for: indexPath)
cell.selectionStyle = .none
cell.textLabel?.text = "cell\(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func myMIN(_ x: CGFloat, _ y: CGFloat) -> CGFloat {
return x < y ? x : y
}
func myMAX(_ x: CGFloat, _ y: CGFloat) -> CGFloat {
return x > y ? x : y
}
}
OC版本如下
#import "HViewController.h"
#define kScreenW [[UIScreen mainScreen] bounds].size.width
#define kScreenH [[UIScreen mainScreen] bounds].size.height
#define kEndH 80
@interface HViewController ()<UIScrollViewDelegate> {
CGFloat minY;
CGFloat maxY;
// 是否显示底部视图,
BOOL _isShowBottom;
}
@property(nonatomic,strong) UIView *contentView;
@property(nonatomic,strong) UIScrollView *middleView;
@property(nonatomic,strong) UIWebView *webView;
@property(nonatomic,strong) UILabel *bottomLab;
@property(nonatomic,strong) UILabel *middleLab;
@end
@implementation HViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.contentView];
[self.contentView addSubview:self.middleView];
[self.contentView addSubview:self.webView];
[self.middleView addSubview:self.middleLab];
[self.webView.scrollView addSubview:self.bottomLab];
}
#pragma makr - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat offset = scrollView.contentOffset.y;
if (scrollView == self.middleView) {
CGFloat middViewMAXH = self.middleView.contentSize.height - kScreenH + kEndH;
// NSLog(@"%f,%f",offset,middViewH);
//如果偏移量小于 middleLab对应的最大偏移量 释放回道原有View
if (offset <= middViewMAXH) {
self.middleLab.text = @"释放返回中间middleView";
} else {//如果偏移量大于 middleLab对应的最大偏移量 释放显示下一个View
self.middleLab.text = @"上拉显示底部View";
}
}
if (scrollView == self.webView.scrollView) {
//当下拉偏移小于释放范围
if (offset <= -kEndH) {
self.bottomLab.text = @"释放回到middleView";
} else {
self.bottomLab.text = @"下拉回到middleView";
}
}
}
//滚动视图并结束拖动 将减速
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (decelerate) {
CGFloat offset = scrollView.contentOffset.y;
NSLog(@"%f",offset);
if (scrollView == self.middleView)
{
if (offset < 0)
{
minY = MIN(minY, offset);
} else {
maxY = MAX(maxY, offset);
}
}
else
{
minY = MIN(minY, offset);
}
CGFloat middViewMAXH = self.middleView.contentSize.height - kScreenH + kEndH;
NSLog(@"maxyy--=>%f",middViewMAXH);
// 滚到底部视图
////如果偏移量大于 middleLab对应的最大偏移量 释放显示下一个View
if (maxY >= middViewMAXH) {
//设置是否显示底部View为No
_isShowBottom = NO;
[UIView animateWithDuration:0.4 animations:^{
//原始的基础上偏移
self.contentView.transform = CGAffineTransformTranslate(self.contentView.transform, 0, -kScreenH);
} completion:^(BOOL finished) {
//将最大Y值重置为0
maxY = 0.0f;
//设置是否显示底部View为yes
_isShowBottom = YES;
}];
}
NSLog(@"minY--------d>%f",minY);
//当下拉偏移小于释放范围 显示上一个View
if (minY <= -kEndH && _isShowBottom) {
_isShowBottom = NO;
[UIView animateWithDuration:0.4 animations:^{
//回到原有位置
self.contentView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
minY = 0.0f;
}];
}
}
}
#pragma mark - getter/setter
- (UIView *)contentView {
if (!_contentView) {
_contentView = [[UIView alloc]init];
_contentView.frame = CGRectMake(0, 0, kScreenW, kScreenH * 2);
_contentView.backgroundColor = [UIColor grayColor];
}
return _contentView;
}
- (UIScrollView *)middleView {
if (!_middleView) {
_middleView = [[UIScrollView alloc]init];
_middleView.backgroundColor = [UIColor whiteColor];
_middleView.frame = CGRectMake(0, 0, kScreenW, kScreenH);
_middleView.contentSize = CGSizeMake(kScreenW, kScreenH * 2);
_middleView.delegate = self;
}
return _middleView;
}
- (UIWebView *)webView {
if (!_webView) {
_webView = [[UIWebView alloc]init];
_webView.frame = CGRectMake(0, kScreenH, kScreenW, kScreenH);
[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
_webView.scrollView.delegate = self;
}
return _webView;
}
-(UILabel *)bottomLab {
if (!_bottomLab) {
_bottomLab = [[UILabel alloc]initWithFrame:CGRectMake(0, -kEndH, kScreenW, kEndH)];
_bottomLab.font = [UIFont systemFontOfSize:13.0f];
_bottomLab.textAlignment = NSTextAlignmentCenter;
_bottomLab.text = @"下拉返回中间View";
}
return _bottomLab;
}
- (UILabel *)middleLab {
if (!_middleLab) {
_middleLab = [[UILabel alloc]initWithFrame:CGRectMake(0, self.middleView.contentSize.height, kScreenW, kEndH)];
_middleLab.font = [UIFont systemFontOfSize:13.0f];
_middleLab.textAlignment = NSTextAlignmentCenter;
_middleLab.backgroundColor = [UIColor purpleColor];
_middleLab.text = @"上拉显示底部View";
_middleLab.textColor = [UIColor blackColor];
}
return _middleLab;
}
@end