1、

if (!self.scrollView) {

CGRect frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame));

UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];

//增加这个滚动事件是为了执行BaseViewController中的scrollViewDidEndDragging事件,滚动立马隐藏键盘

scrollView.delegate = self;

scrollView.backgroundColor = [UIColor clearColor];

[scrollView addHeaderWithTarget:self action:@selector(loadData)];

[self.view addSubview:scrollView];

self.scrollView = scrollView;

//为了让scrollView可以滚动,设置contentSize

self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) + 10);

} else {

[self.scrollView headerEndRefreshing];

}

------------------------------------------------------------------------------------------------------------

//

//  UIScrollView+MJRefresh.h

//  MJRefreshExample

//

//  Created by MJ Lee on 14-5-28.

//  Copyright (c) 2014年 itcast. All rights reserved.

//

// 版权属于原作者

// http://code4app.com (cn) http://code4app.net (en)

// 发布代码于最专业的源码分享网站: Code4App.com

#import <UIKit/UIKit.h>

@interface UIScrollView (MJRefresh)

#pragma mark - 下拉刷新

/**

*  添加一个下拉刷新头部控件

*

*  @param callback 回调

*/

- (void)addHeaderWithCallback:(void (^)())callback;

/**

*  添加一个下拉刷新头部控件

*

*  @param target 目标

*  @param action 回调方法

*/

- (void)addHeaderWithTarget:(id)target action:(SEL)action;

/**

*  移除下拉刷新头部控件

*/

- (void)removeHeader;

/**

*  主动让下拉刷新头部控件进入刷新状态

*/

- (void)headerBeginRefreshing;

/**

*  让下拉刷新头部控件停止刷新状态

*/

- (void)headerEndRefreshing;

/**

*  下拉刷新头部控件的可见性

*/

@property (nonatomic, assign, getter = isHeaderHidden) BOOL headerHidden;

/**

*  是否正在下拉刷新

*/

@property (nonatomic, assign, readonly, getter = isHeaderRefreshing) BOOL headerRefreshing;

#pragma mark - 上拉刷新

/**

*  添加一个上拉刷新尾部控件

*

*  @param callback 回调

*/

- (void)addFooterWithCallback:(void (^)())callback;

/**

*  添加一个上拉刷新尾部控件

*

*  @param target 目标

*  @param action 回调方法

*/

- (void)addFooterWithTarget:(id)target action:(SEL)action;

/**

*  移除上拉刷新尾部控件

*/

- (void)removeFooter;

/**

*  主动让上拉刷新尾部控件进入刷新状态

*/

- (void)footerBeginRefreshing;

/**

*  让上拉刷新尾部控件停止刷新状态

*/

- (void)footerEndRefreshing;

/**

*  上拉刷新头部控件的可见性

*/

@property (nonatomic, assign, getter = isFooterHidden) BOOL footerHidden;

/**

*  是否正在上拉刷新

*/

@property (nonatomic, assign, readonly, getter = isFooterRefreshing) BOOL footerRefreshing;

/**

*  设置尾部控件的文字

*/

@property (copy, nonatomic) NSString *footerPullToRefreshText; // 默认:@"上拉可以加载更多数据"

@property (copy, nonatomic) NSString *footerReleaseToRefreshText; // 默认:@"松开立即加载更多数据"

@property (copy, nonatomic) NSString *footerRefreshingText; // 默认:@"MJ哥正在帮你加载数据..."

/**

*  设置头部控件的文字

*/

@property (copy, nonatomic) NSString *headerPullToRefreshText; // 默认:@"下拉可以刷新"

@property (copy, nonatomic) NSString *headerReleaseToRefreshText; // 默认:@"松开立即刷新"

@property (copy, nonatomic) NSString *headerRefreshingText; // 默认:@"MJ哥正在帮你刷新..."

@end

--------------------------------------------------------------------

//

//  UIScrollView+MJRefresh.m

//  MJRefreshExample

//

//  Created by MJ Lee on 14-5-28.

//  Copyright (c) 2014年 itcast. All rights reserved.

//

// 版权属于原作者

// http://code4app.com (cn) http://code4app.net (en)

// 发布代码于最专业的源码分享网站: Code4App.com

#import "UIScrollView+MJRefresh.h"

#import "MJRefreshHeaderView.h"

#import "MJRefreshFooterView.h"

#import <objc/runtime.h>

@interface UIScrollView()

@property (weak, nonatomic) MJRefreshHeaderView *header;

@property (weak, nonatomic) MJRefreshFooterView *footer;

