Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
iOS¿ª·¢Êµ¼ù£ºÓÃSwiftºÍCore Animatoin´´½¨Ô²ÐÎͼƬ¼ÓÔØ¶¯»­
 
×÷ÕߣºÁõÒ«Öù À´Ô´£ºCSDN ·¢²¼ÓÚ£º 2015-06-17
  3655  次浏览      30
 

ÕªÒª£º±¾ÎÄ×÷ÕßÔÚÎÄÕÂÖÐÏêϸµØ½²½âÁËÈçºÎʹÓÃSwiftºÍCore AnimatoinÀ´´´½¨½«Ô²Ðνø¶ÈָʾÆ÷ºÍÔ²Ðν¥ÏÖ¶¯»­Ïà½áºÏµÄ¶¯»­Ð§¹û¡£»ùÓÚ±¾½Ì³Ì£¬¿ª·¢Õß»¹¿ÉÒÔ¸ù¾Ý×Ô¼ºµÄÐèÇóºÍÉè¼ÆÃÀѧÀ´½øÒ»²½Î¢µ÷¶¯»­µÄʱ¼ä¡¢ÇúÏߺÍÑÕÉ«µÈ¡£

¼¸¸öÐÇÆÚ֮ǰ£¬Michael VillarÔÚMotionÊÔÑéÖд´½¨Ò»¸ö·Ç³£ÓÐȤµÄ¼ÓÔØ¶¯»­¡£ÏÂÃæµÄGIFͼƬչʾÕâ¸ö¼ÓÔØ¶¯»­£¬Ëü½«Ò»¸öÔ²Ðνø¶ÈָʾÆ÷ºÍÔ²Ðν¥ÏÖ¶¯»­½áºÏ¡£Õâ¸ö×éºÏµÄЧ¹ûÓÐȤ£¬¶ÀÒ»ÎÞ¶þºÍÓеãÃÔÈË¡£

Õâ¸ö½Ì³Ì½«»á½ÌÄãÈçºÎʹÓÃSwiftºÍCore AnimatoinÀ´ÖØÐ´´½¨Õâ¸öЧ¹û£¬ÈÃÎÒÃÇ¿ªÊ¼°É£¡

»ù´¡

Ê×ÏÈÏÂÔØÕâ¸ö½Ì³ÌµÄÆô¶¯ÏîÄ¿£¬È»ºó±àÒëºÍÔËÐС£¹ýÒ»»áÖ®ºó£¬ÄãÓ¦¸Ã¿´µ½Ò»¸ö¼òµ¥µÄimageÏÔʾ£º

Õâ¸öÆô¶¯ÏîÄ¿ÒѾ­Ô¤ÏÈÔÚÇ¡µ±µÄλÖý«viewsºÍ¼ÓÔØÂß¼­±àдºÃÁË¡£»¨Ò»·ÖÖÓÀ´ä¯ÀÀÀ´¿ìËÙÁ˽âÕâ¸öÏîÄ¿£»ÄÇÀïÓÐÒ»¸öViewController£¬ViewControllerÀïÓÐÒ»¸öÃüÃûΪCustomImageViewµÄUIImageView×ÓÀà, »¹ÓÐÒ»¸öSDWebImageµÄ·½·¨±»µ÷ÓÃÀ´¼ÓÔØimage¡£

Äã¿ÉÄÜ×¢Òâµ½µ±ÄãµÚÒ»´ÎÔËÐÐÕâ¸öappµÄʱºò£¬µ±imageÏÂÔØÊ±Õâ¸öappËÆºõ»áÔÝÍ£¼¸Ã룬Ȼºóimage»áÏÔʾÔÚÆÁÄ»¡£µ±È»£¬´Ë¿ÌûÓÐÔ²Ðνø¶ÈָʾÆ÷ - Ä㽫»áÔÚÕâ¸ö½Ì³ÌÖд´½¨Ëü£¡

Äã»áÔÚÁ½¸ö²½ÖèÖд´½¨Õâ¸ö¶¯»­£º

  1. Ô²Ðνø¶È¡£Ê×ÏÈ£¬Äã»á»­Ò»¸öÔ²Ðνø¶ÈָʾÆ÷£¬È»ºó¸ù¾ÝÏÂÔØ½ø¶ÈÀ´¸üÐÂËü¡£
  2. À©Õ¹Ô²ÐÎͼƬ¡£µÚ¶þ£¬Äã»áͨ¹ýÀ©Õ¹µÄÔ²Ðδ°¿ÚÀ´½ÒʾÏÂÔØÍ¼Æ¬¡£

