最近有很多人问我,这个效果该怎么实现,那个功能该怎么实现。所以我准备开个专题,找一些app模仿,写一些示例代码,以供大家参考。

第一个下手的就是格瓦拉,没用过的可以下载看看,效果做的还是可以的,专场,和 tabBar的实现都觉得挺有意思的。项目代码

项目代码已经提交到github上 https://github.com/qianhongqiang/QHQGewala

首先讲解下如何实现这样的自定义的tabBar

首先创建了继承于UITabBarController的TranslationTabBarViewController,并且讲其自带的tabBar隐藏,并且创建了一个自定义的tabBar。

-(void)setupTabBar {
self.tabBar.hidden = YES; GewalaTabBar *tabbar = [[GewalaTabBar alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height - 60, [UIScreen mainScreen].bounds.size.width, 60) delegate:self];
[self.view addSubview:tabbar];
}

接着我们就需要实现格瓦拉下面的效果:点击某个按钮后,那个按钮右侧的字,也就是提示文字会出现。然后后面的按钮会往后移,腾出文字的位置。我们可以给每一个button添加1个UIImageView,和一个UILabel,当这个按钮被选中时,增大按钮的宽度,让文本框UILabel显示出来。这里实现一个方法,tabBar的某个按钮被点击后,每个按钮自己移动到对应的位置,并线决定自己是否显示文本等信息。这里味了方便大家看清楚,其实重写setSelected更加好一些。

-(void)tabBar:(GewalaTabBar *)tabBar tabBarItemClickedAtIndex:(NSUInteger)index {
CGRect toRect;
if (index > self.tag) {
toRect = CGRectMake(self.tag * kStandardButtonWidth, 0, kStandardButtonWidth, kStandardButtonHeight);
}else if(index < self.tag) {
toRect = CGRectMake((self.tag + 1) * kStandardButtonWidth, 0, kStandardButtonWidth, kStandardButtonHeight);
}else {
toRect = CGRectMake(self.tag* kStandardButtonWidth, 0, kStandardButtonWidth * 2, kStandardButtonHeight);
} [UIView animateWithDuration:0.35 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0.6 options:0 animations:^{
self.frame = toRect;
if (index > self.tag) {
self.tabBarButtonTitleView.alpha = 0;
self.tabBarButtonTitleView.frame = CGRectMake(0, 0, kStandardButtonWidth, kStandardButtonHeight);
self.tabbarButtonImageView.image = self.item.normalImage;
}else if(index < self.tag) {
self.tabBarButtonTitleView.alpha = 0;
self.tabBarButtonTitleView.frame = CGRectMake(0, 0, kStandardButtonWidth, kStandardButtonHeight);
self.tabbarButtonImageView.image = self.item.normalImage;
}else {
self.tabBarButtonTitleView.alpha = 1;
self.tabBarButtonTitleView.frame = CGRectMake(kStandardButtonWidth, 0, kStandardButtonWidth, kStandardButtonHeight);
self.tabbarButtonImageView.image = self.item.selectedImage;
} } completion:nil];
}

其中下面方法的参数,如果你不知道怎么调整的话,可以在我上面参数的值附近微调,活着干脆不需要弹簧的效果。

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

我们继续实现一个专场,我们观察格瓦拉tabbar的切换。显示的页面不是直接切换,而是最后呈现简谐阻尼的震荡,切换有些类似于导航控制器。说到UIViewController这个东西,其实是设计模式的产物,从本质上来讲,就是UIViewController的view在做显示。

    TranslationDelegate *delegate = [[TranslationDelegate alloc] init];
self.delegate = delegate;
objc_setAssociatedObject(self, &TranslationTabBarViewControllerDelegateAssociationKey, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

如果你直接去改变页面的frame也是可以的,但是为了迎合这种设置模式,所以我们最好去实现开放给我们专场的协议。要实现上面那个delegate。

这个代理类里,只有一个方法

-(id<UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController animationControllerForTransitionFromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
return [[TranslationAnimator alloc] init];
}

又创建了一个TranslationAnimator,这个对象是真正说明,这个专场该如何切换的。

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *containerView = transitionContext.containerView;
UIView *fromView;
UIView *toView; if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
toView = [transitionContext viewForKey:UITransitionContextToViewKey];
} else {
fromView = fromViewController.view;
toView = toViewController.view;
} CGRect fromFrame = [transitionContext initialFrameForViewController:fromViewController];
CGRect toFrame = [transitionContext finalFrameForViewController:toViewController]; fromView.frame = fromFrame;
toView.frame = CGRectOffset(toFrame, toFrame.size.width,0); [containerView addSubview:toView]; NSTimeInterval transitionDuration = [self transitionDuration:transitionContext]; [UIView animateWithDuration:transitionDuration delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0.8 options:0 animations:^{
toView.frame = fromFrame;
} completion:^(BOOL finished) {
BOOL wasCancelled = [transitionContext transitionWasCancelled];
[transitionContext completeTransition:!wasCancelled];
}];
}

有点类似于NSInvoke对象,transitionContext就是一个包涵了你所需要的对象,fromView和toView分别对应的是,从哪个view跳转到哪个view。取到所有信息后,首先将toView的frame设置到屏幕的右侧CGRectOffset(toFrame, toFrame.size.width,0)即向右移动屏幕款,接着就执行弹性动画,将页面移动到屏幕中央。

