add mjrefresh

This commit is contained in:
wu736139669
2015-03-31 09:18:20 +08:00
parent 839ec05135
commit 3b29d41338
64 changed files with 5118 additions and 2505 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@@ -0,0 +1,9 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
#import "UIScrollView+MJRefresh.h"
#import "MJRefreshGifHeader.h"
#import "MJRefreshLegendHeader.h"
#import "MJRefreshGifFooter.h"
#import "MJRefreshLegendFooter.h"
#import "MJRefreshConst.h"
@@ -0,0 +1,37 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshComponent.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
// 刷新组件:基本的开始刷新和结束刷新行为
#import <UIKit/UIKit.h>
@interface MJRefreshComponent : UIView
{
UIEdgeInsets _scrollViewOriginalInset;
__weak UIScrollView *_scrollView;
}
#pragma mark - 文字处理
/** 文字颜色 */
@property (strong, nonatomic) UIColor *textColor;
/** 字体大小 */
@property (strong, nonatomic) UIFont *font;
#pragma mark - 刷新处理
/** 正在刷新的回调 */
@property (copy, nonatomic) void (^refreshingBlock)();
/** 设置回调对象和回调方法 */
- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action;
@property (weak, nonatomic) id refreshingTarget;
@property (assign, nonatomic) SEL refreshingAction;
/** 进入刷新状态 */
- (void)beginRefreshing;
/** 结束刷新状态 */
- (void)endRefreshing;
/** 是否正在刷新 */
- (BOOL)isRefreshing;
@end
@@ -0,0 +1,81 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshComponent.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshComponent.h"
#import "MJRefreshConst.h"
#import "UIView+MJExtension.h"
@interface MJRefreshComponent()
/** 记录scrollView刚开始的inset */
@property (assign, nonatomic) UIEdgeInsets scrollViewOriginalInset;
/** 父控件 */
@property (weak, nonatomic) UIScrollView *scrollView;
@end
@implementation MJRefreshComponent
#pragma mark - 初始化
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// 基本属性
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.backgroundColor = [UIColor clearColor];
// 默认文字颜色和字体大小
self.textColor = MJRefreshLabelTextColor;
self.font = MJRefreshLabelFont;
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
// 旧的父控件
[self.superview removeObserver:self forKeyPath:MJRefreshContentOffset context:nil];
if (newSuperview) { // 新的父控件
[newSuperview addObserver:self forKeyPath:MJRefreshContentOffset options:NSKeyValueObservingOptionNew context:nil];
// 设置宽度
self.mj_w = newSuperview.mj_w;
// 设置位置
self.mj_x = 0;
// 记录UIScrollView
self.scrollView = (UIScrollView *)newSuperview;
// 设置永远支持垂直弹簧效果
self.scrollView.alwaysBounceVertical = YES;
// 记录UIScrollView最开始的contentInset
self.scrollViewOriginalInset = self.scrollView.contentInset;
}
}
#pragma mark - 公共方法
- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action
{
self.refreshingTarget = target;
self.refreshingAction = action;
}
- (void)beginRefreshing
{
}
- (void)endRefreshing
{
}
- (BOOL)isRefreshing {
return NO;
}
@end
@@ -0,0 +1,48 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
#import <UIKit/UIKit.h>
// 日志输出
#ifdef DEBUG
#define MJLog(...) NSLog(__VA_ARGS__)
#else
#define MJLog(...)
#endif
// 过期提醒
#define MJDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
// 运行时objc_msgSend
#define msgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__)
#define msgTarget(target) (__bridge void *)(target)
// RGB颜色
#define MJColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
// 文字颜色
#define MJRefreshLabelTextColor MJColor(100, 100, 100)
// 字体大小
#define MJRefreshLabelFont [UIFont boldSystemFontOfSize:13]
// 图片路径
#define MJRefreshSrcName(file) [@"MJRefresh.bundle" stringByAppendingPathComponent:file]
// 常量
UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight;
UIKIT_EXTERN const CGFloat MJRefreshFooterHeight;
UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration;
UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration;
UIKIT_EXTERN NSString *const MJRefreshHeaderUpdatedTimeKey;
UIKIT_EXTERN NSString *const MJRefreshContentOffset;
UIKIT_EXTERN NSString *const MJRefreshContentSize;
UIKIT_EXTERN NSString *const MJRefreshPanState;
UIKIT_EXTERN NSString *const MJRefreshHeaderStateIdleText;
UIKIT_EXTERN NSString *const MJRefreshHeaderStatePullingText;
UIKIT_EXTERN NSString *const MJRefreshHeaderStateRefreshingText;
UIKIT_EXTERN NSString *const MJRefreshFooterStateIdleText;
UIKIT_EXTERN NSString *const MJRefreshFooterStateRefreshingText;
UIKIT_EXTERN NSString *const MJRefreshFooterStateNoMoreDataText;
@@ -0,0 +1,21 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
#import <UIKit/UIKit.h>
const CGFloat MJRefreshHeaderHeight = 64.0;
const CGFloat MJRefreshFooterHeight = 44.0;
const CGFloat MJRefreshFastAnimationDuration = 0.25;
const CGFloat MJRefreshSlowAnimationDuration = 0.4;
NSString *const MJRefreshHeaderUpdatedTimeKey = @"MJRefreshHeaderUpdatedTimeKey";
NSString *const MJRefreshContentOffset = @"contentOffset";
NSString *const MJRefreshContentSize = @"contentSize";
NSString *const MJRefreshPanState = @"pan.state";
NSString *const MJRefreshHeaderStateIdleText = @"下拉可以刷新";
NSString *const MJRefreshHeaderStatePullingText = @"松开立即刷新";
NSString *const MJRefreshHeaderStateRefreshingText = @"正在刷新数据中...";
NSString *const MJRefreshFooterStateIdleText = @"点击加载更多";
NSString *const MJRefreshFooterStateRefreshingText = @"正在加载更多的数据...";
NSString *const MJRefreshFooterStateNoMoreDataText = @"已经全部加载完毕";
@@ -0,0 +1,40 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshFooter.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/5.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshComponent.h"
typedef enum {
MJRefreshFooterStateIdle = 1, // 普通闲置状态
MJRefreshFooterStateRefreshing, // 正在刷新中的状态
MJRefreshFooterStateNoMoreData // 所有数据加载完毕,没有更多的数据了
} MJRefreshFooterState;
@interface MJRefreshFooter : MJRefreshComponent
/** 提示没有更多的数据 */
- (void)noticeNoMoreData;
/** 重置没有更多的数据(消除没有更多数据的状态) */
- (void)resetNoMoreData;
/** 刷新控件的状态(交给子类重写) */
@property (assign, nonatomic) MJRefreshFooterState state;
/** 是否隐藏状态标签 */
@property (assign, nonatomic, getter=isStateHidden) BOOL stateHidden;
/**
* 设置state状态下的状态文字内容title
*/
- (void)setTitle:(NSString *)title forState:(MJRefreshFooterState)state;
/** 是否自动刷新(默认为YES) */
@property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh;
/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */
@property (assign, nonatomic) CGFloat appearencePercentTriggerAutoRefresh;
@end
@@ -0,0 +1,319 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshFooter.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/5.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshFooter.h"
#import "MJRefreshConst.h"
#import "UIScrollView+MJExtension.h"
#import "MJRefreshHeader.h"
#import "UIView+MJExtension.h"
#import "UIScrollView+MJRefresh.h"
#import <objc/message.h>
@interface MJRefreshFooter()
/** 显示状态文字的标签 */
@property (weak, nonatomic) UILabel *stateLabel;
/** 点击可以加载更多 */
@property (weak, nonatomic) UIButton *loadMoreButton;
/** 没有更多的数据 */
@property (weak, nonatomic) UILabel *noMoreLabel;
/** 即将要执行的代码 */
@property (strong, nonatomic) NSMutableArray *willExecuteBlocks;
@end
@implementation MJRefreshFooter
#pragma mark - 懒加载
- (NSMutableArray *)willExecuteBlocks
{
if (!_willExecuteBlocks) {
self.willExecuteBlocks = [NSMutableArray array];
}
return _willExecuteBlocks;
}
- (UIButton *)loadMoreButton
{
if (!_loadMoreButton) {
UIButton *loadMoreButton = [[UIButton alloc] init];
loadMoreButton.backgroundColor = [UIColor clearColor];
[loadMoreButton addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_loadMoreButton = loadMoreButton];
}
return _loadMoreButton;
}
- (UILabel *)noMoreLabel
{
if (!_noMoreLabel) {
UILabel *noMoreLabel = [[UILabel alloc] init];
noMoreLabel.backgroundColor = [UIColor clearColor];
noMoreLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_noMoreLabel = noMoreLabel];
}
return _noMoreLabel;
}
- (UILabel *)stateLabel
{
if (!_stateLabel) {
UILabel *stateLabel = [[UILabel alloc] init];
stateLabel.backgroundColor = [UIColor clearColor];
stateLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_stateLabel = stateLabel];
}
return _stateLabel;
}
#pragma mark - 初始化方法
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// 默认底部控件100%出现时才会自动刷新
self.appearencePercentTriggerAutoRefresh = 1.0;
// 设置为默认状态
self.automaticallyRefresh = YES;
self.state = MJRefreshFooterStateIdle;
// 初始化文字
[self setTitle:MJRefreshFooterStateIdleText forState:MJRefreshFooterStateIdle];
[self setTitle:MJRefreshFooterStateRefreshingText forState:MJRefreshFooterStateRefreshing];
[self setTitle:MJRefreshFooterStateNoMoreDataText forState:MJRefreshFooterStateNoMoreData];
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
// 旧的父控件
[self.superview removeObserver:self forKeyPath:MJRefreshContentSize context:nil];
[self.superview removeObserver:self forKeyPath:MJRefreshPanState context:nil];
if (newSuperview) { // 新的父控件
// 监听
[newSuperview addObserver:self forKeyPath:MJRefreshContentSize options:NSKeyValueObservingOptionNew context:nil];
[newSuperview addObserver:self forKeyPath:MJRefreshPanState options:NSKeyValueObservingOptionNew context:nil];
self.mj_h = MJRefreshFooterHeight;
_scrollView.mj_insetB += self.mj_h;
// 重新调整frame
[self adjustFrameWithContentSize];
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.loadMoreButton.frame = self.bounds;
self.stateLabel.frame = self.bounds;
self.noMoreLabel.frame = self.bounds;
}
#pragma mark - 私有方法
- (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 == MJRefreshFooterStateIdle) {
// 当是Idle状态时,才需要检测是否要进入刷新状态
if ([keyPath isEqualToString:MJRefreshPanState]) {
if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) {// 手松开
if (_scrollView.mj_insetT + _scrollView.mj_contentSizeH <= _scrollView.mj_h) { // 不够一个屏幕
if (_scrollView.mj_offsetY > - _scrollView.mj_insetT) { // 向上拽
[self beginRefreshing];
}
} else { // 超出一个屏幕
if (_scrollView.mj_offsetY > _scrollView.mj_contentSizeH + _scrollView.mj_insetB - _scrollView.mj_h) {
[self beginRefreshing];
}
}
}
} else if ([keyPath isEqualToString:MJRefreshContentOffset]) {
if (self.state != MJRefreshFooterStateRefreshing && self.automaticallyRefresh) {
// 根据contentOffset调整state
[self adjustStateWithContentOffset];
}
}
}
// 不管是什么状态,都要调整位置
if ([keyPath isEqualToString:MJRefreshContentSize]) {
[self adjustFrameWithContentSize];
}
}
#pragma mark 根据contentOffset调整state
- (void)adjustStateWithContentOffset
{
if (self.mj_y == 0) return;
if (_scrollView.mj_insetT + _scrollView.mj_contentSizeH > _scrollView.mj_h) { // 内容超过一个屏幕
// 这里的_scrollView.mj_contentSizeH替换掉self.mj_y更为合理
if (_scrollView.mj_offsetY > _scrollView.mj_contentSizeH - _scrollView.mj_h + self.mj_h * self.appearencePercentTriggerAutoRefresh + _scrollView.mj_insetB - self.mj_h) {
// 当底部刷新控件完全出现时,才刷新
[self beginRefreshing];
}
}
}
- (void)adjustFrameWithContentSize
{
// 设置位置
self.mj_y = _scrollView.mj_contentSizeH;
}
- (void)buttonClick
{
[self beginRefreshing];
}
#pragma mark - 公共方法
- (void)setHidden:(BOOL)hidden
{
__weak typeof(self) weakSelf = self;
BOOL lastHidden = weakSelf.isHidden;
CGFloat h = weakSelf.mj_h;
[weakSelf.willExecuteBlocks addObject:^{
if (!lastHidden && hidden) {
weakSelf.state = MJRefreshFooterStateIdle;
_scrollView.mj_insetB -= h;
} else if (lastHidden && !hidden) {
_scrollView.mj_insetB += h;
[weakSelf adjustFrameWithContentSize];
}
}];
[weakSelf setNeedsDisplay]; // 放到drawRect是为了延迟执行,防止因为修改了inset,导致循环调用数据源方法
[super setHidden:hidden];
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
for (void (^block)() in self.willExecuteBlocks) {
block();
}
[self.willExecuteBlocks removeAllObjects];
}
- (void)beginRefreshing
{
self.state = MJRefreshFooterStateRefreshing;
}
- (void)endRefreshing
{
self.state = MJRefreshFooterStateIdle;
}
- (BOOL)isRefreshing
{
return self.state == MJRefreshFooterStateRefreshing;
}
- (void)noticeNoMoreData
{
self.state = MJRefreshFooterStateNoMoreData;
}
- (void)resetNoMoreData
{
self.state = MJRefreshFooterStateIdle;
}
- (void)setTitle:(NSString *)title forState:(MJRefreshFooterState)state
{
if (title == nil) return;
// 刷新当前状态的文字
switch (state) {
case MJRefreshFooterStateIdle:
[self.loadMoreButton setTitle:title forState:UIControlStateNormal];
break;
case MJRefreshFooterStateRefreshing:
self.stateLabel.text = title;
break;
case MJRefreshFooterStateNoMoreData:
self.noMoreLabel.text = title;
break;
default:
break;
}
}
- (void)setState:(MJRefreshFooterState)state
{
if (_state == state) return;
_state = state;
switch (state) {
case MJRefreshFooterStateIdle:
self.noMoreLabel.hidden = YES;
self.stateLabel.hidden = YES;
self.loadMoreButton.hidden = NO;
break;
case MJRefreshFooterStateRefreshing:
self.loadMoreButton.hidden = YES;
self.noMoreLabel.hidden = YES;
if (!self.stateHidden) self.stateLabel.hidden = NO;
if (self.refreshingBlock) {
self.refreshingBlock();
}
if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
msgSend(msgTarget(self.refreshingTarget), self.refreshingAction, self);
}
break;
case MJRefreshFooterStateNoMoreData:
self.loadMoreButton.hidden = YES;
self.noMoreLabel.hidden = NO;
self.stateLabel.hidden = YES;
break;
default:
break;
}
}
- (void)setTextColor:(UIColor *)textColor
{
[super setTextColor:textColor];
self.stateLabel.textColor = textColor;
[self.loadMoreButton setTitleColor:textColor forState:UIControlStateNormal];
self.noMoreLabel.textColor = textColor;
}
- (void)setFont:(UIFont *)font
{
[super setFont:font];
self.loadMoreButton.titleLabel.font = font;
self.noMoreLabel.font = font;
self.stateLabel.font = font;
}
- (void)setStateHidden:(BOOL)stateHidden
{
_stateHidden = stateHidden;
self.stateLabel.hidden = stateHidden;
[self setNeedsLayout];
}
@end
@@ -0,0 +1,15 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshGifFooter.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/5.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshFooter.h"
@interface MJRefreshGifFooter : MJRefreshFooter
/** 正在刷新时的动画图片 */
@property (strong, nonatomic) NSArray *refreshingImages;
@end
@@ -0,0 +1,90 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshGifFooter.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/5.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshGifFooter.h"
#import "MJRefreshConst.h"
#import "UIView+MJExtension.h"
#import "UIScrollView+MJExtension.h"
@interface MJRefreshGifFooter()
/** 播放动画图片的控件 */
@property (weak, nonatomic) UIImageView *gifView;
@end
@implementation MJRefreshGifFooter
#pragma mark - 懒加载
- (UIImageView *)gifView
{
if (!_gifView) {
UIImageView *gifView = [[UIImageView alloc] init];
[self addSubview:_gifView = gifView];
}
return _gifView;
}
#pragma mark - 初始化方法
- (void)layoutSubviews
{
[super layoutSubviews];
// 指示器
self.gifView.frame = self.bounds;
if (self.stateHidden) {
self.gifView.contentMode = UIViewContentModeCenter;
} else {
self.gifView.contentMode = UIViewContentModeRight;
self.gifView.mj_w = self.mj_w * 0.5 - 90;
}
}
#pragma mark - 公共方法
- (void)setState:(MJRefreshFooterState)state
{
if (self.state == state) return;
switch (state) {
case MJRefreshFooterStateIdle:
self.gifView.hidden = YES;
[self.gifView stopAnimating];
break;
case MJRefreshFooterStateRefreshing:
self.gifView.hidden = NO;
[self.gifView startAnimating];
break;
case MJRefreshFooterStateNoMoreData:
self.gifView.hidden = YES;
[self.gifView stopAnimating];
break;
default:
break;
}
// super里面有回调,应该在最后面调用
[super setState:state];
}
- (void)setRefreshingImages:(NSArray *)refreshingImages
{
_refreshingImages = refreshingImages;
self.gifView.animationImages = refreshingImages;
self.gifView.animationDuration = refreshingImages.count * 0.1;
// 根据图片设置控件的高度
UIImage *image = [refreshingImages firstObject];
if (image.size.height > self.mj_h) {
_scrollView.mj_insetB -= self.mj_h;
self.mj_h = image.size.height;
_scrollView.mj_insetB += self.mj_h;
}
}
@end
@@ -0,0 +1,15 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshGifHeader.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
// 带有gif图片功能的下拉刷新控件
#import "MJRefreshHeader.h"
@interface MJRefreshGifHeader : MJRefreshHeader
/** 设置state状态下的动画图片images */
- (void)setImages:(NSArray *)images forState:(MJRefreshHeaderState)state;
@end
@@ -0,0 +1,130 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshGifHeader.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshGifHeader.h"
#import "MJRefreshConst.h"
#import "UIView+MJExtension.h"
@interface MJRefreshGifHeader()
/** 所有状态对应的动画图片 */
@property (strong, nonatomic) NSMutableDictionary *stateImages;
/** 播放动画图片的控件 */
@property (weak, nonatomic) UIImageView *gifView;
@end
@implementation MJRefreshGifHeader
#pragma mark - 懒加载
- (NSMutableDictionary *)stateImages
{
if (!_stateImages) {
self.stateImages = [NSMutableDictionary dictionary];
}
return _stateImages;
}
- (UIImageView *)gifView
{
if (!_gifView) {
UIImageView *gifView = [[UIImageView alloc] init];
[self addSubview:_gifView = gifView];
}
return _gifView;
}
#pragma mark - 初始化
- (void)layoutSubviews
{
[super layoutSubviews];
self.gifView.frame = self.bounds;
if (self.stateHidden && self.updatedTimeHidden) {
self.gifView.contentMode = UIViewContentModeCenter;
} else {
self.gifView.contentMode = UIViewContentModeRight;
self.gifView.mj_w = self.mj_w * 0.5 - 90;
}
}
#pragma mark - 公共方法
#pragma mark 设置状态
- (void)setState:(MJRefreshHeaderState)state
{
if (self.state == state) return;
// 旧状态
MJRefreshHeaderState oldState = self.state;
NSArray *images = self.stateImages[@(state)];
if (images.count != 0) {
switch (state) {
case MJRefreshHeaderStateIdle: {
if (oldState == MJRefreshHeaderStateRefreshing) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJRefreshSlowAnimationDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.pullingPercent = 0.0;
});
} else {
self.pullingPercent = self.pullingPercent;
}
break;
}
case MJRefreshHeaderStatePulling:
case MJRefreshHeaderStateRefreshing: {
[self.gifView stopAnimating];
if (images.count == 1) { // 单张图片
self.gifView.image = [images lastObject];
} else { // 多张图片
self.gifView.animationImages = images;
self.gifView.animationDuration = images.count * 0.1;
[self.gifView startAnimating];
}
break;
}
default:
break;
}
}
// super里面有回调,应该在最后面调用
[super setState:state];
}
- (void)setPullingPercent:(CGFloat)pullingPercent
{
[super setPullingPercent:pullingPercent];
NSArray *images = self.stateImages[@(self.state)];
switch (self.state) {
case MJRefreshHeaderStateIdle: {
[self.gifView stopAnimating];
NSUInteger index = images.count * self.pullingPercent;
if (index >= images.count) index = images.count - 1;
self.gifView.image = images[index];
break;
}
default:
break;
}
}
- (void)setImages:(NSArray *)images forState:(MJRefreshHeaderState)state
{
if (images == nil) return;
self.stateImages[@(state)] = images;
// 根据图片设置控件的高度
UIImage *image = [images firstObject];
if (image.size.height > self.mj_h) {
self.mj_h = image.size.height;
}
}
@end
@@ -0,0 +1,47 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshHeader.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
// 下拉刷新控件:负责监控用户下拉的状态
#import "MJRefreshComponent.h"
// 下拉刷新控件的状态
typedef enum {
/** 普通闲置状态 */
MJRefreshHeaderStateIdle = 1,
/** 松开就可以进行刷新的状态 */
MJRefreshHeaderStatePulling,
/** 正在刷新中的状态 */
MJRefreshHeaderStateRefreshing,
/** 即将刷新的状态 */
MJRefreshHeaderStateWillRefresh
} MJRefreshHeaderState;
@interface MJRefreshHeader : MJRefreshComponent
/** 利用这个key来保存上次的刷新时间(不同界面的刷新控件应该用不同的dateKey,以区分不同界面的刷新时间) */
@property (copy, nonatomic) NSString *dateKey;
/** 利用这个block来决定显示的更新时间 */
@property (copy, nonatomic) NSString *(^updatedTimeTitle)(NSDate *updatedTime);
/**
* 设置state状态下的状态文字内容title(别直接拿stateLabel修改文字)
*/
- (void)setTitle:(NSString *)title forState:(MJRefreshHeaderState)state;
/** 刷新控件的状态 */
@property (assign, nonatomic) MJRefreshHeaderState state;
#pragma mark - 文字控件的可见性处理
/** 是否隐藏状态标签 */
@property (assign, nonatomic, getter=isStateHidden) BOOL stateHidden;
/** 是否隐藏刷新时间标签 */
@property (assign, nonatomic, getter=isUpdatedTimeHidden) BOOL updatedTimeHidden;
#pragma mark - 交给子类重写
/** 下拉的百分比(交给子类重写) */
@property (assign, nonatomic) CGFloat pullingPercent;
@end
@@ -0,0 +1,332 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshHeader.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshHeader.h"
#import "MJRefreshConst.h"
#import "UIView+MJExtension.h"
#import <objc/message.h>
#import "UIScrollView+MJExtension.h"
@interface MJRefreshHeader()
/** 显示上次刷新时间的标签 */
@property (weak, nonatomic) UILabel *updatedTimeLabel;
/** 上次刷新时间 */
@property (strong, nonatomic) NSDate *updatedTime;
/** 显示状态文字的标签 */
@property (weak, nonatomic) UILabel *stateLabel;
/** 所有状态对应的文字 */
@property (strong, nonatomic) NSMutableDictionary *stateTitles;
@end
@implementation MJRefreshHeader
#pragma mark - 懒加载
- (NSMutableDictionary *)stateTitles
{
if (!_stateTitles) {
self.stateTitles = [NSMutableDictionary dictionary];
}
return _stateTitles;
}
- (UILabel *)stateLabel
{
if (!_stateLabel) {
UILabel *stateLabel = [[UILabel alloc] init];
stateLabel.backgroundColor = [UIColor clearColor];
stateLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_stateLabel = stateLabel];
}
return _stateLabel;
}
- (UILabel *)updatedTimeLabel
{
if (!_updatedTimeLabel) {
UILabel *updatedTimeLabel = [[UILabel alloc] init];
updatedTimeLabel.backgroundColor = [UIColor clearColor];
updatedTimeLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_updatedTimeLabel = updatedTimeLabel];
}
return _updatedTimeLabel;
}
#pragma mark - 初始化方法
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// 设置默认的dateKey
self.dateKey = MJRefreshHeaderUpdatedTimeKey;
// 设置为默认状态
self.state = MJRefreshHeaderStateIdle;
// 初始化文字
[self setTitle:MJRefreshHeaderStateIdleText forState:MJRefreshHeaderStateIdle];
[self setTitle:MJRefreshHeaderStatePullingText forState:MJRefreshHeaderStatePulling];
[self setTitle:MJRefreshHeaderStateRefreshingText forState:MJRefreshHeaderStateRefreshing];
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
if (newSuperview) {
self.mj_h = MJRefreshHeaderHeight;
}
}
- (void)drawRect:(CGRect)rect
{
if (self.state == MJRefreshHeaderStateWillRefresh) {
self.state = MJRefreshHeaderStateRefreshing;
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
// 设置自己的位置
self.mj_y = - self.mj_h;
// 2个标签都隐藏
if (self.stateHidden && self.updatedTimeHidden) return;
if (self.updatedTimeHidden) { // 显示状态
_stateLabel.frame = self.bounds;
} else if (self.stateHidden) { // 显示时间
self.updatedTimeLabel.frame = self.bounds;
} else { // 都显示
CGFloat stateH = self.mj_h * 0.55;
CGFloat stateW = self.mj_w;
// 1.状态标签
_stateLabel.frame = CGRectMake(0, 0, stateW, stateH);
// 2.时间标签
CGFloat updatedTimeY = stateH;
CGFloat updatedTimeH = self.mj_h - stateH;
CGFloat updatedTimeW = stateW;
self.updatedTimeLabel.frame = CGRectMake(0, updatedTimeY, updatedTimeW, updatedTimeH);
}
}
#pragma mark - 私有方法
- (void)setDateKey:(NSString *)dateKey
{
_dateKey = dateKey ? dateKey : MJRefreshHeaderUpdatedTimeKey;
self.updatedTime = [[NSUserDefaults standardUserDefaults] objectForKey:_dateKey];
}
#pragma mark 设置最后的更新时间
- (void)setUpdatedTime:(NSDate *)updatedTime
{
_updatedTime = updatedTime;
if (updatedTime) {
[[NSUserDefaults standardUserDefaults] setObject:updatedTime forKey:self.dateKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if (self.updatedTimeTitle) {
self.updatedTimeLabel.text = self.updatedTimeTitle(updatedTime);
return;
}
if (updatedTime) {
// 1.获得年月日
NSCalendar *calendar = [NSCalendar currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour |NSCalendarUnitMinute;
NSDateComponents *cmp1 = [calendar components:unitFlags fromDate:updatedTime];
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:updatedTime];
// 3.显示日期
self.updatedTimeLabel.text = [NSString stringWithFormat:@"最后更新:%@", time];
} else {
self.updatedTimeLabel.text = @"最后更新:无记录";
}
}
#pragma mark KVO属性监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// 遇到这些情况就直接返回
if (!self.userInteractionEnabled || self.alpha <= 0.01 || self.hidden || self.state == MJRefreshHeaderStateRefreshing) return;
// 根据contentOffset调整state
if ([keyPath isEqualToString:MJRefreshContentOffset]) {
[self adjustStateWithContentOffset];
}
}
#pragma mark 根据contentOffset调整state
- (void)adjustStateWithContentOffset
{
if (self.state != MJRefreshHeaderStateRefreshing) {
// 在刷新过程中,跳转到下一个控制器时,contentInset可能会变
_scrollViewOriginalInset = _scrollView.contentInset;
}
// 当前的contentOffset
CGFloat offsetY = _scrollView.mj_offsetY;
// 头部控件刚好出现的offsetY
CGFloat happenOffsetY = - _scrollViewOriginalInset.top;
// 如果是向上滚动到看不见头部控件,直接返回
if (offsetY >= happenOffsetY) return;
// 普通 和 即将刷新 的临界点
CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h;
if (_scrollView.isDragging) {
self.pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
if (self.state == MJRefreshHeaderStateIdle && offsetY < normal2pullingOffsetY) {
// 转为即将刷新状态
self.state = MJRefreshHeaderStatePulling;
} else if (self.state == MJRefreshHeaderStatePulling && offsetY >= normal2pullingOffsetY) {
// 转为普通状态
self.state = MJRefreshHeaderStateIdle;
}
} else if (self.state == MJRefreshHeaderStatePulling) {// 即将刷新 && 手松开
self.pullingPercent = 1.0;
// 开始刷新
self.state = MJRefreshHeaderStateRefreshing;
} else {
self.pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
}
}
#pragma mark - 公共方法
- (void)setTitle:(NSString *)title forState:(MJRefreshHeaderState)state
{
if (title == nil) return;
self.stateTitles[@(state)] = title;
// 刷新当前状态的文字
self.stateLabel.text = self.stateTitles[@(self.state)];
}
- (void)beginRefreshing
{
if (self.window) {
self.state = MJRefreshHeaderStateRefreshing;
} else {
self.state = MJRefreshHeaderStateWillRefresh;
}
}
- (void)endRefreshing
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.state = MJRefreshHeaderStateIdle;
});
}
- (BOOL)isRefreshing
{
return self.state == MJRefreshHeaderStateRefreshing;
}
- (void)setState:(MJRefreshHeaderState)state
{
if (_state == state) return;
// 旧状态
MJRefreshHeaderState oldState = _state;
// 赋值
_state = state;
// 设置状态文字
_stateLabel.text = _stateTitles[@(state)];
switch (state) {
case MJRefreshHeaderStateIdle: {
if (oldState == MJRefreshHeaderStateRefreshing) {
// 保存刷新时间
self.updatedTime = [NSDate date];
// 恢复inset和offset
[UIView animateWithDuration:MJRefreshSlowAnimationDuration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState animations:^{
_scrollView.mj_insetT -= self.mj_h;
} completion:nil];
}
break;
}
case MJRefreshHeaderStateRefreshing: {
[UIView animateWithDuration:MJRefreshFastAnimationDuration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionBeginFromCurrentState animations:^{
// 增加滚动区域
CGFloat top = _scrollViewOriginalInset.top + self.mj_h;
_scrollView.mj_insetT = top;
// 设置滚动位置
_scrollView.mj_offsetY = - top;
} completion:^(BOOL finished) {
// 回调
if (self.refreshingBlock) {
self.refreshingBlock();
}
if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
msgSend(msgTarget(self.refreshingTarget), self.refreshingAction, self);
}
}];
break;
}
default:
break;
}
}
- (void)setTextColor:(UIColor *)textColor
{
[super setTextColor:textColor];
self.updatedTimeLabel.textColor = textColor;
self.stateLabel.textColor = textColor;
}
- (void)setFont:(UIFont *)font
{
[super setFont:font];
self.updatedTimeLabel.font = font;
self.stateLabel.font = font;
}
- (void)setStateHidden:(BOOL)stateHidden
{
_stateHidden = stateHidden;
self.stateLabel.hidden = stateHidden;
[self setNeedsLayout];
}
- (void)setUpdatedTimeHidden:(BOOL)updatedTimeHidden
{
_updatedTimeHidden = updatedTimeHidden;
self.updatedTimeLabel.hidden = updatedTimeHidden;
[self setNeedsLayout];
}
@end
@@ -0,0 +1,14 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshLegendFooter.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/5.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshFooter.h"
@interface MJRefreshLegendFooter : MJRefreshFooter
@end
@@ -0,0 +1,68 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshLegendFooter.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/5.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshLegendFooter.h"
#import "MJRefreshConst.h"
#import "UIView+MJExtension.h"
#import "UIScrollView+MJExtension.h"
@interface MJRefreshLegendFooter()
@property (nonatomic, weak) UIActivityIndicatorView *activityView;
@end
@implementation MJRefreshLegendFooter
#pragma mark - 懒加载
- (UIActivityIndicatorView *)activityView
{
if (!_activityView) {
UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self addSubview:_activityView = activityView];
}
return _activityView;
}
#pragma mark - 初始化方法
- (void)layoutSubviews
{
[super layoutSubviews];
// 指示器
if (self.stateHidden) {
self.activityView.center = CGPointMake(self.mj_w * 0.5, self.mj_h * 0.5);
} else {
self.activityView.center = CGPointMake(self.mj_w * 0.5 - 100, self.mj_h * 0.5);
}
}
#pragma mark - 公共方法
- (void)setState:(MJRefreshFooterState)state
{
if (self.state == state) return;
switch (state) {
case MJRefreshFooterStateIdle:
[self.activityView stopAnimating];
break;
case MJRefreshFooterStateRefreshing:
[self.activityView startAnimating];
break;
case MJRefreshFooterStateNoMoreData:
[self.activityView stopAnimating];
break;
default:
break;
}
// super里面有回调,应该在最后面调用
[super setState:state];
}
@end
@@ -0,0 +1,14 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshLegendHeader.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
// 传统的下拉刷新控件:箭头 + 圈圈
#import "MJRefreshHeader.h"
@interface MJRefreshLegendHeader : MJRefreshHeader
@end
@@ -0,0 +1,103 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// MJRefreshLegendHeader.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "MJRefreshLegendHeader.h"
#import "MJRefreshConst.h"
#import "UIView+MJExtension.h"
@interface MJRefreshLegendHeader()
@property (nonatomic, weak) UIImageView *arrowImage;
@property (nonatomic, weak) UIActivityIndicatorView *activityView;
@end
@implementation MJRefreshLegendHeader
#pragma mark - 懒加载
- (UIImageView *)arrowImage
{
if (!_arrowImage) {
UIImageView *arrowImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:MJRefreshSrcName(@"arrow.png")]];
[self addSubview:_arrowImage = arrowImage];
}
return _arrowImage;
}
- (UIActivityIndicatorView *)activityView
{
if (!_activityView) {
UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityView.bounds = self.arrowImage.bounds;
[self addSubview:_activityView = activityView];
}
return _activityView;
}
#pragma mark - 初始化
- (void)layoutSubviews
{
[super layoutSubviews];
// 箭头
CGFloat arrowX = (self.stateHidden && self.updatedTimeHidden) ? self.mj_w * 0.5 : (self.mj_w * 0.5 - 100);
self.arrowImage.center = CGPointMake(arrowX, self.mj_h * 0.5);
// 指示器
self.activityView.center = self.arrowImage.center;
}
#pragma mark - 公共方法
#pragma mark 设置状态
- (void)setState:(MJRefreshHeaderState)state
{
if (self.state == state) return;
// 旧状态
MJRefreshHeaderState oldState = self.state;
switch (state) {
case MJRefreshHeaderStateIdle: {
if (oldState == MJRefreshHeaderStateRefreshing) {
self.arrowImage.transform = CGAffineTransformIdentity;
[UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
self.activityView.alpha = 0.0;
} completion:^(BOOL finished) {
self.arrowImage.alpha = 1.0;
self.activityView.alpha = 1.0;
[self.activityView stopAnimating];
}];
} else {
[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
self.arrowImage.transform = CGAffineTransformIdentity;
}];
}
break;
}
case MJRefreshHeaderStatePulling: {
[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
self.arrowImage.transform = CGAffineTransformMakeRotation(0.000001 - M_PI);
}];
break;
}
case MJRefreshHeaderStateRefreshing: {
[self.activityView startAnimating];
self.arrowImage.alpha = 0.0;
break;
}
default:
break;
}
// super里面有回调,应该在最后面调用
[super setState:state];
}
@end
@@ -0,0 +1,23 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// UIScrollView+Extension.h
// MJRefreshExample
//
// Created by MJ Lee on 14-5-28.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIScrollView (MJExtension)
@property (assign, nonatomic) CGFloat mj_insetT;
@property (assign, nonatomic) CGFloat mj_insetB;
@property (assign, nonatomic) CGFloat mj_insetL;
@property (assign, nonatomic) CGFloat mj_insetR;
@property (assign, nonatomic) CGFloat mj_offsetX;
@property (assign, nonatomic) CGFloat mj_offsetY;
@property (assign, nonatomic) CGFloat mj_contentSizeW;
@property (assign, nonatomic) CGFloat mj_contentSizeH;
@end
@@ -0,0 +1,108 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// UIScrollView+Extension.m
// MJRefreshExample
//
// Created by MJ Lee on 14-5-28.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "UIScrollView+MJExtension.h"
@implementation UIScrollView (MJExtension)
- (void)setMj_insetT:(CGFloat)mj_insetT
{
UIEdgeInsets inset = self.contentInset;
inset.top = mj_insetT;
self.contentInset = inset;
}
- (CGFloat)mj_insetT
{
return self.contentInset.top;
}
- (void)setMj_insetB:(CGFloat)mj_insetB
{
UIEdgeInsets inset = self.contentInset;
inset.bottom = mj_insetB;
self.contentInset = inset;
}
- (CGFloat)mj_insetB
{
return self.contentInset.bottom;
}
- (void)setMj_insetL:(CGFloat)mj_insetL
{
UIEdgeInsets inset = self.contentInset;
inset.left = mj_insetL;
self.contentInset = inset;
}
- (CGFloat)mj_insetL
{
return self.contentInset.left;
}
- (void)setMj_insetR:(CGFloat)mj_insetR
{
UIEdgeInsets inset = self.contentInset;
inset.right = mj_insetR;
self.contentInset = inset;
}
- (CGFloat)mj_insetR
{
return self.contentInset.right;
}
- (void)setMj_offsetX:(CGFloat)mj_offsetX
{
CGPoint offset = self.contentOffset;
offset.x = mj_offsetX;
self.contentOffset = offset;
}
- (CGFloat)mj_offsetX
{
return self.contentOffset.x;
}
- (void)setMj_offsetY:(CGFloat)mj_offsetY
{
CGPoint offset = self.contentOffset;
offset.y = mj_offsetY;
self.contentOffset = offset;
}
- (CGFloat)mj_offsetY
{
return self.contentOffset.y;
}
- (void)setMj_contentSizeW:(CGFloat)mj_contentSizeW
{
CGSize size = self.contentSize;
size.width = mj_contentSizeW;
self.contentSize = size;
}
- (CGFloat)mj_contentSizeW
{
return self.contentSize.width;
}
- (void)setMj_contentSizeH:(CGFloat)mj_contentSizeH
{
CGSize size = self.contentSize;
size.height = mj_contentSizeH;
self.contentSize = size;
}
- (CGFloat)mj_contentSizeH
{
return self.contentSize.height;
}
@end
@@ -0,0 +1,222 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// UIScrollView+MJRefresh.h
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
// 给ScrollView增加下拉刷新、上拉刷新的功能
#import <UIKit/UIKit.h>
#import "MJRefreshConst.h"
@class MJRefreshGifHeader, MJRefreshLegendHeader, MJRefreshHeader;
@class MJRefreshGifFooter, MJRefreshLegendFooter, MJRefreshFooter;
@interface UIScrollView (MJRefresh)
#pragma mark - 访问下拉刷新控件
/** 下拉刷新控件 */
@property (strong, nonatomic, readonly) MJRefreshHeader *header;
/** gif功能的下拉刷新控件 */
@property (nonatomic, readonly) MJRefreshGifHeader *gifHeader;
/** 传统的下拉刷新控件 */
@property (nonatomic, readonly) MJRefreshLegendHeader *legendHeader;
#pragma mark - 添加下拉刷新控件
/**
* 添加一个传统的下拉刷新控件
*
* @param block 进入刷新状态就会自动调用这个block
*/
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block;
/**
* 添加一个传统的下拉刷新控件
*
* @param block 进入刷新状态就会自动调用这个block
* @param dateKey 用来记录刷新时间的key
*/
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey;
/**
* 添加一个传统的下拉刷新控件
*
* @param target 进入刷新状态就会自动调用target对象的action方法
* @param action 进入刷新状态就会自动调用target对象的action方法
*/
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
/**
* 添加一个传统的下拉刷新控件
*
* @param target 进入刷新状态就会自动调用target对象的action方法
* @param action 进入刷新状态就会自动调用target对象的action方法
* @param dateKey 用来记录刷新时间的key
*/
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey;
/**
* 添加一个gif图片的下拉刷新控件
*
* @param block 进入刷新状态就会自动调用这个block
*/
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block;
/**
* 添加一个gif图片的下拉刷新控件
*
* @param block 进入刷新状态就会自动调用这个block
* @param dateKey 用来记录刷新时间的key
*/
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey;
/**
* 添加一个gif图片的下拉刷新控件
*
* @param target 进入刷新状态就会自动调用target对象的action方法
* @param action 进入刷新状态就会自动调用target对象的action方法
*/
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
/**
* 添加一个gif图片的下拉刷新控件
*
* @param target 进入刷新状态就会自动调用target对象的action方法
* @param action 进入刷新状态就会自动调用target对象的action方法
* @param dateKey 用来记录刷新时间的key
*/
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey;
#pragma mark - 移除下拉刷新控件
/**
* 移除下拉刷新控件
*/
- (void)removeHeader;
#pragma mark - 访问上拉刷新控件
/** 上拉刷新控件 */
@property (strong, nonatomic, readonly) MJRefreshFooter *footer;
/** gif功能的上拉刷新控件 */
@property (nonatomic, readonly) MJRefreshGifFooter *gifFooter;
/** 传统的上拉刷新控件 */
@property (nonatomic, readonly) MJRefreshLegendFooter *legendFooter;
#pragma mark - 添加上拉刷新控件
/**
* 添加一个传统的上拉刷新控件
*
* @param block 进入刷新状态就会自动调用这个block
*/
- (MJRefreshLegendFooter *)addLegendFooterWithRefreshingBlock:(void (^)())block;
/**
* 添加一个传统的上拉刷新控件
*
* @param target 进入刷新状态就会自动调用target对象的action方法
* @param action 进入刷新状态就会自动调用target对象的action方法
*/
- (MJRefreshLegendFooter *)addLegendFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
/**
* 添加一个gif图片的上拉刷新控件
*
* @param block 进入刷新状态就会自动调用这个block
*/
- (MJRefreshGifFooter *)addGifFooterWithRefreshingBlock:(void (^)())block;
/**
* 添加一个gif图片的上拉刷新控件
*
* @param target 进入刷新状态就会自动调用target对象的action方法
* @param action 进入刷新状态就会自动调用target对象的action方法
*/
- (MJRefreshGifFooter *)addGifFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
#pragma mark - 移除上拉刷新控件
/**
* 移除上拉刷新控件
*/
- (void)removeFooter;
@end
#pragma mark - 1.0.0版本以前的接口
@interface UIScrollView(MJRefreshDeprecated)
#pragma mark - 下拉刷新
/**
* 添加一个下拉刷新头部控件
*
* @param callback 回调
*/
- (void)addHeaderWithCallback:(void (^)())callback MJDeprecated("建议使用addLegendHeaderWithRefreshingBlock:");
/**
* 添加一个下拉刷新头部控件
*
* @param callback 回调
* @param dateKey 刷新时间保存的key值
*/
- (void)addHeaderWithCallback:(void (^)())callback dateKey:(NSString*)dateKey MJDeprecated("建议使用addLegendHeaderWithRefreshingBlock:dateKey:");
/**
* 添加一个下拉刷新头部控件
*
* @param target 目标
* @param action 回调方法
*/
- (void)addHeaderWithTarget:(id)target action:(SEL)action MJDeprecated("建议使用addLegendHeaderWithRefreshingTarget:refreshingAction:");
/**
* 添加一个下拉刷新头部控件
*
* @param target 目标
* @param action 回调方法
* @param dateKey 刷新时间保存的key值
*/
- (void)addHeaderWithTarget:(id)target action:(SEL)action dateKey:(NSString*)dateKey MJDeprecated("建议使用addLegendHeaderWithRefreshingTarget:refreshingAction:dateKey:");
/**
* 主动让下拉刷新头部控件进入刷新状态
*/
- (void)headerBeginRefreshing MJDeprecated("建议使用[self.tableView.header beginRefreshing]");
/**
* 让下拉刷新头部控件停止刷新状态
*/
- (void)headerEndRefreshing MJDeprecated("建议使用[self.tableView.header endRefreshing]");
/**
* 下拉刷新头部控件的可见性
*/
@property (nonatomic, assign, getter = isHeaderHidden) BOOL headerHidden MJDeprecated("建议使用self.tableView.header.hidden");
/**
* 是否正在下拉刷新
*/
@property (nonatomic, assign, readonly, getter = isHeaderRefreshing) BOOL headerRefreshing MJDeprecated("建议使用self.tableView.header.isRefreshing");
#pragma mark - 上拉刷新
/**
* 添加一个上拉刷新尾部控件
*
* @param callback 回调
*/
- (void)addFooterWithCallback:(void (^)())callback MJDeprecated("建议使用addLegendFooterWithRefreshingBlock:");
/**
* 添加一个上拉刷新尾部控件
*
* @param target 目标
* @param action 回调方法
*/
- (void)addFooterWithTarget:(id)target action:(SEL)action MJDeprecated("建议使用addLegendFooterWithRefreshingTarget:refreshingAction:");
/**
* 主动让上拉刷新尾部控件进入刷新状态
*/
- (void)footerBeginRefreshing MJDeprecated("建议使用[self.tableView.footer beginRefreshing]");
/**
* 让上拉刷新尾部控件停止刷新状态
*/
- (void)footerEndRefreshing MJDeprecated("建议使用[self.tableView.footer endRefreshing]");
/**
* 上拉刷新头部控件的可见性
*/
@property (nonatomic, assign, getter = isFooterHidden) BOOL footerHidden MJDeprecated("建议使用self.tableView.footer.hidden");
/**
* 是否正在上拉刷新
*/
@property (nonatomic, assign, readonly, getter = isFooterRefreshing) BOOL footerRefreshing MJDeprecated("建议使用self.tableView.footer.isRefreshing");
@end
@@ -0,0 +1,394 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// UIScrollView+MJRefresh.m
// MJRefreshExample
//
// Created by MJ Lee on 15/3/4.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "UIScrollView+MJRefresh.h"
#import "MJRefreshGifHeader.h"
#import "MJRefreshLegendHeader.h"
#import "MJRefreshGifFooter.h"
#import "MJRefreshLegendFooter.h"
#import <objc/runtime.h>
@implementation UIScrollView (MJRefresh)
#pragma mark - 下拉刷新
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey
{
MJRefreshLegendHeader *header = [self addLegendHeader];
header.refreshingBlock = block;
header.dateKey = dateKey;
return header;
}
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey
{
MJRefreshLegendHeader *header = [self addLegendHeader];
header.refreshingTarget = target;
header.refreshingAction = action;
header.dateKey = dateKey;
return header;
}
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action
{
return [self addLegendHeaderWithRefreshingTarget:target refreshingAction:action dateKey:nil];
}
- (MJRefreshLegendHeader *)addLegendHeaderWithRefreshingBlock:(void (^)())block
{
return [self addLegendHeaderWithRefreshingBlock:block dateKey:nil];
}
- (MJRefreshLegendHeader *)addLegendHeader
{
MJRefreshLegendHeader *header = [[MJRefreshLegendHeader alloc] init];
self.header = header;
return header;
}
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block dateKey:(NSString *)dateKey
{
MJRefreshGifHeader *header = [self addGifHeader];
header.refreshingBlock = block;
header.dateKey = dateKey;
return header;
}
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action dateKey:(NSString *)dateKey
{
MJRefreshGifHeader *header = [self addGifHeader];
header.refreshingTarget = target;
header.refreshingAction = action;
header.dateKey = dateKey;
return header;
}
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingBlock:(void (^)())block
{
return [self addGifHeaderWithRefreshingBlock:block dateKey:nil];
}
- (MJRefreshGifHeader *)addGifHeaderWithRefreshingTarget:(id)target refreshingAction:(SEL)action
{
return [self addGifHeaderWithRefreshingTarget:target refreshingAction:action dateKey:nil];
}
- (MJRefreshGifHeader *)addGifHeader
{
MJRefreshGifHeader *header = [[MJRefreshGifHeader alloc] init];
self.header = header;
return header;
}
- (void)removeHeader
{
self.header = nil;
}
#pragma mark - Property Methods
#pragma mark gifHeader
- (MJRefreshGifHeader *)gifHeader
{
if ([self.header isKindOfClass:[MJRefreshGifHeader class]]) {
return (MJRefreshGifHeader *)self.header;
}
return nil;
}
#pragma mark legendHeader
- (MJRefreshLegendHeader *)legendHeader
{
if ([self.header isKindOfClass:[MJRefreshLegendHeader class]]) {
return (MJRefreshLegendHeader *)self.header;
}
return nil;
}
#pragma mark header
static char MJRefreshHeaderKey;
- (void)setHeader:(MJRefreshHeader *)header
{
if (header != self.header) {
[self.header removeFromSuperview];
[self willChangeValueForKey:@"header"];
objc_setAssociatedObject(self, &MJRefreshHeaderKey,
header,
OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"header"];
[self addSubview:header];
}
}
- (MJRefreshHeader *)header
{
return objc_getAssociatedObject(self, &MJRefreshHeaderKey);
}
#pragma mark - 上拉刷新
- (MJRefreshLegendFooter *)addLegendFooterWithRefreshingBlock:(void (^)())block
{
MJRefreshLegendFooter *footer = [self addLegendFooter];
footer.refreshingBlock = block;
return footer;
}
- (MJRefreshLegendFooter *)addLegendFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action
{
MJRefreshLegendFooter *footer = [self addLegendFooter];
footer.refreshingTarget = target;
footer.refreshingAction = action;
return footer;
}
- (MJRefreshLegendFooter *)addLegendFooter
{
MJRefreshLegendFooter *footer = [[MJRefreshLegendFooter alloc] init];
self.footer = footer;
return footer;
}
- (MJRefreshGifFooter *)addGifFooterWithRefreshingBlock:(void (^)())block
{
MJRefreshGifFooter *footer = [self addGifFooter];
footer.refreshingBlock = block;
return footer;
}
- (MJRefreshGifFooter *)addGifFooterWithRefreshingTarget:(id)target refreshingAction:(SEL)action
{
MJRefreshGifFooter *footer = [self addGifFooter];
footer.refreshingTarget = target;
footer.refreshingAction = action;
return footer;
}
- (MJRefreshGifFooter *)addGifFooter
{
MJRefreshGifFooter *footer = [[MJRefreshGifFooter alloc] init];
self.footer = footer;
return footer;
}
- (void)removeFooter
{
self.footer = nil;
}
static char MJRefreshFooterKey;
- (void)setFooter:(MJRefreshFooter *)footer
{
if (footer != self.footer) {
[self.footer removeFromSuperview];
[self willChangeValueForKey:@"footer"];
objc_setAssociatedObject(self, &MJRefreshFooterKey,
footer,
OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"footer"];
[self addSubview:footer];
}
}
- (MJRefreshGifFooter *)gifFooter
{
if ([self.footer isKindOfClass:[MJRefreshGifFooter class]]) {
return (MJRefreshGifFooter *)self.footer;
}
return nil;
}
- (MJRefreshLegendFooter *)legendFooter
{
if ([self.footer isKindOfClass:[MJRefreshLegendFooter class]]) {
return (MJRefreshLegendFooter *)self.footer;
}
return nil;
}
- (MJRefreshFooter *)footer
{
return objc_getAssociatedObject(self, &MJRefreshFooterKey);
}
#pragma mark - swizzle
+ (void)load
{
Method method1 = class_getInstanceMethod([self class], NSSelectorFromString(@"dealloc"));
Method method2 = class_getInstanceMethod([self class], @selector(deallocSwizzle));
method_exchangeImplementations(method1, method2);
}
- (void)deallocSwizzle
{
[self removeFooter];
[self removeHeader];
[self deallocSwizzle];
}
@end
#pragma mark - 1.0.0版本以前的接口
@implementation UIScrollView(MJRefreshDeprecated)
#pragma mark - 下拉刷新
/**
* 添加一个下拉刷新头部控件
*
* @param callback 回调
*/
- (void)addHeaderWithCallback:(void (^)())callback
{
[self addHeaderWithCallback:callback dateKey:nil];
}
/**
* 添加一个下拉刷新头部控件
*
* @param callback 回调
* @param dateKey 刷新时间保存的key值
*/
- (void)addHeaderWithCallback:(void (^)())callback dateKey:(NSString*)dateKey
{
[self addLegendHeader];
self.header.dateKey = dateKey;
self.header.refreshingBlock = callback;
}
/**
* 添加一个下拉刷新头部控件
*
* @param target 目标
* @param action 回调方法
*/
- (void)addHeaderWithTarget:(id)target action:(SEL)action
{
[self addHeaderWithTarget:target action:action dateKey:nil];
}
/**
* 添加一个下拉刷新头部控件
*
* @param target 目标
* @param action 回调方法
* @param dateKey 刷新时间保存的key值
*/
- (void)addHeaderWithTarget:(id)target action:(SEL)action dateKey:(NSString*)dateKey
{
[self addLegendHeader];
self.header.dateKey = dateKey;
[self.header setRefreshingTarget:target refreshingAction:action];
}
/**
* 主动让下拉刷新头部控件进入刷新状态
*/
- (void)headerBeginRefreshing
{
[self.header beginRefreshing];
}
/**
* 让下拉刷新头部控件停止刷新状态
*/
- (void)headerEndRefreshing
{
[self.header endRefreshing];
}
/**
* 下拉刷新头部控件的可见性
*/
- (void)setHeaderHidden:(BOOL)headerHidden
{
self.header.hidden = headerHidden;
}
- (BOOL)isHeaderHidden
{
return self.header.isHidden;
}
/**
* 是否正在下拉刷新
*/
- (BOOL)isHeaderRefreshing
{
return self.header.isRefreshing;
}
#pragma mark - 上拉刷新
/**
* 添加一个上拉刷新尾部控件
*
* @param callback 回调
*/
- (void)addFooterWithCallback:(void (^)())callback
{
[self addLegendFooter];
self.footer.refreshingBlock = callback;
}
/**
* 添加一个上拉刷新尾部控件
*
* @param target 目标
* @param action 回调方法
*/
- (void)addFooterWithTarget:(id)target action:(SEL)action
{
[self addLegendFooter];
[self.footer setRefreshingTarget:target refreshingAction:action];
}
/**
* 主动让上拉刷新尾部控件进入刷新状态
*/
- (void)footerBeginRefreshing
{
[self.footer beginRefreshing];
}
/**
* 让上拉刷新尾部控件停止刷新状态
*/
- (void)footerEndRefreshing
{
[self.footer endRefreshing];
}
/**
* 上拉刷新头部控件的可见性
*/
- (void)setFooterHidden:(BOOL)footerHidden
{
self.footer.hidden = footerHidden;
}
- (BOOL)isFooterHidden
{
return self.footer.isHidden;
}
/**
* 是否正在上拉刷新
*/
- (BOOL)isFooterRefreshing
{
return self.footer.isRefreshing;
}
@end
@@ -0,0 +1,19 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// UIView+Extension.h
// MJRefreshExample
//
// Created by MJ Lee on 14-5-28.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (MJExtension)
@property (assign, nonatomic) CGFloat mj_x;
@property (assign, nonatomic) CGFloat mj_y;
@property (assign, nonatomic) CGFloat mj_w;
@property (assign, nonatomic) CGFloat mj_h;
@property (assign, nonatomic) CGSize mj_size;
@property (assign, nonatomic) CGPoint mj_origin;
@end
@@ -0,0 +1,84 @@
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
// UIView+Extension.m
// MJRefreshExample
//
// Created by MJ Lee on 14-5-28.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "UIView+MJExtension.h"
@implementation UIView (MJExtension)
- (void)setMj_x:(CGFloat)mj_x
{
CGRect frame = self.frame;
frame.origin.x = mj_x;
self.frame = frame;
}
- (CGFloat)mj_x
{
return self.frame.origin.x;
}
- (void)setMj_y:(CGFloat)mj_y
{
CGRect frame = self.frame;
frame.origin.y = mj_y;
self.frame = frame;
}
- (CGFloat)mj_y
{
return self.frame.origin.y;
}
- (void)setMj_w:(CGFloat)mj_w
{
CGRect frame = self.frame;
frame.size.width = mj_w;
self.frame = frame;
}
- (CGFloat)mj_w
{
return self.frame.size.width;
}
- (void)setMj_h:(CGFloat)mj_h
{
CGRect frame = self.frame;
frame.size.height = mj_h;
self.frame = frame;
}
- (CGFloat)mj_h
{
return self.frame.size.height;
}
- (void)setMj_size:(CGSize)mj_size
{
CGRect frame = self.frame;
frame.size = mj_size;
self.frame = frame;
}
- (CGSize)mj_size
{
return self.frame.size;
}
- (void)setMj_origin:(CGPoint)mj_origin
{
CGRect frame = self.frame;
frame.origin = mj_origin;
self.frame = frame;
}
- (CGPoint)mj_origin
{
return self.frame.origin;
}
@end