½ô¸ú×ÅÏÂÃæ²½ÖèÀ´Öð²½ÊµÏÖ£¡

´´½¨Ô²ÐÎָʾÆ÷

ÏëһϹØÓÚ½ø¶ÈָʾÆ÷µÄ»ù±¾Éè¼Æ¡£Õâ¸öָʾÆ÷Ò»¿ªÊ¼ÊÇ¿ÕÀ´Õ¹Ê¾0%½ø¶È£¬È»ºóÖð½¥ÌîÂúÖ±µ½imageÍê³ÉÏÂÔØ¡£Í¨¹ýÉèÖÃCAShapeLayerµÄpathΪcircleÀ´ÊµÏÖÊÇÏ൱¼òµ¥¡£

×¢Ò⣺Èç¹ûÄã²»ÊìϤCAShapeLayer(»òCALayers)µÄ»ù±¾¸ÅÄ¿ÉÒԲ鿴Scott GardnerµÄCALayer in iOS with SwiftÎÄÕ¡£

Äã¿ÉÒÔͨ¹ýCAShapeLayerµÄstrokeStartºÍstrokeEndÊôÐÔÀ´¿ØÖÆ¿ªÊ¼ºÍ½áÊøÎ»ÖõÄÍâ¹Û¡£Í¨¹ý¸Ä±ästrokeEndµÄÖµÔÚ0µ½1Ö®¼ä£¬Äã¿ÉÒÔÇ¡µ±µØÌî³äÏÂÔØ½ø¶È¡£

ÈÃÎÒÃÇÊÔһϡ£Í¨¹ýiOS\Source\Cocoa Touch Class templateÀ´´´½¨Ò»¸öеÄÎļþ£¬ÎļþÃûΪCircularLoaderView¡£ÉèÖÃËüΪUIViewµÄ×ÓÀà¡£

µã»÷NextºÍCreate¡£ÐµÄ×ÓÀàUIView½«ÓÃÀ´±£´æ¶¯»­µÄ´úÂë¡£

´ò¿ªCircularLoaderView.swiftºÍÌí¼ÓÒÔÏÂÊôÐԺͳ£Á¿µ½Õâ¸öÀࣺ

let circlePathLayer = CAShapeLayer()  
let circleRadius: CGFloat = 20.0

circlePathLayer±íʾÕâ¸öÔ²Ðη¾¶£¬¶øcircleRadius±íʾÕâ¸öÔ²Ðη¾¶µÄ°ë¾¶¡£

Ìí¼ÓÒÔϳõʼ»¯´úÂëµ½CircularLoaderView.swiftÀ´ÅäÖÃÕâ¸öshape layer£º

override init(frame: CGRect) {  
super.init(frame: frame)
configure()
}

required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}

func configure() {
circlePathLayer.frame = bounds
circlePathLayer.lineWidth = 2
circlePathLayer.fillColor = UIColor.clearColor().CGColor
circlePathLayer.strokeColor = UIColor.redColor().CGColor
layer.addSublayer(circlePathLayer)
backgroundColor = UIColor.whiteColor()
}

Á½¸ö³õʼ»¯·½·¨¶¼µ÷ÓÃconfigure·½·¨£¬configure·½·¨ÉèÖÃÒ»¸öshape layerµÄline widthΪ2£¬fill colorΪclear,stroke colorΪred¡£½«Ìí¼ÓcirclePathLayerÌí¼Óµ½view's main layer¡£È»ºóÉèÖÃviewµÄ backgroundColor Ϊwhite£¬ÄÇôµ±image¼ÓÔØÊ±£¬ÆÁÄ»µÄÆäÓಿ·Ö¾ÍºöÂÔµô¡£

Ìí¼Ó·¾¶

Äã»á×¢Òâµ½Ä㻹û¸³ÖµÒ»¸öpath¸ølayer¡£ÎªÁË×öµ½Õâµã£¬Ìí¼ÓÒÔÏ·½·¨(»¹ÊÇÔÚCircularLoaderView.swiftÎļþ)£º