是不是很简单?只要抓住本质,就很容易。

我爱模仿app之格瓦拉客户端的更多相关文章

  1. 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付

    前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...

  2. 推荐一款App运营工具:AYL爱盈利App榜单监控

    对包括开发者.产品运营.投资人在内的诸多移动互联网从业人员而言,国内Android应用市场和IOS应用市场的榜单变化数据时大家的必修功课之一:看看这段时间所关注的垂直领域里最火的是哪几款应用:看看竞争 ...

  3. 爱pia戏推出PC客户端,为您自动置顶窗口,方便查找

    爱pia戏推出PC客户端, 可以在无法使用插件的时候,使用PC客户端, 将为您自动置顶窗口,方便查看剧本. 百度网盘下载地址: 链接: http://pan.baidu.com/s/1pLpvn5p ...

  4. 王者荣耀交流协会互评Beta版本--爱阅app

    测评人:任思佳 爱阅APP软件说明书地址:http://www.cnblogs.com/szjzsd/p/7881686.html 1.根据NABCD评论作品的选题:   N(Need):相比α发布来 ...

  5. Beta版——爱阅APP功能说明书

    爱阅APP功能说明书 一.引言 通过Alpha发布和一些用户的反馈信息,了解到我们APP存在的问题.针对这些问题我们做了一些修改.以下内容是Beta版的功能说明书. 二.工具 安卓手机 爱阅APP安装 ...

  6. 爱今天 APP 闪退怎么办?

    爱今天 APP 闪退怎么办? 爱今天是一款简洁优秀的时间记录 APP. 但也有一些小 Bug,可能是因为不同的手机兼容问题,在添加时间时会出现闪退现象. 可能是因为自己修改了添加时间的方式. 可以通过 ...

  7. Thunder团队Final版爱阅app发布视频

    视频链接:https://www.bilibili.com/video/av17008792/ 视频简介:首先出现的是我们团队的logo,接着是Final版爱阅app的功能展示,紧接着是我们团队的开发 ...

  8. final版——爱阅APP功能说明书

    爱阅APP功能说明书 一.引言 以下内容是final版的功能说明书. 新增功能: 1.WiFi传书 2.书友群跳转 3.网址内部打开 4.设置-->关于爱阅 5.设置-->TXT文本的翻页 ...

  9. Thunder——爱阅app(测评人:方铭)

    B.Thunder——爱阅app(测评人:方铭) 一.基于NABCD评论作品,及改进建议 每个小组评论其他小组Alpha发布的作品: 1.根据(不限于)NABCD评论作品的选题: 2.评论作品对选题的 ...

随机推荐

  1. ORACLE数据库存储空间使用情况查询

    使用系统sys或者dba权限的账户创建视图如下: 1. 主要从数据库的表dba_data_files,dba_segments两张表中获取.2. 默认数据库保存的是byte单位,转换关系如下: 102 ...

  2. Windows 10 装机回忆录

    Frank.Han 标记: Windows,快捷键,安装 2015年10月我便更新了Win10系统,一直用着很顺手,比起Win8.x,他更像Win7的嫡系版本. 屏蔽掉系统自带的平板服务(小娜.地理位 ...

  3. 洛谷P1220关路灯[区间DP]

    题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯. 为了给村 ...

  4. bash 脚本编程 利用 “=” 赋值时,左右不能留空格

    对脚本变量用“=”赋值时, "=" 左右不能留有空格,否则会提示错误. 比如以下例子: #!/bin/bash BEGIN_TIME = `date +%H:%M:%S` ./a. ...

  5. 物联网平台设计心得:你所不知道的CRC校验

    在物联网平台设计过程中,我的中间件一方面需要处理来自于硬件端的包,另一方面需要处理来自于用户端的包,用户端包括web端和手机端等等.所以编写一个统一的CRC认证是非常必须要. 那么,在设计开始,CRC ...

  6. Jsoup开发网站客户端第二篇,图片轮播,ScrollView兼容ListView

    最近一段日子忙的焦头烂额,代码重构,新项目编码,导致jsoup开发网站客户端也没时间继续下去,只能利用晚上时间去研究了.今天实现美食网首页图片轮播效果,网站效果图跟Android客户端实现如图: 从浏 ...

  7. sql server 排名函数:DENSE_RANK

    一.需求 之前sql server 的排名函数用得最多的应该是RoW_NUMBER()了,我通常用ROW_NUMBER() + CTE 来实现分页:今天逛园,看到另一个内置排名函数还不错,自己顺便想了 ...

  8. 初次尝试用Kotlin实现Android项目

    Kotlin: The Swift of Android 起这个文内标题的原因很简单,就是对Kotlin抱有希望--能使Android的开发更简洁.高效及安全.知道Kotlin是从简书的一篇短文,越来 ...

  9. nginx、php-fpm二三问

    php-cgi为什么没了? php-fpm子进程是干啥的?php-cgi是原来php自带的fastcgi进程管理器,有一些缺点,比如不能平滑重启,进程管理差.php-fpm可以看做升级版的php-fp ...

  10. Learning to rank 介绍

    PS:文章主要转载自CSDN大神hguisu的文章"机器学习排序":          http://blog.csdn.net/hguisu/article/details/79 ...