我爱模仿app之格瓦拉客户端
最近有很多人问我,这个效果该怎么实现,那个功能该怎么实现。所以我准备开个专题,找一些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之格瓦拉客户端的更多相关文章
- 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付
前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...
- 推荐一款App运营工具:AYL爱盈利App榜单监控
对包括开发者.产品运营.投资人在内的诸多移动互联网从业人员而言,国内Android应用市场和IOS应用市场的榜单变化数据时大家的必修功课之一:看看这段时间所关注的垂直领域里最火的是哪几款应用:看看竞争 ...
- 爱pia戏推出PC客户端,为您自动置顶窗口,方便查找
爱pia戏推出PC客户端, 可以在无法使用插件的时候,使用PC客户端, 将为您自动置顶窗口,方便查看剧本. 百度网盘下载地址: 链接: http://pan.baidu.com/s/1pLpvn5p ...
- 王者荣耀交流协会互评Beta版本--爱阅app
测评人:任思佳 爱阅APP软件说明书地址:http://www.cnblogs.com/szjzsd/p/7881686.html 1.根据NABCD评论作品的选题: N(Need):相比α发布来 ...
- Beta版——爱阅APP功能说明书
爱阅APP功能说明书 一.引言 通过Alpha发布和一些用户的反馈信息,了解到我们APP存在的问题.针对这些问题我们做了一些修改.以下内容是Beta版的功能说明书. 二.工具 安卓手机 爱阅APP安装 ...
- 爱今天 APP 闪退怎么办?
爱今天 APP 闪退怎么办? 爱今天是一款简洁优秀的时间记录 APP. 但也有一些小 Bug,可能是因为不同的手机兼容问题,在添加时间时会出现闪退现象. 可能是因为自己修改了添加时间的方式. 可以通过 ...
- Thunder团队Final版爱阅app发布视频
视频链接:https://www.bilibili.com/video/av17008792/ 视频简介:首先出现的是我们团队的logo,接着是Final版爱阅app的功能展示,紧接着是我们团队的开发 ...
- final版——爱阅APP功能说明书
爱阅APP功能说明书 一.引言 以下内容是final版的功能说明书. 新增功能: 1.WiFi传书 2.书友群跳转 3.网址内部打开 4.设置-->关于爱阅 5.设置-->TXT文本的翻页 ...
- Thunder——爱阅app(测评人:方铭)
B.Thunder——爱阅app(测评人:方铭) 一.基于NABCD评论作品,及改进建议 每个小组评论其他小组Alpha发布的作品: 1.根据(不限于)NABCD评论作品的选题: 2.评论作品对选题的 ...
随机推荐
- CF731C. Socks[DFS 贪心]
C. Socks time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- JS数组去重比较
数组去重复是一个常见的需求,我们暂时考虑同类型的数组去重复.主要是理清思路和考虑执行性能. for循环删除后面重复的 var uniqueFor = function(arr) { for (var ...
- 可能是史上最强大的js图表库——ECharts带你入门
PS:之前的那篇博客Highcharts——让你的网页上图表画的飞起 ,评论中,花儿笑弯了腰 和 StanZhai 两位仁兄让我试试 ECharts ,去主页看到<Why ECharts ?&g ...
- 关于javascript中this的那点事
this可谓是JavaScript中的开发神器,使用得当的话不仅有事半功倍的效果,而且代码的逼格也更高.但是既然是神器,如果你没有足够的功力的话,那么就不要使用它,否则就有可能自毁身亡.曾几何时,我偶 ...
- URLConnection类介绍
URLConnection是一个功能强大的抽象类,它表示指向URL指定资源的活动连接. 与URL类相比,它与服务器的交互提供了更多的控制机制.尤其服务器是HTTP服务器,可以使用URLConnecti ...
- Webpack 中文指南
来源于:http://webpackdoc.com/index.html Webpack 是当下最热门的前端资源模块化管理和打包工具.它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资 ...
- js精确加减乘除
//加法函数function accAdd(arg1, arg2) { var r1, r2, m; try { r1 = arg1.toString().split(".")[1 ...
- jQuery之XML的加载和解析
1.XML(eXtensible Markup Language)即可扩展标记语言,与HTML一样,都是SGML标准通用语言.语法如下: 任何起始标签都必须有一个结束标签. 可以采用另一种简化语法,即 ...
- Block产生的内存泄露,以及解决方法
前言: 在ARC(自动引用技术)前,Objective-c都是手动来分配释放 释放 计数内存,其过程非常复杂. ARC技术推出后,貌似世界和平了很多,但是其实ARC并不等同于Java或者C#中的垃圾回 ...
- iOS音乐播放器相关
iOS音乐播放器框架主要有两大类:AvPlayer.AvaudioPlayer AvPlayer 能播放本地及网络歌曲 AvaudioPlayer 能播放本地歌曲.有相关代理方法(其实也可以播放网络歌 ...