“我的部落”多动画APP设计与实现

hellow.jpg

废话不说,先看gif效果,觉得不错的话,就继续看下去。

los_pro1.gif
los_pro2.gif
los_pro3.gif
los_pro4.gif
los_pro5.gif
los_pro6.gif
los_pro7.gif
los_pro8.gif

该APP起初是参考城觅这个app(界面),之后加了些自己的设计想法,例如底部的ControlTabBar点击动画,登录界面的动画,电影界面的动画,控制器转场动画,物体下落碰撞动画,树叶飘落动画,新闻界面cell动画。当然这些动画的原型是我在cocoaChina上看到的动画,觉得不错,然后移植到自己设计的app中,并在大神们的基础之上改成自己想要的动画。

当然这个项目我会放在Github上,然后就其中有些动画说明一下。

动画一:动态的UITabBar动画

自定义TaBaController把需要的参数传入到YALFoldingTabBarController中,这样的好处是我们只是需要给定参数,其余的操作,例如点击后的操作只需要在底层写好就可以了。

+ (void)showMainTabBarViewController {
    
    YALFoldingTabBarController *tabBarController = [[YALFoldingTabBarController alloc]
                                                        initWithViewControllers:[self getRootViewController]];

    //prepare leftBarItems
    YALTabBarItem *item1                         = [[YALTabBarItem alloc] initWithItemImage:[UIImage imageNamed:@"nearby_icon"]
                                                      leftItemImage:nil
                                                     rightItemImage:nil];

    //prepare rightBarItems
    YALTabBarItem *item2                         = [[YALTabBarItem alloc] initWithItemImage:[UIImage imageNamed:@"meishi"]
                                                      leftItemImage:nil
                                                     rightItemImage:nil];

    YALTabBarItem *item3                         = [[YALTabBarItem alloc] initWithItemImage:[UIImage imageNamed:@"plus_icon"]
                                                      leftItemImage:nil
                                             
        rightItemImage:[UIImage imageNamed:@"profile_icon"]];
    
    tabBarController.leftBarItems = @[item1];
    tabBarController.rightBarItems = @[item2];
    tabBarController.centerBarItems = @[item3];
    
    tabBarController.centerButtonImage = [UIImage imageNamed:@"plus_icon"];
    
    tabBarController.selectedIndex = 1;
    
    //customize tabBarView,设置底部View的高度,item的数据等信息
    tabBarController.tabBarView.extraTabBarItemHeight = YALExtraTabBarItemsDefaultHeight;
    tabBarController.tabBarView.offsetForExtraTabBarItems = YALForExtraTabBarItemsDefaultOffset;
    tabBarController.tabBarView.backgroundColor = [UIColor colorWithRed:94.0/255.0 green:91.0/255.0 blue:149.0/255.0 alpha:1];
    tabBarController.tabBarView.tabBarColor = [UIColor colorWithRed:72.0/255.0 green:211.0/255.0 blue:178.0/255.0 alpha:1];
    tabBarController.tabBarViewHeight = YALTabBarViewDefaultHeight;
    tabBarController.tabBarView.tabBarViewEdgeInsets = YALTabBarViewHDefaultEdgeInsets;
    tabBarController.tabBarView.tabBarItemsEdgeInsets = YALTabBarViewItemsDefaultEdgeInsets;
    
    UIWindow *window = [UIApplication sharedApplication].delegate.window;
    window.backgroundColor = [UIColor whiteColor];
    window.rootViewController = tabBarController;
    [window makeKeyAndVisible];
}

自己app中的根控制器,对应的是几个按钮点击的时候进入该控制器中。