@end

@implementation UIScrollView (MJRefresh)

#pragma mark - 运行时相关

static char MJRefreshHeaderViewKey;

static char MJRefreshFooterViewKey;

- (void)setHeader:(MJRefreshHeaderView *)header {

[self willChangeValueForKey:@"MJRefreshHeaderViewKey"];

objc_setAssociatedObject(self, &MJRefreshHeaderViewKey,

header,

OBJC_ASSOCIATION_ASSIGN);

[self didChangeValueForKey:@"MJRefreshHeaderViewKey"];

}

- (MJRefreshHeaderView *)header {

return objc_getAssociatedObject(self, &MJRefreshHeaderViewKey);

}

- (void)setFooter:(MJRefreshFooterView *)footer {

[self willChangeValueForKey:@"MJRefreshFooterViewKey"];

objc_setAssociatedObject(self, &MJRefreshFooterViewKey,

footer,

OBJC_ASSOCIATION_ASSIGN);

[self didChangeValueForKey:@"MJRefreshFooterViewKey"];

}

- (MJRefreshFooterView *)footer {

return objc_getAssociatedObject(self, &MJRefreshFooterViewKey);

}

#pragma mark - 下拉刷新

/**

*  添加一个下拉刷新头部控件

*

*  @param callback 回调

*/

- (void)addHeaderWithCallback:(void (^)())callback

{

// 1.创建新的header

if (!self.header) {

MJRefreshHeaderView *header = [MJRefreshHeaderView header];

[self addSubview:header];

self.header = header;

}

// 2.设置block回调

self.header.beginRefreshingCallback = callback;

}

/**

*  添加一个下拉刷新头部控件

*

*  @param target 目标

*  @param action 回调方法

*/

- (void)addHeaderWithTarget:(id)target action:(SEL)action

{

// 1.创建新的header

if (!self.header) {

MJRefreshHeaderView *header = [MJRefreshHeaderView header];

[self addSubview:header];

self.header = header;

}

// 2.设置目标和回调方法

self.header.beginRefreshingTaget = target;

self.header.beginRefreshingAction = action;

}

/**

*  移除下拉刷新头部控件

*/

- (void)removeHeader

{

[self.header removeFromSuperview];

self.header = nil;

}

/**

*  主动让下拉刷新头部控件进入刷新状态

*/

- (void)headerBeginRefreshing

{

[self.header beginRefreshing];

}

/**

*  让下拉刷新头部控件停止刷新状态

*/

- (void)headerEndRefreshing

{

[self.header endRefreshing];

}

/**

*  下拉刷新头部控件的可见性

*/

- (void)setHeaderHidden:(BOOL)hidden

{

self.header.hidden = hidden;

}

- (BOOL)isHeaderHidden

{

return self.header.isHidden;

}

- (BOOL)isHeaderRefreshing

{

return self.header.state == MJRefreshStateRefreshing;

}

#pragma mark - 上拉刷新

/**

*  添加一个上拉刷新尾部控件

*

*  @param callback 回调

*/

- (void)addFooterWithCallback:(void (^)())callback

{

// 1.创建新的footer

if (!self.footer) {

MJRefreshFooterView *footer = [MJRefreshFooterView footer];

[self addSubview:footer];

self.footer = footer;

}

// 2.设置block回调

self.footer.beginRefreshingCallback = callback;

}

/**

*  添加一个上拉刷新尾部控件

*

*  @param target 目标

*  @param action 回调方法

*/

- (void)addFooterWithTarget:(id)target action:(SEL)action

{

// 1.创建新的footer

if (!self.footer) {

MJRefreshFooterView *footer = [MJRefreshFooterView footer];

[self addSubview:footer];

self.footer = footer;

}

// 2.设置目标和回调方法

self.footer.beginRefreshingTaget = target;

self.footer.beginRefreshingAction = action;

}

/**

*  移除上拉刷新尾部控件

*/

- (void)removeFooter

{

[self.footer removeFromSuperview];

self.footer = nil;

}

/**

*  主动让上拉刷新尾部控件进入刷新状态

*/

- (void)footerBeginRefreshing

{

[self.footer beginRefreshing];

}

/**

*  让上拉刷新尾部控件停止刷新状态

*/

- (void)footerEndRefreshing

{

[self.footer endRefreshing];

}

/**

*  下拉刷新头部控件的可见性

*/

- (void)setFooterHidden:(BOOL)hidden

{

self.footer.hidden = hidden;

}

- (BOOL)isFooterHidden

{

return self.footer.isHidden;

}