func circleFrame() -> CGRect {  
var circleFrame = CGRect(x: 0, y: 0, width:
2*circleRadius, height: 2*circleRadius)
circleFrame.origin.x = CGRectGetMidX(circlePathLayer.bounds)
- CGRectGetMidX(circleFrame)
circleFrame.origin.y = CGRectGetMidY(circlePathLayer.bounds)
- CGRectGetMidY(circleFrame)
return circleFrame
}

ÉÏÃæÄǸö·½·¨·µ»ØÒ»¸öCGRectµÄʵÀýÀ´½ç¶¨Ö¸Ê¾Æ÷µÄ·¾¶¡£Õâ¸ö±ß¿òÊÇ2*circleRadius¿íºÍ2*circleRadius¸ß£¬·ÅÔÚÕâ¸öviewµÄÕýÖÐÐÄ¡£

ÿ´ÎÕâ¸öviewµÄsize¸Ä±äʱ£¬Äã»áÐèÒª¶¼ÖØÐ¼ÆËãcircleFrame£¬ËùÒÔÄã¿ÉÄܽ«Ëü·ÅÔÚÒ»¸ö¶ÀÁ¢µÄ·½·¨¡£

ÏÖÔÚÌí¼ÓÒÔÏ·½·¨À´´´½¨ÄãµÄ·¾¶£º

func circlePath() -> UIBezierPath {  
return UIBezierPath(ovalInRect: circleFrame())
}

ÕâÖ»ÊǸù¾ÝcircleFrameÏÞ¶¨À´·µ»ØÔ²ÐεÄUIBezierPath¡£ÓÉÓÚcircleFrame()·µ»ØÒ»¸öÕý·½ÐΣ¬ÔÚÕâÖÖÇé¿öÏ¡±ÍÖÔ²¡°»á×îÖÕ³ÉΪһ¸öÔ²ÐΡ£

ÓÉÓÚlayersûÓÐautoresizingMaskÕâ¸öÊôÐÔ£¬ÄãÐèÒªÔÚlayoutSubviews·½·¨¸üÐÂcirclePathLayerµÄframeÀ´Ç¡µ±µØÏìÓ¦viewµÄsize±ä»¯¡£

ÏÂÒ»²½£¬¸²¸ÇlayoutSubviews()·½·¨£º

override func layoutSubviews() {  
super.layoutSubviews()
circlePathLayer.frame = bounds
circlePathLayer.path = circlePath().CGPath
}

ÓÉÓڸıäÁËframe£¬ÄãÒªÔÚÕâÀïµ÷ÓÃcirclePath()·½·¨À´´¥·¢ÖØÐ¼ÆËã·¾¶¡£

ÏÖÔÚ´ò¿ªCustomImageView.swiftÎļþºÍÌí¼ÓÒÔÏÂCircularLoaderViewʵÀý×÷Ϊһ¸öÊôÐÔ£º

let progressIndicatorView = CircularLoaderView(frame: CGRectZero)

ÏÂÒ»²½£¬ÔÚ֮ǰÏÂÔØÍ¼Æ¬µÄ´úÂëÌí¼ÓÕ⼸ÐдúÂëµ½init(coder:)·½·¨£º

addSubview(self.progressIndicatorView)  
progressIndicatorView.frame = bounds
progressIndicatorView.autoresizingMask
= .FlexibleWidth | .FlexibleHeight

ÉÏÃæ´úÂëÌí¼Ó½ø¶ÈָʾÆ÷×÷Ϊһ¸ösubviewÌí¼Óµ½×Ô¶¨ÒåµÄimage view¡£autoresizingMaskÈ·±£½ø¶ÈָʾÆ÷view±£³ÖÓëimage viewµÄsizeÒ»Ñù¡£±àÒëºÍÔËÐÐÄãµÄÏîÄ¿£»Äã»á¿´µ½Ò»¸öºìµÄ¡¢¿ÕÐĵÄÔ²ÐγöÏÖ£¬¾ÍÏñÕâÑù£º

ºÃµÄ - ÄãÒѾ­Óнø¶ÈָʾÆ÷»­ÔÚÆÁÄ»ÉÏ¡£ÄãµÄÏÂÒ»¸öÈÎÎñ¾ÍÊǸù¾ÝÏÂÔØ½ø¶È±ä»¯À´stroke¡£

ÐÞ¸ÄStroke³¤¶È

»Øµ½CircularLoaderView.swiftÎļþºÍÔÚÕâ¸öÎļþµÄÆäËûÊôÐÔÖ±½ÓÌí¼ÓÒÔÏ´úÂ룺

var progress: CGFloat {  
get {
return circlePathLayer.strokeEnd
}
set {
if (newValue > 1) {
circlePathLayer.strokeEnd = 1
} else if (newValue < 0) {
circlePathLayer.strokeEnd = 0
} else {
circlePathLayer.strokeEnd = newValue
}
}
}

ÒÔÉÏ´úÂë´´½¨Ò»¸öcomputed property - Ò²¾ÍÊÇÒ»¸öÊôÐÔûÓÐÈκκ󱳵ıäÁ¿ - ËüÓÐÒ»¸ö×Ô¶¨ÒåµÄsetterºÍgetter¡£Õâ¸ögetterÖ»ÊÇ·µ»ØcirclePathLayer.strokeEnd£¬setterÑéÖ¤ÊäÈëÖµÒªÔÚ0µ½1Ö®¼ä£¬È»ºóÇ¡µ±µØÉèÖÃlayerµÄstrokeEndÊôÐÔ¡£

ÔÚµÚÒ»´ÎÔËÐеÄʱºò£¬Ìí¼ÓÏÂÃæÕâÐдúÂëµ½configure()À´³õʼ»¯½ø¶È£º

progress = 0 

±àÒëºÍÔËÐй¤³Ì£»³ýÁËÒ»¸ö¿Õ°×µÄÆÁÄ»£¬ÄãÓ¦¸ÃʲôҲû¿´µ½¡£ÏàÐÅÎÒ£¬ÕâÊÇÒ»¸öºÃÏûÏ¢¡£ÉèÖÃprogressΪ0£¬·´¹ýÀ´»áÉèÖÃstrokeEndҲΪ0£¬Õâ¾ÍÒâζ×Åshape layerʲôҲû»­¡£

ΨһʣÏÂÒª×öµÄ¾ÍÊÇÄãµÄָʾÆ÷ÔÚimageÏÂÔØ»Øµ÷·½·¨ÖиüÐÂprogress¡£

»Øµ½CustomImageView.swiftÎļþºÍÓÃÒÔÏ´úÂëÀ´´úÌæ×¢ÊÍUpdate progress here£º

self!.progressIndicatorView.progress =
CGFloat(receivedSize)/CGFloat(expectedSize)

ÕâÖ÷Ҫͨ¹ýreceivedSize³ýÒÔexpectedSizeÀ´¼ÆËã½ø¶È¡£

×¢Ò⣺Äã»á×¢Òâµ½blockʹÓÃweak selfÒýÓà - ÕâÑùÄܹ»±ÜÃâretain cycle¡£

±àÒëºÍÔËÐÐÄãµÄ¹¤³Ì£»Äã»á¿´µ½½ø¶ÈָʾÆ÷ÏñÕâÑù¿ªÊ¼Òƶ¯£º

¼´Ê¹Äã×Ô¼ºÃ»ÓÐÌí¼ÓÈκζ¯»­´úÂ룬CALayerÔÚlayerÇáËɵط¢ÏÖÈκÎanimatableÊôÐԺ͵±ÊôÐԸıäʱƽ»¬µØanimate¡£

ÉÏÃæÒѾ­Íê³ÉµÚÒ»¸ö½×¶Î¡£ÏÖÔÚ½øÈëµÚ¶þºÍ×îºó½×¶Î¡£

´´½¨Reveal¶¯»­

reveal½×¶ÎÔÚwindowÏÔʾimageÈ»ºóÖð½¥À©Õ¹Ô²Ðλ·µÄÐÎ×´¡£Èç¹ûÄãÒѾ­¶Á¹ýÇ°Ãæ½Ì³Ì£¬ÄǸö½Ì³ÌÖ÷Òª½²´´½¨Ò»¸öPing·ç¸ñµÄview controller¶¯»­£¬Äã¾Í»áÖªµÀÕâÊÇÒ»¸öºÜºÃµÄ¹ØÓÚCALayerµÄmaskÊôÐÔµÄʹÓð¸Àý¡£

Ìí¼ÓÒÔÏ·½·¨µ½CircularLoaderView.swiftÎļþ£º

func reveal() {  
// 1
backgroundColor = UIColor.clearColor()
progress = 1
// 2
circlePathLayer.removeAnimationForKey("strokeEnd")
// 3
circlePathLayer.removeFromSuperlayer()
superview?.layer.mask = circlePathLayer
}

ÕâÊÇÒ»¸öºÜÖØÒªµÄ·½·¨ÐèÒªÀí½â£¬ÈÃÎÒÃÇÖð¶Î¿´Ò»±é£º

  1. ÉèÖÃviewµÄ±³¾°É«Îªclear£¬ÄÇôÔÚviewºóÃæµÄimage²»ÔÙÒþ²Ø£¬È»ºóÉèÖÃprogressΪ1»ò100%¡£
  2. ʹÓÃstrokeEndÊôÐÔÀ´ÒƳýÈκδý¶¨µÄimplicit animations£¬·ñÔò¸ÉÈÅreveal animation¡£¹ØÓÚimplicit animationsµÄ¸ü¶àÐÅÏ¢£¬Çë²é¿´iOS Animations by Tutorials¡£
  3. ´ÓËüµÄsuperLayerÒÆ³ýcirclePathLayer£¬È»ºó¸³Öµ¸øsuperViewµÄlayer maks£¬½èÖúcircular mask ¡°hole¡±£¬imageÊǿɼûµÄ¡£ÕâÑùÈÃÄ㸴ÓÃÒÑ´æÔÚµÄlayerºÍ±ÜÃâÖØ¸´´úÂë¡£

ÏÖÔÚÄãÐèÒªÔÚij¸öµØ·½µ÷ÓÃreveal()¡£ÔÚCustomImageView.swiftÎļþÓÃÒÔÏ´úÂëÌæ»»Reveal image here×¢ÊÍ£º

self!.progressIndicatorView.reveal() 

±àÒëºÍÔËÐÐÄãµÄapp£»Ò»µ©image¿ªÊ¼ÏÂÔØ£¬Äã»á¿´¼ûÒ»²¿·ÖСµÄringÔÚÏÔʾ¡£

ÄãÄÜÔÚ±³¾°¿´µ½ÄãµÄimage - µ«¼¸ºõʲôҲûÓУ¡

À©Õ¹»·

ÄãµÄÏÂÒ»²½¾ÍÊÇÔÚÄÚÍâÀ©Õ¹Õâ¸ö»·¡£Äã¿ÉÒÔÁ½¸ö·ÖÀëµÄ¡¢Í¬ÖáÐĵÄUIBezierPathÀ´×öµ½£¬µ«ÄãÒ²¿ÉÒÔÒ»¸ö¸ü¼ÓÓÐЧµÄ·½·¨£¬Ö»ÊÇʹÓÃÒ»¸öBezier pathÀ´Íê³É¡£

ÔõÑù×öÄØ£¿ÄãÖ»ÊÇÔö¼ÓÔ²µÄ°ë¾¶(pathÊôÐÔ)À´ÏòÍâÀ©Õ¹£¬Í¬Ê±Ôö¼ÓlineµÄ¿í¶È(lineWidthÊôÐÔ)À´Ê¹»·¸ü¼ÓºñºÍÏòÄÚÀ©Õ¹¡£×îÖÕ£¬Á½¸öÖµ¶¼Ôö³¤µ½×㹻ʱ¾ÍÔÚÏÂÃæÏÔʾÕû¸öimage¡£

»Øµ½CircularLoaderView.swiftÎļþºÍÌí¼ÓÒÔÏ´úÂëµ½reveal()·½·¨µÄ×îºó£º

// 1  
let center = CGPoint(x: CGRectGetMidX(bounds), y: CGRectGetMidY(bounds))
let finalRadius = sqrt((center.x*center.x) + (center.y*center.y))
let radiusInset = finalRadius - circleRadius
let outerRect = CGRectInset(circleFrame(), -radiusInset, -radiusInset)
let toPath = UIBezierPath(ovalInRect: outerRect).CGPath
// 2
let fromPath = circlePathLayer.path
let fromLineWidth = circlePathLayer.lineWidth
// 3
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue,
forKey: kCATransactionDisableActions)
circlePathLayer.lineWidth = 2*finalRadius
circlePathLayer.path = toPath
CATransaction.commit()
// 4
let lineWidthAnimation = CABasicAnimation(keyPath: "lineWidth")
lineWidthAnimation.fromValue = fromLineWidth
lineWidthAnimation.toValue = 2*finalRadius
let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.fromValue = fromPath
pathAnimation.toValue = toPath
// 5
let groupAnimation = CAAnimationGroup()
groupAnimation.duration = 1
groupAnimation.timingFunction =
CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
groupAnimation.animations = [pathAnimation, lineWidthAnimation]
groupAnimation.delegate = self
circlePathLayer.addAnimation(groupAnimation, forKey: "strokeWidth")

ÏÖÔÚÖð¶Î½âÊÍÒÔÉÏ´úÂëÊǾ¿¾¹×öÁËʲô£º

  1. È·¶¨Ô²Ðεİ뾶֮ºó¾ÍÄÜÍêÈ«ÏÞÖÆimage view¡£È»ºó¼ÆËãCGRectÀ´ÍêÈ«ÏÞÖÆÕâ¸öÔ²ÐΡ£toPath±íʾCAShapeLayer maskµÄ×îÖÕÐÎ×´¡£
  2. ÉèÖÃlineWidthºÍpath³õʼֵÀ´Æ¥Å䵱ǰlayerµÄÖµ¡£
  3. ÉèÖÃlineWidthºÍpathµÄ×îÖÕÖµ£»ÕâÑùÄÜ·ÀÖ¹ËüÃǵ±¶¯»­Íê³ÉÊ±Ìø»ØËüÃǵÄԭʼֵ¡£CATransactionÉèÖÃkCATransactionDisableActions¼ü¶ÔÓ¦µÄֵΪtrueÀ´½ûÓÃlayerµÄimplicit animations¡£
  4. ´´½¨Ò»¸öÁ½¸öCABasicAnimationµÄʵÀý£¬Ò»¸öÊÇ·¾¶¶¯»­£¬Ò»¸öÊÇlineWidth¶¯»­£¬lineWidth±ØÐëÔö¼Óµ½Á½±¶¸ú°ë¾¶Ôö³¤ËÙ¶ÈÒ»Ñù¿ì£¬ÕâÑùÔ²ÐÎÏòÄÚÀ©Õ¹ÓëÏòÍâÀ©Õ¹Ò»Ñù¡£
  5. ½«Á½¸öanimationsÌí¼Óµ½Ò»¸öCAAnimationGroup£¬È»ºóÌí¼Óanimation groupµ½layer¡£½«self¸³Öµ¸ødelegate£¬µÈÏÂÄã»áʹÓõ½Ëü¡£

±àÒëºÍÔËÐÐÄãµÄ¹¤³Ì£»Äã»á¿´µ½Ò»µ©imageÍê³ÉÏÂÔØ£¬reveal animation¾Í»áµ¯³öÀ´¡£µ«¼´Ê¹reveal animationÍê³É£¬²¿·ÖÔ²Ðλ¹Êǻᱣ³ÖÔÚÆÁÄ»ÉÏ¡£

ΪÁËÐÞ¸´ÕâÖÖÇé¿ö£¬Ìí¼ÓÒÔÏÂʵÏÖanimationDidStop(_:finished:) µ½ CircularLoaderView.swift£º

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) 
{ superview?.layer.mask = nil
}

ÕâЩ´úÂë´Ósuper layerÉÏÒÆ³ýmask£¬Õâ»áÍêÈ«µØÒƳýÔ²ÐΡ£

ÔٴαàÒëºÍÔËÐÐÄãµÄ¹¤³Ì£¬ºÍÄã»á¿´µ½Õû¸ö¶¯»­µÄЧ¹û£º

¹§Ï²Ä㣬ÄãÒѾ­Íê³É´´½¨Ô²ÐÎͼÏñ¼ÓÔØ¶¯»­£¡

ÏÂÒ»²½

Äã¿ÉÒÔÔÚÕâÀïÏÂÔØÕû¸ö¹¤³Ì¡£

