Core Animation一些Demo總結(jié) (動(dòng)態(tài)切換圖片、大轉(zhuǎn)盤、圖片折疊、進(jìn)度條等動(dòng)畫效果)
前一篇總結(jié)了Core Animation的一些基礎(chǔ)知識(shí),這一篇主要是Core Animation 的一些應(yīng)用,涉及到CAShapeLayer、CAReplicatorLayer等圖層的知識(shí)。
先看效果圖:
1、切換圖片:
2、彩票轉(zhuǎn)盤
3、圖片折疊
4、進(jìn)度條旋轉(zhuǎn)
5、粒子效果
一、切換圖片
看起來很復(fù)雜的動(dòng)畫,通過少量的計(jì)算和編碼就可以簡(jiǎn)單的實(shí)現(xiàn)。要做到這一步,必須是需要研究iOS開發(fā)中的Core Animation和Core Graphics框架的。日常工作中,對(duì)于很多東西不求甚解,只是拿過來用,甚至都不研究、封裝一下別人代碼,這種做法是很不好的。我喜歡自己造輪子,輪子造多了,開發(fā)經(jīng)驗(yàn)與思維也就提升上去了。
這個(gè)動(dòng)畫實(shí)現(xiàn)是比較簡(jiǎn)單的,利用了CABasicAnimation、CAKeyframeAnimation和CAAnimationGroup??此剖莾蓮垐D片各自有著自己不同的動(dòng)畫,實(shí)際不過是一個(gè)動(dòng)畫方法,其平移方向與旋轉(zhuǎn)角度的不同。
我是用了CABasicAnimation設(shè)置了view的zPosition值,CAKeyframeAnimation對(duì)象設(shè)計(jì)了圖片的位移與旋轉(zhuǎn)動(dòng)畫,然后將之放到CAAnimationGroup對(duì)象里面,開始動(dòng)畫。
這里有一個(gè)注意點(diǎn),那就是Core Animation設(shè)置的動(dòng)畫位移、旋轉(zhuǎn)、縮放都只是一個(gè)假象,實(shí)際上的view該怎么還是怎么樣,并未真正有過變化。所以,在動(dòng)畫結(jié)束后,想要正確的效果,那么需要設(shè)置view的zPosition值,這個(gè)值越大,view越在前面(z軸方向上的“前面”)。
代碼:
#import "ViewController.h" @interface ViewController () @property (nonatomic, strong) NSMutableArray *images; @property (nonatomic, assign) int currentIndex; @property (weak, nonatomic) IBOutlet UIImageView *currentImageView; @property (weak, nonatomic) IBOutlet UIImageView *behindImageView; @end @implementation ViewController - (NSMutableArray *)images { if (_images == nil) { _images = [NSMutableArray array]; for (int i = 1; i <= 7; i++) { UIImage *image = [UIImage imageNamed: [NSString stringWithFormat:@"%d",i]]; [_images addObject:image]; } } return _images; } - (void)viewDidLoad { [super viewDidLoad]; self.currentIndex = 0; self.currentImageView.image = self.images[_currentIndex]; } - (void)addAnimateWithPoint:(CGPoint )point angle:(CGFloat)angle fromZ:(CGFloat)fromZ toZ:(CGFloat)toZ view:(UIView *)view { CABasicAnimation *zPosition = [[CABasicAnimation alloc] init]; zPosition.keyPath = @"zPosition"; zPosition.fromValue = @(fromZ); zPosition.toValue = @(toZ); zPosition.duration = 1.2; CAKeyframeAnimation *rotation = [[CAKeyframeAnimation alloc] init]; rotation.keyPath = @"transform.rotation"; rotation.values = @[@(0), @(angle), @(0)]; rotation.duration = 2; rotation.timingFunctions = @[ [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; CAKeyframeAnimation *position = [[CAKeyframeAnimation alloc] init]; position.keyPath = @"position"; // CGPointMake(110, -20) position.values = @[ [NSValue valueWithCGPoint:CGPointZero], [NSValue valueWithCGPoint:point], [NSValue valueWithCGPoint:CGPointZero] ]; position.timingFunctions = @[ [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut], [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] ]; position.additive = YES; position.duration = 1.2; CAAnimationGroup *animateGroup = [[CAAnimationGroup alloc] init]; animateGroup.animations = @[zPosition, rotation, position]; // animateGroup.beginTime = 0.5; animateGroup.delegate = self; animateGroup.duration = 1.2; [animateGroup setValue:view forKey:@"view"]; [view.layer addAnimation:animateGroup forKey:nil]; view.layer.zPosition = toZ; } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { CAAnimationGroup *group = [anim valueForKey:@"view"]; if (group != nil) { self.currentImageView.image = self.images[_currentIndex]; self.currentImageView.layer.zPosition = 1; self.behindImageView.image = nil; self.behindImageView.layer.zPosition = -1; } } - (IBAction)previous:(id)sender { self.currentIndex = (self.currentIndex + 1) % self.images.count; self.behindImageView.image = self.images[_currentIndex]; [self addAnimateWithPoint:CGPointMake(-90, 20) angle:0.15 fromZ:-1 toZ:1 view:self.behindImageView]; [self addAnimateWithPoint:CGPointMake(90, -20) angle:-0.15 fromZ:1 toZ:-1 view:self.currentImageView]; } - (IBAction)next:(id)sender { self.currentIndex = (self.currentIndex + 6) % self.images.count; self.behindImageView.image = self.images[_currentIndex]; [self addAnimateWithPoint:CGPointMake(-90, 20) angle:-0.15 fromZ:-1 toZ:1 view:self.behindImageView]; [self addAnimateWithPoint:CGPointMake(90, -20) angle:0.15 fromZ:1 toZ:-1 view:self.currentImageView]; } @end
二、彩票轉(zhuǎn)盤
這個(gè)動(dòng)畫的實(shí)現(xiàn)主要難點(diǎn)在于Button的擺放,只要擺放好button,其他就是簡(jiǎn)單的添加動(dòng)畫的一個(gè)過程。
12個(gè)星座,那么需要12個(gè)button。在擺放它們的時(shí)候,我是將一個(gè)個(gè)button的anchorPoint設(shè)置為(0.5, 1),將button的position設(shè)置為中心圓的圓心,然后設(shè)置transform來旋轉(zhuǎn)它們,是的達(dá)到圍繞一個(gè)圓擺放的目的。
需要知道的是,一般來說,控件的anchorPoint就是控件的中心點(diǎn),所以在我們做旋轉(zhuǎn)、平移等操作的時(shí)候,也就是在圍繞中心點(diǎn)的一系列操作。但是,很多時(shí)候,只是圍繞中心點(diǎn)來設(shè)置動(dòng)畫的話,會(huì)很復(fù)雜,CALayer提供了一個(gè)anchorPoint屬性,可以讓我們自由的改變其數(shù)值,從而實(shí)現(xiàn)比較復(fù)雜的動(dòng)畫。
還有就是button的點(diǎn)擊事件,事實(shí)上由于一個(gè)扇形區(qū)域是上邊大,下邊小,要是不做相應(yīng)的限制,當(dāng)用戶點(diǎn)擊下面的區(qū)域時(shí),很可能不是選中當(dāng)前的button,因此要做一定的限制。這里我是自定義了一個(gè)button,在里面重寫了hitTest: WwthEvent: 方法,這個(gè)方法可以設(shè)置你所要監(jiān)聽事件的區(qū)域范圍。
代碼:
#import "ZYWheelView.h" #define ZYImageW 40 #define ZYImageH 46 @interface ZYButton : UIButton @end @implementation ZYButton /** * 重寫此方法,截取button的點(diǎn)擊 * */ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { CGFloat btnW = self.bounds.size.width; CGFloat btnH = self.bounds.size.height; CGFloat x = 0; CGFloat y = btnH / 2; CGFloat w = btnW; CGFloat h = y; CGRect rect = CGRectMake(x, y, w, h); if (CGRectContainsPoint(rect, point)) { return nil; }else{ return [super hitTest:point withEvent:event]; } } - (CGRect)imageRectForContentRect:(CGRect)contentRect { CGFloat imageX = (contentRect.size.width - ZYImageW ) * 0.5; CGFloat imageY = 18; return CGRectMake(imageX, imageY, ZYImageW, ZYImageH); } - (void)setHighlighted:(BOOL)highlighted { } @end @interface ZYWheelView () @property (weak, nonatomic) IBOutlet UIImageView *wheelView; @property (nonatomic, weak) UIButton *lastSelectedBtn; @property (nonatomic, strong) CADisplayLink *timer; @end @implementation ZYWheelView + (instancetype)wheelView { return [[[NSBundle mainBundle] loadNibNamed:@"ZYWheelView" owner:nil options:nil] lastObject]; } - (void)awakeFromNib { self.wheelView.userInteractionEnabled = YES; CGFloat angle = 2 * M_PI / 12.0; UIImage *normalImage = [UIImage imageNamed:@"LuckyAstrology"]; UIImage *selectedImage = [UIImage imageNamed:@"LuckyAstrologyPressed"]; for (int bi = 0; bi < 12; bi++) { ZYButton *btn = [[ZYButton alloc] init]; [btn setBackgroundImage:[UIImage imageNamed:@"LuckyRototeSelected"] forState:UIControlStateSelected]; // 切割圖片,將切割好的圖片設(shè)置到按鈕上 // CGImage中rect是當(dāng)做像素來使用 // UIKit 中是點(diǎn)坐標(biāo)系 // 坐標(biāo)系的特點(diǎn):如果在非retain屏上 1個(gè)點(diǎn)等于1個(gè)像素 // 在retain屏上1個(gè)點(diǎn)等于2個(gè)像素 CGFloat imageH = ZYImageH * [UIScreen mainScreen].scale; CGFloat imageW = ZYImageW * [UIScreen mainScreen].scale; CGFloat imageY = 0; CGFloat imageX = bi * imageW; CGRect rect = CGRectMake(imageX, imageY, imageW, imageH); CGImageRef normalRef = CGImageCreateWithImageInRect(normalImage.CGImage, rect); CGImageRef selectedRef = CGImageCreateWithImageInRect(selectedImage.CGImage, rect); [btn setImage:[UIImage imageWithCGImage:normalRef] forState:UIControlStateNormal]; [btn setImage:[UIImage imageWithCGImage:selectedRef] forState:UIControlStateSelected]; btn.bounds = CGRectMake(0, 0, 58, 143); btn.layer.anchorPoint = CGPointMake(0.5, 1); btn.layer.position = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5); btn.transform = CGAffineTransformMakeRotation(angle * bi); [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside]; [self.wheelView addSubview:btn]; } [self startRotating]; } - (void)startRotating { if (self.timer) return; self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateTimer)]; [self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } - (void)stopRotating { [self.timer invalidate]; self.timer = nil; } - (void)clickBtn:(UIButton *)btn { self.lastSelectedBtn.selected = NO; btn.selected = YES; self.lastSelectedBtn = btn; } - (IBAction)clickCenterBtn:(id)sender { self.userInteractionEnabled = NO; [self stopRotating]; CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; basicAnimation.toValue = @(M_PI * 2 * 5); basicAnimation.duration = 2; basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; // basicAnimation.removedOnCompletion = NO; // basicAnimation.fillMode = kCAFillModeForwards; basicAnimation.delegate = self; [self.wheelView.layer addAnimation:basicAnimation forKey:nil]; } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { self.userInteractionEnabled = YES; // 根據(jù)選中的按鈕獲取旋轉(zhuǎn)的度數(shù), // 通過transform獲取角度 CGFloat angle = atan2(self.lastSelectedBtn.transform.b, self.lastSelectedBtn.transform.a); // 從實(shí)際上旋轉(zhuǎn)轉(zhuǎn)盤 self.wheelView.transform = CGAffineTransformMakeRotation(-angle); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self startRotating]; }); } - (void)updateTimer { self.wheelView.transform = CGAffineTransformRotate(self.wheelView.transform, M_PI / 200); } - (void)dealloc { [self stopRotating]; } @end
3、圖片折疊
這個(gè)效果看起來很炫酷,但實(shí)際做起來是比較簡(jiǎn)單的。需要三個(gè)View,兩個(gè)UIImageView,一個(gè)接受拖拽action的View。CALayer里面有個(gè)contentRect屬性,它可以設(shè)置layer里面的顯示內(nèi)容,利用這個(gè)屬性,我們可以做在下載圖片時(shí),下載一點(diǎn)展示一點(diǎn)的效果。 在這里,我用這個(gè)屬性來這是兩張UIImageView各自展示一半的圖片,然后將這兩張ImageView拼接在一起,顯示完整的圖片。
在一個(gè)覆蓋這張完整圖片的View上添加拖拽手勢(shì),以實(shí)現(xiàn)動(dòng)畫過程。
這里有一個(gè)新的圖層需要學(xué)習(xí)下,CAGradientLayer,它是用來做顏色漸變的,用法與CALayer的用法相似:
屬性代碼:
CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = self.bottomView.bounds; gradientLayer.opacity = 0; gradientLayer.colors = @[(id)[UIColor clearColor].CGColor, (id)[UIColor blackColor].CGColor]; self.gradientLayer = gradientLayer; [self.bottomView.layer addSublayer:gradientLayer]; // 設(shè)置漸變顏色 // gradientL.colors = @[(id)[UIColor redColor].CGColor,(id)[UIColor greenColor].CGColor,(id)[UIColor yellowColor].CGColor]; // 設(shè)置漸變定位點(diǎn) // gradientL.locations = @[@0.1,@0.4,@0.5]; // 設(shè)置漸變開始點(diǎn),取值0~1 // gradientL.startPoint = CGPointMake(0, 1);
設(shè)置好之后,在pan手勢(shì)的方法里面不斷改變gradientLayer的opacity即可達(dá)到想要的效果。
CATransform3D有個(gè)m34屬性,可以設(shè)置透視度,一般將這個(gè)值設(shè)置為- 1 / 500.0,特定需求可以微調(diào)這個(gè)值。
代碼:
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *topView; @property (weak, nonatomic) IBOutlet UIImageView *bottomView; @property (weak, nonatomic) IBOutlet UIView *containView; @property (nonatomic, weak) CAGradientLayer *gradientLayer; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self setupOtherView]; //設(shè)置漸變的陰影 [self setupShadow]; } - (void)setupOtherView { //設(shè)置contentsRect用來表示圖片顯示的大小,可以做邊下載邊顯示的UI效果,取值是(0--1) self.topView.layer.contentsRect = CGRectMake(0, 0, 1, 0.5); self.topView.layer.anchorPoint = CGPointMake(0.5, 1); self.bottomView.layer.contentsRect = CGRectMake(0, 0.5, 1, 0.5); self.bottomView.layer.anchorPoint = CGPointMake(0.5, 0); UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [self.containView addGestureRecognizer:gesture]; } - (void)setupShadow { CAGradientLayer *gradientLayer = [CAGradientLayer layer]; gradientLayer.frame = self.bottomView.bounds; gradientLayer.opacity = 0; gradientLayer.colors = @[(id)[UIColor clearColor].CGColor, (id)[UIColor blackColor].CGColor]; self.gradientLayer = gradientLayer; [self.bottomView.layer addSublayer:gradientLayer]; // 設(shè)置漸變顏色 // gradientL.colors = @[(id)[UIColor redColor].CGColor,(id)[UIColor greenColor].CGColor,(id)[UIColor yellowColor].CGColor]; // 設(shè)置漸變定位點(diǎn) // gradientL.locations = @[@0.1,@0.4,@0.5]; // 設(shè)置漸變開始點(diǎn),取值0~1 // gradientL.startPoint = CGPointMake(0, 1); } - (void)pan:(UIPanGestureRecognizer *)recognizer { CGFloat y = [recognizer translationInView:self.containView].y; if (y >= 300) y = 300; if (y <= -300) y = -300; // 旋轉(zhuǎn)角度,往下逆時(shí)針旋轉(zhuǎn) CGFloat angle = -y / 320.0 * M_PI; self.topView.layer.transform = CATransform3DIdentity; CATransform3D transfrom = CATransform3DIdentity; transfrom.m34 = -1 / 500.0; self.topView.layer.transform = CATransform3DRotate(transfrom, angle, 1, 0, 0); self.gradientLayer.opacity = y / 300.0; if (recognizer.state == UIGestureRecognizerStateEnded) { // 彈簧效果的動(dòng)畫 // SpringWithDamping:彈性系數(shù),越小,彈簧效果越明顯 [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:11 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.topView.layer.transform = CATransform3DIdentity; self.gradientLayer.opacity = 0; } completion:nil]; } } @end
4、旋轉(zhuǎn)進(jìn)度條
圓圈旋轉(zhuǎn)一般都是放在HUD上吧。記得以前我也做過一個(gè)類似的功能,那時(shí)候還沒現(xiàn)在這樣的知識(shí)儲(chǔ)備,只能是用CAKeyframeAnimation做,讓美工做出了一根頂部是一個(gè)小白點(diǎn),除此之外,很長的那部分是為clearColor的小矩形,然后我設(shè)置它的anchorPoint,給 CAKeyframeAnimation添加一個(gè)圓形的path,然后圍繞這個(gè)path旋轉(zhuǎn),做是勉強(qiáng)做出來,但是很不好看吧。
現(xiàn)在可以有更好的選擇了,CAReplicatorLayer(復(fù)制圖層)。我們可以在復(fù)制圖層里面添加一個(gè)instance圖層,如果設(shè)置了復(fù)制圖層的instanceCount,假如讓instanceCount == 5, 那么復(fù)制圖層會(huì)自動(dòng)幫我們復(fù)制5個(gè)跟instance圖層一樣的圖層(事實(shí)上,我們可以在一開始就給instance圖層設(shè)置動(dòng)畫,那么在復(fù)制的時(shí)候,一樣會(huì)把動(dòng)畫也復(fù)制過來),除此之外,還可以設(shè)置復(fù)制圖層里面的instance圖層的transfrom,從而實(shí)現(xiàn)一定的布局。復(fù)制圖層里面還有一個(gè)instanceDelay,它表示延遲多少時(shí)間開始動(dòng)畫等等。
這個(gè)Demo就是用了上面所說的實(shí)現(xiàn)的,代碼:
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIView *containView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self setupReplicatorLayerAndAnimation]; } - (void)setupReplicatorLayerAndAnimation { CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = self.containView.layer.bounds; [self.containView.layer addSublayer:replicatorLayer]; CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(self.containView.frame.size.width * 0.5, 20, 16, 16); layer.backgroundColor = [UIColor redColor].CGColor; layer.cornerRadius = layer.frame.size.width / 2; //這一句可以將初始過程移除掉 layer.transform = CATransform3DMakeScale(0, 0, 0); [replicatorLayer addSublayer:layer]; replicatorLayer.instanceCount = 22; CABasicAnimation *basicAn = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; basicAn.fromValue = @1; basicAn.toValue = @0; basicAn.duration = 1; basicAn.repeatCount = MAXFLOAT; [layer addAnimation:basicAn forKey:nil]; replicatorLayer.instanceDelay = basicAn.duration / (double)replicatorLayer.instanceCount; replicatorLayer.instanceTransform = CATransform3DMakeRotation(2 * M_PI / replicatorLayer.instanceCount, 0, 0, 1); } @end
5、粒子效果
這個(gè)東西就是CAReplicatorLayer(復(fù)制圖層)和Core Graphics的結(jié)合吧,我是采用UIBezierPath來繪制線條,然后將繪制好的path賦值給小球的animation路徑,然后將小球添加到復(fù)制圖層,設(shè)置下instanceCount,設(shè)置下延遲時(shí)間,效果就出來了。
代碼:
#import "ZYDrawView.h" @interface ZYDrawView () @property (nonatomic, strong) UIBezierPath *bezierPath; @property (nonatomic, weak) CAReplicatorLayer *replicatorLayer; @property (nonatomic, weak) CALayer *norLayer; @end static int _count = 0; @implementation ZYDrawView - (UIBezierPath *)bezierPath { if (_bezierPath == nil) { _bezierPath = [[UIBezierPath alloc] init]; } return _bezierPath; } - (void)awakeFromNib { CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = self.bounds; [self.layer addSublayer:replicatorLayer]; CALayer *layer = [CALayer layer]; layer.frame = CGRectMake(0, -200, 10, 10); layer.cornerRadius = layer.frame.size.width * 0.5; layer.backgroundColor = [UIColor redColor].CGColor; [replicatorLayer addSublayer:layer]; self.replicatorLayer = replicatorLayer; self.norLayer = layer; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { CGPoint curPoint = [[touches anyObject] locationInView:self]; [self.bezierPath moveToPoint:curPoint]; } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { _count++; CGPoint curPoint = [[touches anyObject] locationInView:self]; [self.bezierPath addLineToPoint:curPoint]; [self setNeedsDisplay]; } - (void)startAnimation { CAKeyframeAnimation *keyframeAn = [CAKeyframeAnimation animationWithKeyPath:@"position"]; keyframeAn.path = self.bezierPath.CGPath; keyframeAn.duration = 4; keyframeAn.repeatCount = MAXFLOAT; [self.norLayer addAnimation:keyframeAn forKey:nil]; self.replicatorLayer.instanceCount = _count; self.replicatorLayer.instanceDelay = 0.1; } - (void)reDraw { _bezierPath = nil; _count = 1; [self.norLayer removeAllAnimations]; [self setNeedsDisplay]; } - (void)drawRect:(CGRect)rect { [self.bezierPath stroke]; } @end
以上內(nèi)容是小編給大家介紹的Core Animation一些Demo總結(jié) (動(dòng)態(tài)切換圖片、大轉(zhuǎn)盤、圖片折疊、進(jìn)度條等動(dòng)畫效果),希望對(duì)大家以上幫助!
- IOS開發(fā)代碼分享之獲取啟動(dòng)畫面圖片的string
- IOS等待時(shí)動(dòng)畫效果的實(shí)現(xiàn)
- iOS開發(fā)中CALayer使用的基本教程
- iOS開發(fā)中CAlayer層的屬性以及自定義層的方法
- iOS開發(fā)中使用CoreLocation框架處理地理編碼的方法
- IOS實(shí)戰(zhàn)之自定義轉(zhuǎn)場(chǎng)動(dòng)畫詳解
- 詳解iOS應(yīng)用開發(fā)中Core Data數(shù)據(jù)存儲(chǔ)的使用
- 詳解iOS App中調(diào)用AVAudioPlayer播放音頻文件的用法
- IOS如何使用CAShapeLayer實(shí)現(xiàn)復(fù)雜的View的遮罩效果
- IOS CoreAnimation中l(wèi)ayer動(dòng)畫閃爍的解決方法
相關(guān)文章
自定義ListView實(shí)現(xiàn)拖拽ListItem項(xiàng)交換位置(附源碼)
本文要實(shí)現(xiàn)的是拖拽ListView的Item項(xiàng),在布局方面還是用基于布局泵LayoutInflater來從不同的Layout模板拿到不同的布局然后將view返回,感興趣的朋友可以了解下哈2013-06-06Android startActivityForResult()代替方案示例
這篇文章主要為大家介紹了Android startActivityForResult()代替方案示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08Android使用自定義View實(shí)現(xiàn)360手機(jī)衛(wèi)士波浪球進(jìn)度的效果
360衛(wèi)士的波浪球進(jìn)度的效果,一般最常用的方法就是畫線的方式,先繪sin線或貝塞爾曲線,然后從左到右繪制豎線,然后再裁剪圓區(qū)域2018-05-05Android獲取手機(jī)的版本號(hào)等信息的代碼
這篇文章主要為大家詳細(xì)介紹了Android獲取手機(jī)的版本號(hào)等信息的代碼,代碼很精彩,感興趣的小伙伴們可以參考一下2016-07-07Android 根據(jù)手勢(shì)頂部View自動(dòng)展示與隱藏效果
這篇文章主要介紹了Android 根據(jù)手勢(shì)頂部View自動(dòng)展示與隱藏效果,本文給大家介紹非常詳細(xì)包括實(shí)現(xiàn)原理和實(shí)例代碼,需要的朋友參考下吧2017-08-08Android 指紋識(shí)別詳解及實(shí)現(xiàn)方法
本文主要介紹Android 指紋識(shí)別的知識(shí),這里整理了詳細(xì)的資料和簡(jiǎn)單實(shí)現(xiàn)代碼,有開發(fā)這部分的朋友可以參考下2016-09-09Android自定義動(dòng)態(tài)壁紙開發(fā)詳解
這篇文章主要為大家詳細(xì)介紹了Android自定義動(dòng)態(tài)壁紙開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Android App中實(shí)現(xiàn)向右滑動(dòng)銷毀功能的要點(diǎn)解析
這篇文章主要介紹了Android應(yīng)用中實(shí)現(xiàn)向右滑動(dòng)銷毀條目功能的要點(diǎn)解析,有些類似于iOS App中的滑動(dòng)頁面刪除效果,需要的朋友可以參考下2016-04-04Android Studio preview 不固定及常見問題的解決辦法
preview 可以幫助您預(yù)覽您的布局文件將如何在用戶的設(shè)備上呈現(xiàn)。這篇文章主要介紹了Android Studio preview 不固定及常見問題的解決辦法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05Android頂部(toolbar)搜索框?qū)崿F(xiàn)的實(shí)例詳解
這篇文章主要介紹了Android頂部(toolbar)搜索框?qū)崿F(xiàn)的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-09-09