- (BOOL)isFooterRefreshing

{

return self.footer.state == MJRefreshStateRefreshing;

}

/**

*  文字

*/

- (void)setFooterPullToRefreshText:(NSString *)footerPullToRefreshText

{

self.footer.pullToRefreshText = footerPullToRefreshText;

}

- (NSString *)footerPullToRefreshText

{

return self.footer.pullToRefreshText;

}

- (void)setFooterReleaseToRefreshText:(NSString *)footerReleaseToRefreshText

{

self.footer.releaseToRefreshText = footerReleaseToRefreshText;

}

- (NSString *)footerReleaseToRefreshText

{

return self.footer.releaseToRefreshText;

}

- (void)setFooterRefreshingText:(NSString *)footerRefreshingText

{

self.footer.refreshingText = footerRefreshingText;

}

- (NSString *)footerRefreshingText

{

return self.footer.refreshingText;

}

- (void)setHeaderPullToRefreshText:(NSString *)headerPullToRefreshText

{

self.header.pullToRefreshText = headerPullToRefreshText;

}

- (NSString *)headerPullToRefreshText

{

return self.header.pullToRefreshText;

}

- (void)setHeaderReleaseToRefreshText:(NSString *)headerReleaseToRefreshText

{

self.header.releaseToRefreshText = headerReleaseToRefreshText;

}

- (NSString *)headerReleaseToRefreshText

{

return self.header.releaseToRefreshText;

}

- (void)setHeaderRefreshingText:(NSString *)headerRefreshingText

{

self.header.refreshingText = headerRefreshingText;

}

- (NSString *)headerRefreshingText

{

return self.header.refreshingText;

}

@end

---------------------------------------------------------------------------

//

//  MJRefreshHeaderView.h

//  MJRefresh

//

//  Created by mj on 13-2-26.

//  Copyright (c) 2013年 itcast. All rights reserved.

//  下拉刷新

// 版权属于原作者

// http://code4app.com (cn) http://code4app.net (en)

// 发布代码于最专业的源码分享网站: Code4App.com

#import "MJRefreshBaseView.h"

@interface MJRefreshHeaderView : MJRefreshBaseView

+ (instancetype)header;

@end

--------------------------------------------------------------

//

//  MJRefreshHeaderView.m

//  MJRefresh

//

//  Created by mj on 13-2-26.

//  Copyright (c) 2013年 itcast. All rights reserved.

//  下拉刷新

// 版权属于原作者

// http://code4app.com (cn) http://code4app.net (en)

// 发布代码于最专业的源码分享网站: Code4App.com

#import "MJRefreshConst.h"

#import "MJRefreshHeaderView.h"

#import "UIView+MJExtension.h"

#import "UIScrollView+MJExtension.h"

@interface MJRefreshHeaderView()

// 最后的更新时间

@property (nonatomic, strong) NSDate *lastUpdateTime;

@property (nonatomic, weak) UILabel *lastUpdateTimeLabel;

@end

@implementation MJRefreshHeaderView

#pragma mark - 控件初始化

/**

*  时间标签

*/

- (UILabel *)lastUpdateTimeLabel

{

if (!_lastUpdateTimeLabel) {

// 1.创建控件

UILabel *lastUpdateTimeLabel = [[UILabel alloc] init];

lastUpdateTimeLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;

lastUpdateTimeLabel.font = [UIFont boldSystemFontOfSize:12];

lastUpdateTimeLabel.textColor = MJRefreshLabelTextColor;

lastUpdateTimeLabel.backgroundColor = [UIColor clearColor];

lastUpdateTimeLabel.textAlignment = NSTextAlignmentCenter;

[self addSubview:_lastUpdateTimeLabel = lastUpdateTimeLabel];

// 2.加载时间

self.lastUpdateTime = [[NSUserDefaults standardUserDefaults] objectForKey:MJRefreshHeaderTimeKey];

}

return _lastUpdateTimeLabel;

}

+ (instancetype)header

{

return [[MJRefreshHeaderView alloc] init];

}

- (id)initWithFrame:(CGRect)frame

{

if (self = [super initWithFrame:frame]) {

self.pullToRefreshText = MJRefreshHeaderPullToRefresh;

self.releaseToRefreshText = MJRefreshHeaderReleaseToRefresh;

self.refreshingText = MJRefreshHeaderRefreshing;

}

return self;

}

- (void)layoutSubviews