»ùÓÚ±¾½Ì³Ì£¬Äã¿ÉÒÔ½øÒ»²½À´Î¢µ÷¶¯»­µÄʱ¼ä¡¢ÇúÏߺÍÑÕÉ«À´Âú×ãÄãµÄÐèÇóºÍ¸öÈËÉè¼ÆÃÀѧ¡£Ò»¸ö¿ÉÄÜÐèÒª¸Ä½ø¾ÍÊÇÉèÖÃshape layerµÄlineCapÊôÐÔֵΪkCALineCapRoundÀ´ËÄÉáÎåÈëÔ²Ðνø¶ÈָʾÆ÷µÄβ²¿¡£Äã×Ô¼ºË¼¿¼»¹ÓÐʲô¿ÉÒԸĽøµÄµØ·½¡£

Èç¹ûÄãϲ»¶Õâ¸ö½Ì³ÌºÍÔ¸ÒâѧϰÔõÑù´´½¨¸ü¶àÏñÕâÑùµÄ¶¯»­£¬Çë²é¿´Marin TodorovµÄÊéiOS Animations by Tutorials¡£ËüÊÇ´Ó»ù±¾µÄ¶¯»­¿ªÊ¼£¬È»ºóÖð²½½²½âlayer animations, animating constraints, view controller transitionsºÍ¸ü¶à¡£

Èç¹ûÄãÓÐʲô¹ØÓÚÕâ¸ö½Ì³ÌµÄÎÊÌâ»òÆÀÂÛ£¬ÇëÔÚÏÂÃæ²ÎÓëÌÖÂÛ¡£ÎÒºÜÀÖÒâ¿´µ½ÄãÔÚÄãµÄAppÖÐÌí¼ÓÕâô¿áµÄ¶¯»­¡£

   
3655 ´Îä¯ÀÀ       30
 
Ïà¹ØÎÄÕÂ

ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖÓë̽ÌÖ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
 
Ïà¹ØÎĵµ

Android_UI¹Ù·½Éè¼Æ½Ì³Ì
ÊÖ»ú¿ª·¢Æ½Ì¨½éÉÜ
androidÅÄÕÕ¼°ÉÏ´«¹¦ÄÜ
Android½²ÒåÖÇÄÜÊÖ»ú¿ª·¢
Ïà¹Ø¿Î³Ì

Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
Androidϵͳ¿ª·¢
AndroidÓ¦Óÿª·¢
ÊÖ»úÈí¼þ²âÊÔ
×îл¼Æ»®
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢ 6-12[ÏÃÃÅ]
È˹¤ÖÇÄÜ.»úÆ÷ѧϰTensorFlow 6-22[Ö±²¥]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 6-30[±±¾©]
ǶÈëʽÈí¼þ¼Ü¹¹-¸ß¼¶Êµ¼ù 7-9[±±¾©]
Óû§ÌåÑé¡¢Ò×ÓÃÐÔ²âÊÔÓëÆÀ¹À 7-25[Î÷°²]
ͼÊý¾Ý¿âÓë֪ʶͼÆ× 8-23[±±¾©]

androidÈË»ú½çÃæÖ¸ÄÏ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
AndroidÊÖ»ú¿ª·¢£¨¶þ£©
AndroidÊÖ»ú¿ª·¢£¨Èý£©
AndroidÊÖ»ú¿ª·¢£¨ËÄ£©
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖ̽ÌÖ
ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
ÊÖ»úÈí¼þ×Ô¶¯»¯²âÊÔÑо¿±¨¸æ


Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
AndroidÓ¦Óÿª·¢
Androidϵͳ¿ª·¢
ÊÖ»úÈí¼þ²âÊÔ
ǶÈëʽÈí¼þ²âÊÔ
AndroidÈí¡¢Ó²¡¢ÔÆÕûºÏ


ÁìÏÈIT¹«Ë¾ android¿ª·¢Æ½Ì¨×î¼Ñʵ¼ù
±±¾© Android¿ª·¢¼¼Êõ½ø½×
ijÐÂÄÜÔ´ÁìÓòÆóÒµ Android¿ª·¢¼¼Êõ
ijº½Ì칫˾ Android¡¢IOSÓ¦ÓÃÈí¼þ¿ª·¢
°¢¶û¿¨ÌØ LinuxÄÚºËÇý¶¯
°¬Ä¬Éú ǶÈëʽÈí¼þ¼Ü¹¹Éè¼Æ
Î÷ÃÅ×Ó Ç¶Èëʽ¼Ü¹¹Éè¼Æ