- (void)prepare
{
[super prepare];
// 设置普通状态的动画图片
NSMutableArray *idleImages = [NSMutableArray array];
for (NSUInteger i = 1; i<=60; i++) {
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_anim__000%zd", i]];
[idleImages addObject:image];
}
[self setImages:idleImages forState:MJRefreshStateIdle];
// 设置即将刷新状态的动画图片(一松开就会刷新的状态)
NSMutableArray *refreshingImages = [NSMutableArray array];
for (NSUInteger i = 1; i<=3; i++) {
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]];
[refreshingImages addObject:image];
}
[self setImages:refreshingImages forState:MJRefreshStatePulling];
// 设置正在刷新状态的动画图片
[self setImages:refreshingImages forState:MJRefreshStateRefreshing];
}
复制代码
下拉过程的渐变更画该怎么样?swift
使用像MJRefresh那样的逐帧图方案?须要跟UI要不少图,并且占用APP空间,不合适公司项目。除非要挂个很是复杂的动画图。markdown
给spinner加个progress属性?根据progress值来设置spinner红圆的的填充效果?发现spinner没有一个渐变过程,所以须要思考其余方案。ide
替代方案:在spinner上面盖一个环形的view,使用贝塞尔曲线来根据下拉距离来填充环形颜色。下拉距离小于临界点,显示环形view,隐藏spinner,开始动画的时候,隐藏环形view,显示spinner。oop
final class RefreshProgressView: UIView {
var progess: CGFloat = 0.0
private let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
seup(rect: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func seup(rect: CGRect) {
shapeLayer.frame = CGRect.init(x: 0, y: 0, width: rect.size.width, height: rect.size.height)
shapeLayer.lineWidth = XOSpinner.pathLineWidth
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.tkRed500.cgColor
shapeLayer.strokeEnd = 0
let center: CGPoint = CGPoint.init(x: rect.size.width/2, y: rect.size.height/2)
let bezierPath: UIBezierPath = UIBezierPath(arcCenter: center,
radius: (rect.size.width - XOSpinner.pathLineWidth)/2,
startAngle: CGFloat(0.5 * Double.pi),
endAngle: CGFloat(2.5 * Double.pi),
clockwise: true)
shapeLayer.path = bezierPath.cgPath
layer.addSublayer(shapeLayer)
}
func setProgress(value: CGFloat) {
progess = value
shapeLayer.strokeEnd = progess
}
}
复制代码
UIScrollView+Extension
中,使用运行时方式,添加headerRefresh
属性,这样就能在设置tableView的时候,添加下拉刷新的事件。(swift扩展中怎么用运行时添加属性:可参考Stored Properties In Swift Extensions)public var headerRefresh: XOPullDownToRefresh? {
get {
return objc_getAssociatedObject(self, &refreshHeaderKey) as? XOPullDownToRefresh
}
set(newValue) {
guard let newValue = newValue, newValue != headerRefresh else { return }
headerRefresh?.removeFromSuperview()
insertSubview(newValue, at: 0)
objc_setAssociatedObject(self, &refreshHeaderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
复制代码
tableView.headerRefresh = XOPullDownToRefresh(refreshingTarget: self, refreshingAction: #selector(refreshAction))
复制代码
XOPullDownToRefresh
中的scrollView
为所在的tableView
:override public func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
guard let newSuperview = newSuperview, let scrollView = newSuperview as? UIScrollView else { return }
removeObservers()
scrollView.alwaysBounceVertical = true
scrollViewOriginalInset = scrollView.contentInset
self.scrollView = scrollView
addObservers()
}
复制代码
拿到scrollView
之后,使用KVO监听他的contentOffset
,根据contentOffset.y
去设置不一样的状态:idle
,pulling
,willRefresh
, refreshing
。动画
下拉:位置未超过临界点,填充环圈颜色的过程。ui