{

[super layoutSubviews];

CGFloat statusX = 0;

CGFloat statusY = 0;

CGFloat statusHeight = self.mj_height * 0.5;

CGFloat statusWidth = self.mj_width;

// 1.状态标签

self.statusLabel.frame = CGRectMake(statusX, statusY, statusWidth, statusHeight);

// 2.时间标签

CGFloat lastUpdateY = statusHeight;

CGFloat lastUpdateX = 0;

CGFloat lastUpdateHeight = statusHeight;

CGFloat lastUpdateWidth = statusWidth;

self.lastUpdateTimeLabel.frame = CGRectMake(lastUpdateX, lastUpdateY, lastUpdateWidth, lastUpdateHeight);

}

- (void)willMoveToSuperview:(UIView *)newSuperview

{

[super willMoveToSuperview:newSuperview];

// 设置自己的位置和尺寸

self.mj_y = - self.mj_height;

}

#pragma mark - 状态相关

#pragma mark 设置最后的更新时间

- (void)setLastUpdateTime:(NSDate *)lastUpdateTime

{

_lastUpdateTime = lastUpdateTime;

// 1.归档

[[NSUserDefaults standardUserDefaults] setObject:lastUpdateTime forKey:MJRefreshHeaderTimeKey];

[[NSUserDefaults standardUserDefaults] synchronize];

// 2.更新时间

[self updateTimeLabel];

}

#pragma mark 更新时间字符串

- (void)updateTimeLabel

{

if (!self.lastUpdateTime) return;

// 1.获得年月日

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags = NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit |NSHourCalendarUnit |NSMinuteCalendarUnit;

NSDateComponents *cmp1 = [calendar components:unitFlags fromDate:_lastUpdateTime];

NSDateComponents *cmp2 = [calendar components:unitFlags fromDate:[NSDate date]];

// 2.格式化日期

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

if ([cmp1 day] == [cmp2 day]) { // 今天

formatter.dateFormat = @"今天 HH:mm";

} else if ([cmp1 year] == [cmp2 year]) { // 今年

formatter.dateFormat = @"MM-dd HH:mm";

} else {

formatter.dateFormat = @"yyyy-MM-dd HH:mm";

}

NSString *time = [formatter stringFromDate:self.lastUpdateTime];

// 3.显示日期

self.lastUpdateTimeLabel.text = [NSString stringWithFormat:@"最后更新:%@", time];

}

#pragma mark - 监听UIScrollView的contentOffset属性

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

// 不能跟用户交互就直接返回

if (!self.userInteractionEnabled || self.alpha <= 0.01 || self.hidden) return;

// 如果正在刷新,直接返回

if (self.state == MJRefreshStateRefreshing) return;

if ([MJRefreshContentOffset isEqualToString:keyPath]) {

[self adjustStateWithContentOffset];

}

}

/**

*  调整状态

*/

- (void)adjustStateWithContentOffset

{

// 当前的contentOffset

CGFloat currentOffsetY = self.scrollView.mj_contentOffsetY;

// 头部控件刚好出现的offsetY

CGFloat happenOffsetY = - self.scrollViewOriginalInset.top;

// 如果是向上滚动到看不见头部控件,直接返回

if (currentOffsetY >= happenOffsetY) return;

if (self.scrollView.isDragging) {

// 普通 和 即将刷新 的临界点

CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_height;

if (self.state == MJRefreshStateNormal && currentOffsetY < normal2pullingOffsetY) {

// 转为即将刷新状态

self.state = MJRefreshStatePulling;

} else if (self.state == MJRefreshStatePulling && currentOffsetY >= normal2pullingOffsetY) {

// 转为普通状态

self.state = MJRefreshStateNormal;

}

} else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开

// 开始刷新

self.state = MJRefreshStateRefreshing;

}

}

#pragma mark 设置状态

- (void)setState:(MJRefreshState)state

{

// 1.一样的就直接返回

if (self.state == state) return;

// 2.保存旧状态

MJRefreshState oldState = self.state;

// 3.调用父类方法

[super setState:state];

// 4.根据状态执行不同的操作

switch (state) {

case MJRefreshStateNormal: // 下拉可以刷新

{

// 刷新完毕

if (MJRefreshStateRefreshing == oldState) {

self.arrowImage.transform = CGAffineTransformIdentity;

// 保存刷新时间

self.lastUpdateTime = [NSDate date];

[UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{

self.scrollView.mj_contentInsetTop -= self.mj_height;

}];

} else {

// 执行动画

[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{

self.arrowImage.transform = CGAffineTransformIdentity;

}];

}

break;

}

case MJRefreshStatePulling: // 松开可立即刷新

{

// 执行动画

[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{

self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);

}];

break;

}

case MJRefreshStateRefreshing: // 正在刷新中

{

// 执行动画

[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{

// 1.增加滚动区域

CGFloat top = self.scrollViewOriginalInset.top + self.mj_height;

self.scrollView.mj_contentInsetTop = top;

// 2.设置滚动位置

self.scrollView.mj_contentOffsetY = - top;

}];

break;

}

default:

break;

}

}

