diff --git a/Yep.xcodeproj/project.pbxproj b/Yep.xcodeproj/project.pbxproj index 970f01b2..2bd9ac43 100644 --- a/Yep.xcodeproj/project.pbxproj +++ b/Yep.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 0A02E46F1AC9208A00235DBF /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A02E46E1AC9208A00235DBF /* libxml2.dylib */; }; + 0A0DE3C21ADD94A5006A4AAE /* YepRefreshView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A0DE3C11ADD94A5006A4AAE /* YepRefreshView.swift */; }; 0A271FD71ACA055400822DFC /* YepAudioService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A271FD61ACA055400822DFC /* YepAudioService.swift */; }; 0A3E60601ACCA9C0003DC853 /* String+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3E605F1ACCA9C0003DC853 /* String+Yep.swift */; }; 0A3E60671ACCAECE003DC853 /* YepLocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3E60661ACCAECE003DC853 /* YepLocationService.swift */; }; @@ -123,6 +124,7 @@ /* Begin PBXFileReference section */ 0A02E46E1AC9208A00235DBF /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; }; + 0A0DE3C11ADD94A5006A4AAE /* YepRefreshView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YepRefreshView.swift; sourceTree = ""; }; 0A271FD61ACA055400822DFC /* YepAudioService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepAudioService.swift; path = Services/YepAudioService.swift; sourceTree = ""; }; 0A3E605F1ACCA9C0003DC853 /* String+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "String+Yep.swift"; path = "Extensions/String+Yep.swift"; sourceTree = ""; }; 0A3E60661ACCAECE003DC853 /* YepLocationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepLocationService.swift; path = Services/YepLocationService.swift; sourceTree = ""; }; @@ -268,6 +270,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0A0DE3C31ADD94A8006A4AAE /* RefreshView */ = { + isa = PBXGroup; + children = ( + 0A0DE3C11ADD94A5006A4AAE /* YepRefreshView.swift */, + ); + name = RefreshView; + sourceTree = ""; + }; 0A3E60631ACCAC02003DC853 /* NSDate+TimeAgo */ = { isa = PBXGroup; children = ( @@ -440,6 +450,7 @@ 5023DE391AB6979C00B3EE96 /* Views */ = { isa = PBXGroup; children = ( + 0A0DE3C31ADD94A8006A4AAE /* RefreshView */, 50A9D4581ACD3943000B2599 /* AudioWaves */, 5023DE3A1AB697A700B3EE96 /* Cells */, 502AE5221AB71C82005BD199 /* Buttons */, @@ -1000,6 +1011,7 @@ 502AE54E1AB93175005BD199 /* ProfileHeaderCell.swift in Sources */, 50553F8F1ADB8BA200F80B59 /* ChatSectionDateCell.swift in Sources */, 0ABF3EA71ACE60D5001E76ED /* Waver.swift in Sources */, + 0A0DE3C21ADD94A5006A4AAE /* YepRefreshView.swift in Sources */, 502AE5381AB866E3005BD199 /* LoginVerifyMobileViewController.swift in Sources */, 503CAB431AC00CB100DFE830 /* ConversationViewController.swift in Sources */, 50553F931ADBA50600F80B59 /* NSDate+Yep.swift in Sources */, diff --git a/Yep/YepRefreshView.swift b/Yep/YepRefreshView.swift new file mode 100644 index 00000000..484911a7 --- /dev/null +++ b/Yep/YepRefreshView.swift @@ -0,0 +1,199 @@ +// +// YepRefreshView.swift +// YepPullRefresh +// +// Created by kevinzhow on 15/4/14. +// Copyright (c) 2015年 kevinzhow. All rights reserved. +// + +import UIKit + +import QuartzCore + +class YepShape: CAShapeLayer { + + func setupWithWidth(width:CGFloat, height:CGFloat) { + var rectanglePath = UIBezierPath() + + let bottomGap = height/CGFloat(tan(M_PI/3)) + let bottomWidth = width - 2*bottomGap + let gapSideLenth = bottomGap*2 + + rectanglePath.moveToPoint(CGPointMake(0, 0)) + rectanglePath.addLineToPoint(CGPointMake(width, 0)) + rectanglePath.addLineToPoint(CGPointMake(width - bottomGap, height)) + rectanglePath.addLineToPoint(CGPointMake(width - bottomWidth - bottomGap, height)) + rectanglePath.closePath() + + // Create initial shape of the view + self.path = rectanglePath.CGPath + self.fillColor = UIColor(red:0.33, green:0.71, blue:0.98, alpha:1).CGColor + } + + func setupFlipWithWidth(width:CGFloat, height:CGFloat) { + var rectanglePath = UIBezierPath() + + let bottomGap = height/CGFloat(tan(M_PI/3)) + let bottomWidth = width - 2*bottomGap + let gapSideLenth = bottomGap*2 + + rectanglePath.moveToPoint(CGPointMake(bottomGap, 0)) + rectanglePath.addLineToPoint(CGPointMake(bottomGap+bottomWidth, 0)) + rectanglePath.addLineToPoint(CGPointMake(bottomGap+bottomWidth+bottomGap, height)) + rectanglePath.addLineToPoint(CGPointMake(0, height)) + rectanglePath.closePath() + + // Create initial shape of the view + self.path = rectanglePath.CGPath + self.fillColor = UIColor(red:0.33, green:0.71, blue:0.98, alpha:1).CGColor + } +} + + +class YepRefreshView: UIView { + + var shapes = [YepShape]() + + var originShapesPosition = [CGPoint]() + + var ramdonShapesPosition = [CGPoint]() + + var refreshing = false + + static let shapeWidth:CGFloat = 15 + + static let shapeHeight:CGFloat = 4.0 + + override init(frame: CGRect) { + super.init(frame: frame) + + var x = YepRefreshView.shapeHeight/CGFloat(tan(M_PI/3)) + var bottomWidth = YepRefreshView.shapeWidth - 2*x + var shape = YepShape() + var shape2 = YepShape() + var shape3 = YepShape() + var shape5 = YepShape() + var shape4 = YepShape() + var shape6 = YepShape() + + shapes = [shape,shape2,shape3,shape4,shape5,shape6] + + shape.setupWithWidth(YepRefreshView.shapeWidth, height: YepRefreshView.shapeHeight) + shape.position = CGPointMake(shape.position.x, shape.position.y+YepRefreshView.shapeHeight) + + shape2.setupFlipWithWidth(YepRefreshView.shapeWidth, height: YepRefreshView.shapeHeight) + + shape3.setupWithWidth(YepRefreshView.shapeWidth, height: YepRefreshView.shapeHeight) + shape3.position = CGPointMake(shape3.position.x, shape3.position.y+YepRefreshView.shapeHeight) + + shape4.setupFlipWithWidth(YepRefreshView.shapeWidth, height: YepRefreshView.shapeHeight) + + shape5.setupWithWidth(YepRefreshView.shapeWidth, height: YepRefreshView.shapeHeight) + shape5.position = CGPointMake(shape5.position.x, shape5.position.y+YepRefreshView.shapeHeight) + + shape6.setupFlipWithWidth(YepRefreshView.shapeWidth, height: YepRefreshView.shapeHeight) + + originShapesPosition = [shape.position, shape2.position, shape3.position, shape4.position, shape5.position, shape6.position] + + ramdonShapesPosition = [CGPointMake(-110, -230.0), CGPointMake(-70, -110.0), CGPointMake(180, -30.0), CGPointMake(140, -220.0), CGPointMake(-140, 230.0), CGPointMake(-220, 40.0)] + + for (index, shape) in enumerate(shapes) { + shape.opacity = 0.0 + shape.position = ramdonShapesPosition[index] + } + + var leafShape1 = CAShapeLayer() + leafShape1.frame = CGRectMake(-YepRefreshView.shapeWidth/2.0 + frame.width/2.0, -YepRefreshView.shapeHeight + frame.height/2.0, YepRefreshView.shapeWidth, YepRefreshView.shapeHeight*2) + leafShape1.addSublayer(shape) + leafShape1.addSublayer(shape2) + self.layer.addSublayer(leafShape1) + + var leafShape2 = CAShapeLayer() + leafShape2.frame = CGRectMake(-YepRefreshView.shapeWidth/2.0 + frame.width/2.0, -YepRefreshView.shapeHeight + frame.height/2.0, YepRefreshView.shapeWidth, YepRefreshView.shapeHeight*2) + leafShape2.addSublayer(shape3) + leafShape2.addSublayer(shape4) + self.layer.addSublayer(leafShape2) + + var leafShape3 = CAShapeLayer() + leafShape3.frame = CGRectMake(-YepRefreshView.shapeWidth/2.0 + frame.width/2.0, -YepRefreshView.shapeHeight + frame.height/2.0, YepRefreshView.shapeWidth, YepRefreshView.shapeHeight*2) + leafShape3.addSublayer(shape5) + leafShape3.addSublayer(shape6) + self.layer.addSublayer(leafShape3) + + leafShape1.anchorPoint = CGPoint(x: 0, y: 0.5) + leafShape2.anchorPoint = CGPoint(x: 0, y: 0.5) + leafShape3.anchorPoint = CGPoint(x: 0, y: 0.5) + leafShape1.transform = CATransform3DMakeRotation(CGFloat(-M_PI/6), 0.0, 0.0, 1.0) + leafShape2.transform = CATransform3DMakeRotation(CGFloat(M_PI/2), 0.0, 0.0, 1.0) + leafShape3.transform = CATransform3DMakeRotation(CGFloat(-(M_PI)+M_PI/6), 0.0, 0.0, 1.0) + + } + + func beginFlik() { + + if !refreshing { + refreshing = true + + for (index, shape) in enumerate(shapes) { + shape.opacity = 1.0 + let animation = CABasicAnimation(keyPath: "opacity") + animation.fromValue = 1.0 + animation.toValue = 0.5 + animation.repeatCount = 1000 + animation.autoreverses = true + animation.fillMode = kCAFillModeBoth + animation.timingFunction = CAMediaTimingFunction(name: "linear") + + var delay:Double = 0 + var timeScale:Double = 3 + + if index == 0 || index == 5 { + + delay = 0.1*timeScale + } + + if index == 1 || index == 2 { + //2 + delay = 0.05*timeScale + } + + + animation.duration = 0.09*timeScale + animation.beginTime = CACurrentMediaTime() + delay + + shape.addAnimation(animation, forKey: "flip") + } + + } + } + + func updatePullRefreshWithProgress(progress: CGFloat) { + println("\(progress)") + + if (!refreshing) { + + if progress == 0.0 { + beginFlik() + } + + for (index, shape) in enumerate(shapes) { + + shape.opacity = 1 - Float(progress) + shape.position = CGPointMake(originShapesPosition[index].x+ramdonShapesPosition[index].x*progress, ramdonShapesPosition[index].y*progress+originShapesPosition[index].y) + + } + } + + } + + func stopFlik() { + for (index, shape) in enumerate(shapes) { + shape.removeAnimationForKey("flip") + } + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +}