UIScrollView增加刷新
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增加刷新的更多相关文章
- UIScrollView增加回弹效果
项目中经常要增加上下滑动回弹的效果: self.scrollView.alwaysBounceVertical = YES;
- 在UIScrollView、UICollectionView和UITableView中添加UIRefreshControl实现下拉刷新
Apple在iOS 6中添加了UIRefreshControl,但只能在UITableViewController中使用,不能在UIScrollView和UICollectionView中使用. 从i ...
- iOS - UIScrollView 相关属性代理详解
一.UIScrollView的属性和代理方法详解 属性: - (void)viewDidLoad { [super viewDidLoad]; _scrollView.backgroundColor ...
- 如何写一套下拉刷新的控件?《MJRefresh原理浅析》(附Demo下载地址)
相信大家有很多人在做项目的时候都在使用MJRefresh 控件来实现下拉刷新的功能: MJRefresh经过不断的重构与更新迭代,现在不管是功能上还是代码结构上都是相当不错的,都是很值我们去学习的. ...
- iOS开发UI篇—UIScrollView控件介绍
iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...
- 利用less监视模式实时预览样式刷新浏览器
[前言]此处介绍的方法只是我个人的用法,相信大家有更好更简洁的方式. 上次写到利用LiveReload解放F5.而且LiveReload可以编辑sass/less/stylus.但是可惜发现LiveR ...
- iOS开发之 UIScrollView的frame、contentSize、contentOffset和contentInset属性
ios中下拉图片变大效果 http://blog.csdn.net/mad2man/article/details/14169197 IOS中UIScrollView的frame.contentSiz ...
- UIScrollView控件详解
一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 (2)当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可 ...
- IOS UI-滚动视图(UIScrollView)
#import "ViewController.h" /* 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤小是极其有限的,因此直接展示在⽤用户眼前的内容也相当有限 ...
随机推荐
- 【好书摘要】性能优化中CPU、内存、磁盘IO、网络性能的依赖
系统优化是一项复杂.繁琐.长期的工作,优化前需要监测.采集.测试.评估,优化后也需要测试.采集.评估.监测,而且是一个长期和持续的过程,不 是说现在优化了,测试了,以后就可以一劳永逸了,也不是说书本上 ...
- json数组的序列化和反序列化json数组的序列化和反序列化
如题,我就不多说了,自己看代码的,很好理解 using System; using System.Collections.Generic; using System.Web; using System ...
- PHP5中的stdClass
PHP5中新增stdClass 官方手册参考:http://www.php.net/manual/en/language.oop5.basic.php#92123 stdClass类是PHP的一个内部 ...
- W3School-CSS 文本实例
CSS 文本实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CSS 内边距 (paddi ...
- Nginx问题定位之监控进程异常退出
nginx在运行过程中是否稳定,是否有异常退出过?这里总结几项平时会用到的小技巧. 1. 在error.log中查看是否有signal项,如果有,看看signal是多少. 比如,这是一个异常退出的情况 ...
- EF Power Tools的Reverse Engineer Code First逆向生成Model时处理计算字段
VS2013上使用EF Power Tools的Reverse Engineer Code First逆向生成Model时,没有处理计算字段.在保存实体时会出现错误. 可以通过修改Mapping.tt ...
- Hyper-V 上的android
为了各种实验环境,装了Hyper-V,然后ADT的android虚拟机就用不上Intel的HAXM了,慢得不行.只有想办法在Hyper-v上装android,还得要ADT能连上. 半天下来,终于搞定. ...
- 烂泥:nginx同时支持asp.net与php
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 经过两天的实验,终于让nginx同时支持asp.net与php了.下面就把具体的配置过程记录如下. 注意:本次实验OS:centos6 64bit. 尽 ...
- android scrollview 实现上下左右滚动方法
原来是scrollview与HorizontalScrollView组合布局 详细可参考:http://blog.csdn.net/aminfo/article/details/7846963
- [转载] Linux启动过程详解-《别怕Linux编程》之八
本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket.为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. = ...