@end

UIScrollView增加刷新的更多相关文章

  1. UIScrollView增加回弹效果

    项目中经常要增加上下滑动回弹的效果: self.scrollView.alwaysBounceVertical = YES;

  2. 在UIScrollView、UICollectionView和UITableView中添加UIRefreshControl实现下拉刷新

    Apple在iOS 6中添加了UIRefreshControl,但只能在UITableViewController中使用,不能在UIScrollView和UICollectionView中使用. 从i ...

  3. iOS - UIScrollView 相关属性代理详解

    一.UIScrollView的属性和代理方法详解 属性: - (void)viewDidLoad { [super viewDidLoad]; _scrollView.backgroundColor ...

  4. 如何写一套下拉刷新的控件?《MJRefresh原理浅析》(附Demo下载地址)

    相信大家有很多人在做项目的时候都在使用MJRefresh 控件来实现下拉刷新的功能: MJRefresh经过不断的重构与更新迭代,现在不管是功能上还是代码结构上都是相当不错的,都是很值我们去学习的. ...

  5. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

  6. 利用less监视模式实时预览样式刷新浏览器

    [前言]此处介绍的方法只是我个人的用法,相信大家有更好更简洁的方式. 上次写到利用LiveReload解放F5.而且LiveReload可以编辑sass/less/stylus.但是可惜发现LiveR ...

  7. iOS开发之 UIScrollView的frame、contentSize、contentOffset和contentInset属性

    ios中下拉图片变大效果 http://blog.csdn.net/mad2man/article/details/14169197 IOS中UIScrollView的frame.contentSiz ...

  8. UIScrollView控件详解

    一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 (2)当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可 ...

  9. IOS UI-滚动视图(UIScrollView)

    #import "ViewController.h" /* 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤小是极其有限的,因此直接展示在⽤用户眼前的内容也相当有限 ...

随机推荐

  1. 【好书摘要】性能优化中CPU、内存、磁盘IO、网络性能的依赖

    系统优化是一项复杂.繁琐.长期的工作,优化前需要监测.采集.测试.评估,优化后也需要测试.采集.评估.监测,而且是一个长期和持续的过程,不 是说现在优化了,测试了,以后就可以一劳永逸了,也不是说书本上 ...

  2. json数组的序列化和反序列化json数组的序列化和反序列化

    如题,我就不多说了,自己看代码的,很好理解 using System; using System.Collections.Generic; using System.Web; using System ...

  3. PHP5中的stdClass

    PHP5中新增stdClass 官方手册参考:http://www.php.net/manual/en/language.oop5.basic.php#92123 stdClass类是PHP的一个内部 ...

  4. W3School-CSS 文本实例

    CSS 文本实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CSS 内边距 (paddi ...

  5. Nginx问题定位之监控进程异常退出

    nginx在运行过程中是否稳定,是否有异常退出过?这里总结几项平时会用到的小技巧. 1. 在error.log中查看是否有signal项,如果有,看看signal是多少. 比如,这是一个异常退出的情况 ...

  6. EF Power Tools的Reverse Engineer Code First逆向生成Model时处理计算字段

    VS2013上使用EF Power Tools的Reverse Engineer Code First逆向生成Model时,没有处理计算字段.在保存实体时会出现错误. 可以通过修改Mapping.tt ...

  7. Hyper-V 上的android

    为了各种实验环境,装了Hyper-V,然后ADT的android虚拟机就用不上Intel的HAXM了,慢得不行.只有想办法在Hyper-v上装android,还得要ADT能连上. 半天下来,终于搞定. ...

  8. 烂泥:nginx同时支持asp.net与php

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 经过两天的实验,终于让nginx同时支持asp.net与php了.下面就把具体的配置过程记录如下. 注意:本次实验OS:centos6 64bit. 尽 ...

  9. android scrollview 实现上下左右滚动方法

    原来是scrollview与HorizontalScrollView组合布局 详细可参考:http://blog.csdn.net/aminfo/article/details/7846963

  10. [转载] Linux启动过程详解-《别怕Linux编程》之八

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket.为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. = ...