iOS 仿 UC 浏览器个人中心 (下拉实现果冻效果)
由于最近没什么项目,所以就试着模仿做了一些 App 的框架或者效果,今天做的是模仿 UC 浏览器个人中心的下拉效果,也有人称之为果冻效果或者是阻尼效果,本文用到了drawRect进行了底层的画线,不过还是很简单的只要把封装好的 MyHeaderView 放入工程中即可
效果图如下:
实现如下
ViewController.m:
- //
- // ViewController.m
- // PullAnimation
- //
- // Created by Amydom on 16/10/29.
- // Copyright © 2016年 Amydom. All rights reserved.
- //
- #import "ViewController.h"
- #import "MyHeaderView.h"
- @interface ViewController () <UITableViewDelegate, UITableViewDataSource>
- @property (strong, nonatomic) MyHeaderView *headerView; // 上面蓝色的 view,可以自定义
- @property (strong, nonatomic) UITableView *tableView;
- @property (assign, nonatomic) CGFloat headerViewHeight; // headerView 高度
- @end
- @implementation ViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.headerViewHeight = 180;
- [self createView];
- }
- #pragma mark - initView
- - (void)createView{
- _tableView = [[UITableView alloc] init];
- _tableView.frame = self.view.bounds;
- _tableView.delegate = self;
- _tableView.dataSource = self;
- _tableView.rowHeight = 40;
- _tableView.sectionHeaderHeight = 20;
- _tableView.showsVerticalScrollIndicator = false;
- [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"mycell"];
- // 占位用的 view,高度 180
- UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, self.headerViewHeight)];
- view.backgroundColor = [UIColor clearColor];
- _tableView.tableHeaderView = view;
- [self.view addSubview:self.tableView];
- // 蓝色的 headerView
- _headerView = [[MyHeaderView alloc] init];
- self.headerView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.headerViewHeight);
- [self.view addSubview:self.headerView];
- }
- #pragma mark - 监听 tableView.contentOffset,也可以用 kvo 监听
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
- CGFloat offsetY = scrollView.contentOffset.y;
- CGRect frame = self.headerView.frame;
- if (offsetY < 0) {
- frame.size.height = self.headerViewHeight - offsetY;
- frame.origin.y = 0; // 及时归零
- } else {
- frame.size.height = self.headerViewHeight;
- frame.origin.y = -offsetY;
- }
- self.headerView.frame = frame;
- }
- // scrollViewWillEndDragging,这个方法内判断一下,contentOffset.y 值,如果超过多少值,那么自动回调一个 block,可实现下拉刷新
- //松手时触发
- - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
- CGFloat offsetY = scrollView.contentOffset.y;
- if (-offsetY > 70) {
- NSLog(@"11111");
- }
- }
- #pragma mark - tableView代理
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- return 30;
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- static NSString *indetifier = @"mycell";
- UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:indetifier];
- cell.textLabel.text = @"Amydom";
- return cell;
- }
- - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
- UITableViewHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"UITableViewHeaderFooterViewID"];
- if (view == nil) {
- view = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:@"UITableViewHeaderFooterViewID"];
- view.contentView.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0];;
- }
- return view;
- }
- @end
MyHeaderView.m:
(这里是自定义的 UIView MyHeaderView.h
@interface MyHeaderView : UIView
@end
)- //
- // MyHeaderView.m
- // PullAnimation
- //
- // Created by Amydom on 16/10/29.
- // Copyright © 2016年 Amydom. All rights reserved.
- //
- #import "MyHeaderView.h"
- @interface MyHeaderView ()
- @property (strong, nonatomic) UIImageView *imageV; // 随便放一个 imageView
- @property (assign, nonatomic) CGFloat headerViewHeight; // headerView 高度
- @property (assign, nonatomic) CGFloat screenWidth;
- @end
- @implementation MyHeaderView
- - (UIImageView *)imageV {
- if (_imageV == nil) {
- _imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ico_Default"]];
- _imageV.contentMode = UIViewContentModeScaleAspectFit;
- _imageV.userInteractionEnabled = true;
- [_imageV addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewTapAction:)]];
- }
- return _imageV;
- }
- - (void)imageViewTapAction:(id)sender {
- NSLog(@"imageView tap");
- }
- - (instancetype)init {
- if (self = [super init]) {
- self.backgroundColor = [UIColor clearColor];
- self.headerViewHeight = 180;
- self.screenWidth = [UIScreen mainScreen].bounds.size.width;
- [self addSubview:self.imageV];
- }
- return self;
- }
- // 更改 frame 会触发 layoutSubviews
- // 触发 layoutSubviews 后,这个 view 里面的控件想怎么变(旋转,位移,缩放),全部这个方法里面就好了
- - (void)layoutSubviews {
- [super layoutSubviews];
- // imageV 是 60 * 60 的
- CGFloat y = 60 + (self.frame.size.height - self.headerViewHeight) * 0.6;
- self.imageV.frame = CGRectMake((self.screenWidth - 60) * 0.5, y, 60, 60);
- [self setNeedsDisplay]; // 重绘
- }
- // 绘制曲线
- - (void)drawRect:(CGRect)rect {
- //获取上下文
- //CGContextRef 用来保存图形信息.输出目标
- CGContextRef context = UIGraphicsGetCurrentContext();
- //设置颜色
- CGContextSetRGBFillColor(context, 0.00392, 0.54117, 0.85098, 1.0);
- CGFloat h1 = self.headerViewHeight;
- CGFloat w = rect.size.width;
- CGFloat h = rect.size.height;
- //起点
- CGContextMoveToPoint(context, w, h1);
- //画线
- CGContextAddLineToPoint(context, w, 0);
- CGContextAddLineToPoint(context, 0, 0);
- CGContextAddLineToPoint(context, 0, h1);
- CGContextAddQuadCurveToPoint(context, w * 0.5, h + (h - h1) * 0.6, w, h1);
- //闭合
- CGContextClosePath(context);
- CGContextDrawPath(context, kCGPathFill);
- }
- // 这个 view 里面有多少个被点击的控件,把他的 frame 告诉 pointInside 就可以了
- //这个函数会被 hitTest 调用,返回 false 表示点击的不是自己,返回 true 表示点击的是自己
- - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
- // 判断点击的点,在不在圆内
- CGPoint center = self.imageV.center;
- CGFloat r = self.imageV.frame.size.width * 0.5;
- CGFloat newR = sqrt((center.x - point.x) * (center.x - point.x) + (center.y - point.y) * (center.y - point.y));
- // 浮点数比较不推荐用等号,虽然 ios 底层已经处理了这种情况
- if (newR > r) {
- return false;
- } else {
- return true;
- }
- }
- //- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; hitTest 主要用来做事件分发的,可以实现不规则点击,它在整个 view 结构上是递归的
- @end
因为做了判断,所以当点击 imageView(头像)时,无法响应下拉效果,这个可以根据需求进行修改!!
转载自:http://blog.****.net/amydom/article/details/53431362