- (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