+ (NSArray *)getRootViewController{
    UIWindow *window = [UIApplication sharedApplication].delegate.window;
    window.backgroundColor = [UIColor whiteColor];
    
    GPFirstController *firstViewController = [[GPFirstController alloc] init];
    UINavigationController *oneNavigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
    oneNavigationController.navigationBar.barStyle = UIBarStyleDefault;
    
    
    GPSecondController *secondViewController = [[GPSecondController alloc] init];
    UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController:secondViewController];
    [secondNavigationController setNavigationBarHidden:YES];
    
    GPThirdController *thirdViewController = [[GPThirdController alloc] init];
    UINavigationController *thirdNavigationController = [[UINavigationController alloc] initWithRootViewController:thirdViewController];
    thirdNavigationController.navigationBar.barStyle = UIBarStyleDefault;
    
    NSArray *ctrlArr = [NSArray arrayWithObjects:oneNavigationController,secondNavigationController,thirdNavigationController,nil];
    
    return ctrlArr;
}

该控件的动画主要是在点击的时候,自定义TabBar中有颜色的View的动态改变,该View的扩展和收缩。并且在收缩的时候位于中间的按钮的图片会发生变化。

- (void)animateTabBarViewExpand {
    CAAnimation *animation = [CAAnimation animationForTabBarExpandFromRect:self.collapsedBounds toRect:self.expandedBounds];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [self.mainView.layer.mask addAnimation:animation forKey:nil];
}

- (void)animateTabBarViewCollapse {
    CAAnimation *animation = [CAAnimation animationForTabBarCollapseFromRect:self.expandedBounds toRect:self.collapsedBounds];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [self.mainView.layer.mask addAnimation:animation forKey:nil];
}

当然这些动画是原来大神封装好了的,你如果有兴趣可以到底层看看。

动画二:登录界面动画

//用手挡住眼睛的动画
[UIView animateWithDuration:0.5 animations:^{
        self.imgLeftHand.frame = CGRectMake(self.imgLeftHand.frame.origin.x - offsetLeftHand, self.imgLeftHand.frame.origin.y + 30, self.imgLeftHand.frame.size.width, self.imgLeftHand.frame.size.height);
        
        self.imgRightHand.frame = CGRectMake(self.imgRightHand.frame.origin.x + 52, self.imgRightHand.frame.origin.y + 30, self.imgRightHand.frame.size.width, self.imgRightHand.frame.size.height);
        
        self.imgLeftHandGone.frame = CGRectMake(self.imgLeftHandGone.frame.origin.x - 70, self.imgLeftHandGone.frame.origin.y, 40, 40);
        
        self.imgRightHandGone.frame = CGRectMake(self.imgRightHandGone.frame.origin.x + 30, self.imgRightHandGone.frame.origin.y, 40, 40);

    } completion:^(BOOL b) {
    }];

该动画其实就是View的frame动画,只需要设置View的起终点的frame,然后放在UIView的animation中。

对于物体下落和碰撞动画,控制器转场动画,cell的动画可以参考我在简书上之前写的文章中,那些都是一个又一个的demo,如果你想把那些动画运用到自己的代码中,你得反复的代码调试。

背景树叶飘落动画

这个动画我们需要用到CADisplayLink,CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。我们在应用中创建一个新的 CADisplayLink 对象,把它添加到一个runloop中,并给它提供一个 target 和selector 在屏幕刷新的时候调用。

一但 CADisplayLink 以特定的模式注册到runloop之后,每当屏幕需要刷新的时候,runloop就会调用CADisplayLink绑定的target上的selector,这时target可以读到 CADisplayLink 的每次调用的时间戳,用来准备下一帧显示需要的数据。例如一个视频应用使用时间戳来计算下一帧要显示的视频数据。在UI做动画的过程中,需要通过时间戳来计算UI对象在动画的下一帧要更新的大小等等。
例如代码:

self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleAction:)];
    self.displayLink.frameInterval = 3;
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

frameInterval
属性是可读可写的NSInteger
型值,标识间隔多少帧调用一次selector
方法,默认值是1,即每帧都调用一次。如果每帧都调用一次的话,对于iOS设备来说那刷新频率就是60HZ也就是每秒60次,如果将frameInterval
设为2 那么就会两帧调用一次,也就是变成了每秒刷新30次。

同时需要注意的是:
在控制器dealloc时

