{"id":818,"date":"2016-11-17T16:47:08","date_gmt":"2016-11-17T08:47:08","guid":{"rendered":"http:\/\/www.yusian.com\/blog\/?p=818"},"modified":"2016-11-17T16:48:26","modified_gmt":"2016-11-17T08:48:26","slug":"%e4%bb%bf%e6%b7%98%e5%ae%9d%e4%b8%8b%e6%8b%89%e5%88%b7%e6%96%b0%e6%95%88%e6%9e%9c%e5%9f%ba%e4%ba%8emjrefresh%e6%8e%a7%e4%bb%b6%e5%b0%81%e8%a3%85","status":"publish","type":"post","link":"https:\/\/www.yusian.com\/blog\/project\/2016\/11\/17\/164708818.html","title":{"rendered":"\u4eff\u6dd8\u5b9d\u4e0b\u62c9\u5237\u65b0\u6548\u679c(\u57fa\u4e8eMJRefresh\u63a7\u4ef6\u5c01\u88c5)"},"content":{"rendered":"<p><strong>1\u3001\u5148\u770b\u51e0\u5f20\u6548\u679c\u56fe<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-814\" style=\"font-size: 1rem;\" src=\"http:\/\/www.yusian.com\/blog\/wp-content\/uploads\/2016\/11\/Simulator-Screen-Shot-2016\u5e7411\u670817\u65e5-\u4e0b\u53483.45.32.png\" alt=\"simulator-screen-shot-2016%e5%b9%b411%e6%9c%8817%e6%97%a5-%e4%b8%8b%e5%8d%883-45-32\" width=\"200\" height=\"355\" \/><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-815\" src=\"http:\/\/www.yusian.com\/blog\/wp-content\/uploads\/2016\/11\/Simulator-Screen-Shot-2016\u5e7411\u670817\u65e5-\u4e0b\u53483.45.34.png\" alt=\"simulator-screen-shot-2016%e5%b9%b411%e6%9c%8817%e6%97%a5-%e4%b8%8b%e5%8d%883-45-34\" width=\"200\" height=\"355\" \/> <img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-816\" src=\"http:\/\/www.yusian.com\/blog\/wp-content\/uploads\/2016\/11\/Simulator-Screen-Shot-2016\u5e7411\u670817\u65e5-\u4e0b\u53483.45.36.png\" alt=\"simulator-screen-shot-2016%e5%b9%b411%e6%9c%8817%e6%97%a5-%e4%b8%8b%e5%8d%883-45-36\" width=\"200\" height=\"355\" \/><\/p>\n<p><strong>2\u3001\u8bbe\u8ba1\u601d\u8def<\/strong><\/p>\n<p>2.1\u3001\u5bf9\u6bd4MJRefresh\u4e0b\u62c9\u5237\u65b0\uff0c\u7c7b\u6dd8\u5b9d\u4e0b\u62c9\u6548\u679c\u53bb\u6389\u4e86\u4e0a\u4e0b\u8c03\u6362\u7bad\u5934\u53ca\u83ca\u82b1\u52a0\u8f7d\u6548\u679c\uff0c\u6dfb\u52a0\u4e86\u52a8\u6001\u753b\u5706\u5708\u7684\u8f68\u8ff9\u52a8\u753b\uff1b<!--more--><br \/>\n2.2\u3001\u7ebf\u4e0a\u6709\u5f88\u591a\u4e0b\u62c9\u5237\u65b0\u64ad\u653e\u52a8\u6001\u56fe\u7684\u52a8\u753b\u6548\u679c\uff0c\u90a3\u4e9b\u662f\u901a\u8fc7\u5e27\u52a8\u753b\u6765\u5b9e\u73b0\uff0c\u5728UIImageView\u4e2d\u591a\u5f20\u56fe\u7247\u5feb\u901f\u66ff\u6362\u5b9e\u73b0\uff1b<br \/>\n2.3\u3001\u4e0a\u8ff0\u6548\u679c\u4e0d\u80fd\u63a7\u5236\u52a8\u753b\u201c\u64ad\u653e\u8fdb\u5ea6\u201d\uff0c\u53ea\u80fd\u5faa\u73af\u64ad\u653e\uff0c\u65e0\u6cd5\u5b9e\u73b0\u7c7b\u6dd8\u5b9d\u201c\u753b\u5708\u201d\u6548\u679c\uff1b<br \/>\n2.4\u3001\u56fe\u7247\u65e0\u6cd5\u5b9e\u73b0\u5c31\u53ea\u80fd\u901a\u8fc7\u7a0b\u5e8f\u6765\u52a8\u6001\u753b\uff0c\u8fd9\u91cc\u6d89\u53ca\u5230\u4e00\u4e2a\u5173\u952e\u6027\u7684\u7c7bCAShapeLayer\uff1b<br \/>\n2.5\u3001CAShapeLayer\u6709\u4e24\u4e2a\u91cd\u8981\u5c5e\u6027strokeStart\u4e0estrokeEnd\uff0c\u8fd9\u4e24\u4e2a\u5c5e\u6027\u53ef\u4ee5\u5b9e\u73b0\u753b\u7ebf\u7684\u8d77\u59cb\u70b9\uff0c\u652f\u6301\u52a8\u753b\uff1b<br \/>\n2.6\u3001\u901a\u8fc7\u8d1d\u585e\u5c14\u66f2\u7ebf\u753b\u5706\u5708\u8f68\u8ff9\uff0c\u5c06\u8f68\u8ff9\u8d4b\u503c\u7ed9CAShapeLayer\uff1b<br \/>\n2.7\u3001\u5728UITableView\u4e0b\u62c9\u65f6\uff0c\u76d1\u542c\u4e0b\u62c9\u8ddd\u79bb(MJRefresh\u5df2\u5b9e\u73b0)\u8c03\u6574\u753b\u5708\u7684\u5f27\u5ea6\uff1b<br \/>\n2.8\u3001\u4e0b\u62c9\u5237\u65b0\u7684\u5176\u4ed6\u72b6\u6001\u901a\u8fc7\u4fee\u6539\u80cc\u666f\u5c0f\u56fe\u6807\u6765\u8f85\u52a9\u52a8\u753b\u6548\u679c\u3002<\/p>\n<p>3\u3001\u5173\u952e\u4ee3\u7801\uff1a<\/p>\n<pre lang=\"objc\" line=\"1\">\/\/\n\/\/  SARefreshHeader.m\n\/\/  fisher\n\/\/\n\/\/  Created by \u4f59\u897f\u5b89 on 16\/1\/29.\n\/\/  Copyright ? 2016\u5e74 Sian. All rights reserved.\n\/\/\n\n#define SAColor(rgb)  [UIColor colorWithRed:((rgb&0xFF0000)>>16)\/255.0 green:((rgb&0xFF00)>>8)\/255.0 blue:(rgb&0xFF)\/255.0 alpha:1.0]\n#import \"SARefreshHeader.h\"\n\n@implementation SARefreshHeader\n\n- (instancetype)initWithFrame:(CGRect)frame\n{\n    if (self = [super initWithFrame:frame]){\n        self.stateLabel.font = [UIFont systemFontOfSize:11];\n        self.stateLabel.textColor = [UIColor lightGrayColor];\n        self.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:11];\n        self.lastUpdatedTimeLabel.textColor = [UIColor lightGrayColor];\n        [self setTitle:@\"\u4e0b\u62c9\u5237\u65b0\" forState:MJRefreshStateIdle];\n        [self setTitle:@\"\u91ca\u653e\u5237\u65b0\" forState:MJRefreshStatePulling];\n        [self setTitle:@\"\u66f4\u65b0\u4e2d...\" forState:MJRefreshStateRefreshing];\n        [self setValue:@\"0\" forKeyPath:@\"arrowView.alpha\"];\n    }\n    return self;\n}\n\n\/\/ \u91cd\u65b0\u5e03\u5c40\u5b50\u63a7\u4ef6\n- (void)placeSubviews\n{\n    [super placeSubviews];\n    self.stateLabel.mj_y = MJRefreshHeaderHeight * 0.3;\n    self.lastUpdatedTimeLabel.mj_y = MJRefreshHeaderHeight * 0.65;\n    CGFloat refreshX = self.mj_w * 0.5 - 40;\n    CGFloat refreshY = MJRefreshHeaderHeight * 0.55;\n    self.refreshIcon.center = CGPointMake(refreshX, refreshY);\n}\n\n\/\/ RefreshState\u72b6\u6001\n- (void)setState:(MJRefreshState)state\n{\n    [super setState:state];\n    \/\/ \u9690\u85cf\u539f\u63a7\u4ef6LoadingView(\u5c0f\u83ca\u82b1\u6548\u679c)\n    [self setValue:@(YES) forKeyPath:@\"loadingView.hidden\"];\n    \/\/ \u4e0d\u52a8\u7684\u72b6\u6001\u7ed9\u51fa\u4e0d\u540c\u7684\u5e95\u90e8\u56fe\u6807\uff0c\u8f85\u52a9\u52a8\u753b\u6548\u679c\n    switch (state) {\n        case MJRefreshStateIdle:{       \/\/ \u4e0b\u62c9\u5237\u65b0\n            self.refreshIcon.image = [UIImage imageNamed:@\"icon_public_refresh_normal.png\"];\n        }break;\n        case MJRefreshStatePulling:{    \/\/ \u91ca\u653e\u5237\u65b0\n            self.refreshIcon.image = [UIImage imageNamed:@\"icon_public_refresh_highlight.png\"];\n        }break;\n        case MJRefreshStateRefreshing:{ \/\/ \u66f4\u65b0\u4e2d...\n            self.refreshIcon.image = [UIImage imageNamed:@\"icon_public_refresh_highlight.png\"];\n        }break;\n        default:break;\n    }\n}\n\n\/\/ KVO\u76d1\u542cScrollView ContentOffset\u503c\n- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change\n{\n    [super scrollViewContentOffsetDidChange:change];\n    \/\/ \u5f53\u4e0b\u62c9\u65f6\u6267\u884c\u76f8\u5173\u7ed8\u56fe\u52a8\u753b\n    if (self.state == MJRefreshStateIdle){\n        CGFloat distance = self.scrollView.contentOffset.y;\n        [self refreshWithDistance:distance];\n    }\n}\n\n\/\/ \u4e0b\u62c9\u8ddd\u79bb(\u6839\u636e\u8be5\u503c\u6765\u753b\u5706\u7684\u5f27\u5ea6\u5927\u5c0f)\n- (void)refreshWithDistance:(CGFloat)distance\n{\n    \/\/ \u4e0b\u62c9\u6700\u5927\u8ddd\u79bb\u4e3a\u5e38\u91cfMJRefreshHeaderHeight\uff0cstrokeEnd\u53d6\u503c0~1\n    CGFloat strokeEnd = distance \/ MJRefreshHeaderHeight;\n    if (strokeEnd < 0) strokeEnd *= -1;\n    self->_shapeLayer.strokeEnd = strokeEnd;\n    [self.shapeLayer setNeedsDisplay];\n}\n\n\/\/ \u4fee\u590d\u81ea\u52a8\u5237\u65b0\u65f6\u65e0\u6548\u679c\u7684Bug\n- (void)beginRefreshing\n{\n    [super beginRefreshing];\n    self.state = MJRefreshStateRefreshing;\n}\n\n#pragma mark - \u61d2\u52a0\u8f7d\u6210\u5458\u5c5e\u6027\n- (UIImageView *)refreshIcon\n{\n    if (self->_refreshIcon == nil){\n        UIImage *image = [UIImage imageNamed:@\"icon_public_refresh_normal.png\"];\n        self->_refreshIcon = [[UIImageView alloc] initWithImage:image];\n        [self addSubview:self->_refreshIcon];\n    }\n    return self->_refreshIcon;\n}\n\/\/ \u52a8\u753b\u56fe\u5c42\n- (CAShapeLayer *)shapeLayer\n{\n    if (self->_shapeLayer == nil){\n        \/\/ \u521b\u5efa\u5f62\u72b6\u56fe\u5c42\uff0c\u56fe\u5c42\u5927\u5c0f\u4e0e\u8986\u76d6\u7684\u5c0f\u56fe\u6807\u5927\u5c0f\u4e00\u81f4\n        self->_shapeLayer = [CAShapeLayer layer];\n        self->_shapeLayer.frame = self.refreshIcon.bounds;\n        \/\/  \u4ece0\u5ea6\u5f00\u59cb\u3001\u7ebf\u5ea61\u50cf\u7d20\u3001\u8fb9\u6846\u84dd\u8272\u3001\u5185\u586b\u5145\u65e0\u8272\n        self->_shapeLayer.strokeStart =  0;\n        self->_shapeLayer.lineWidth = 1.0f;\n        self->_shapeLayer.fillColor = [[UIColor clearColor] CGColor];\n        self->_shapeLayer.strokeColor = [SAColor(0x007AFF) CGColor];\n        \/\/ \u52a8\u753b\u8f68\u8ff9\u901a\u8fc7\u8d1d\u585e\u5c14\u66f2\u7ebf\u5b9e\u73b0\uff0c\u6162\u6162\u8c03\u51fa\u4e0e\u56fe\u6807\u91cd\u53e0\u7684\u8f68\u8ff9\n        CGFloat width = self.refreshIcon.bounds.size.width - 4;\n        CGRect rect = CGRectMake(2, 2, width, width);\n        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];\n        self->_shapeLayer.path = path.CGPath;\n        [self.refreshIcon.layer addSublayer:self->_shapeLayer];\n        \/\/ \u9006\u65f6\u949f\u65cb\u8f6c90\u5ea6\uff0c\u4f7f\u52a8\u753b\u4ece\u6700\u9876\u7aef\u5f00\u59cb\n        [self->_shapeLayer setTransform:CATransform3DMakeRotation(M_PI * -0.5, 0, 0, 1)];\n    }\n    return self->_shapeLayer;\n}\n@end<\/pre>\n<p><strong>4\u3001Demo\u4e0b\u8f7d<\/strong><a href=\"http:\/\/www.yusian.com\/blog\/wp-content\/uploads\/2016\/11\/SARefresh.zip\">\bSARefresh<\/a><\/p>\n<p>\u53c2\u8003\u94fe\u63a5\uff1a<a href=\"http:\/\/www.cocoachina.com\/ios\/20160711\/17007.html\" target=\"_blank\">http:\/\/www.cocoachina.com\/ios\/20160711\/17007.html<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1\u3001\u5148\u770b\u51e0\u5f20\u6548\u679c\u56fe 2\u3001\u8bbe\u8ba1\u601d\u8def 2.1\u3001\u5bf9\u6bd4MJRefresh\u4e0b\u62c9\u5237\u65b0\uff0c\u7c7b\u6dd8\u5b9d\u4e0b\u62c9\u6548\u679c\u53bb\u6389\u4e86\u4e0a\u4e0b\u8c03\u6362\u7bad\u5934\u53ca\u83ca\u82b1\u52a0\u8f7d\u6548\u679c\uff0c\u6dfb\u52a0\u4e86\u52a8\u6001\u753b\u5706\u5708\u7684\u8f68\u8ff9\u52a8\u753b\uff1b<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[20,15,17],"class_list":["post-818","post","type-post","status-publish","format-standard","hentry","category-project","tag-basics","tag-module","tag-skill"],"_links":{"self":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts\/818","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/comments?post=818"}],"version-history":[{"count":0,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts\/818\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/media?parent=818"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/categories?post=818"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/tags?post=818"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}