[self.displayLink invalidate];
  self.displayLink = nil;

如果不这样做的话,就会造成内存泄漏。
而在@selector中的方法是3帧调用一次方法,该方法是一片树叶的飘落效果。

- (void)handleAction:(CADisplayLink *)displayLink {
    
    UIImage *image = [UIImage imageNamed:@"leaf"];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    CGFloat scale = arc4random_uniform(70) / 100.0;
    imageView.transform = CGAffineTransformMakeScale(scale, scale);
    CGSize winSize = self.logoView.bounds.size;
    CGFloat x = arc4random_uniform(winSize.width);
    CGFloat y = - imageView.frame.size.height;
    imageView.center = CGPointMake(x, y);
    
    [self.view addSubview:imageView];
    [UIView animateWithDuration:arc4random_uniform(5) animations:^{
        CGFloat toX = arc4random_uniform(winSize.width);
        CGFloat toY = winSize.height - 10;
        
        imageView.center = CGPointMake(toX, toY);
        imageView.transform = CGAffineTransformRotate(imageView.transform, arc4random_uniform(M_PI * 2));
        
        imageView.alpha = 0.2;
    } completion:^(BOOL finished) {
        [imageView removeFromSuperview];
    }];
}

选取logo动画

该动画只需要封装好视图,其动画在创建的时候就可以做相应的处理。
对外只需要创建和设置属性即可:

- (DisperseBtn *)disperseBtn {
    
    if (!_disperseBtn) {
        _disperseBtn = [[DisperseBtn alloc] initWithFrame:CGRectMake(0, 0, 45, 45)];
        _disperseBtn.borderRect = self.view.frame;
        _disperseBtn.layer.cornerRadius = _disperseBtn.height/2.0;
        _disperseBtn.closeImage = [UIImage imageNamed:@"changImage"];
        _disperseBtn.openImage = [UIImage imageNamed:@"changImage"];
        _disperseBtn.right = SCREEN_WIDTH - 10;
        _disperseBtn.centerY = 42;
    }
    return _disperseBtn;
}

//####################################################################
self.logoImageArr = @[@"mylogo1.jpg",@"mylogo2.jpg",@"mylogo3.jpg",@"mylogo4.jpg",@"mylogo5.jpg",];
    NSMutableArray *marr = [NSMutableArray array];
    for (int i = 0; i< self.logoImageArr.count; i++) {
        UIButton *btn = [UIButton new];
        [btn setBackgroundImage:[UIImage imageNamed:self.logoImageArr[i]] forState:UIControlStateNormal];
        [marr addObject:btn];
        btn.tag = i;
        [btn addTarget:self action:@selector(buttonTagget:) forControlEvents:UIControlEventTouchUpInside];
    }
    self.disperseBtn.btns = [marr copy];
//#####################################################################

其余的动画封装时写进去即可。

如果说亮点的话,我觉得主要有很多动画,让app灵动起来。

下面我就归纳一下这个app实现了哪些功能吧。
1.一套完整的用户登录,注册等功能,包括第三方登录,在github代码中我会屏蔽掉APPKey的,如果你需要第三方登录,你得有自己的appkey。
2.数据,大体分为两类,一是本地数据,放在plist文件中,例如除新闻外的数据。另一个是通过免费的api,例如通过百度API,获取新闻数据。
3.地图,采用的是百度地图,标记用户和目的地之间的路线,包括行车路线等信息。
4.其余的都是界面的设计,主要让app更加好看。

说明:app中有些地方点进去后,没有数据,这些纯属正常,是本地plist种无数据。

如果您看到这儿来了,并且你觉得这些动画还不错的话,麻烦点击一下下面的喜欢就可以了。当然下几篇文章也是关于个人对于app的设计和实现,喜欢的话可以点击关注哦~~~。

最后附上github上的地址:https://github.com/CoDancer/Github_proj.

PS:如果毕业设计是IOS的,有什么地方需要帮助的话可以加QQ:2150393078。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容