iOS 仿淘宝加入购物车前选择尺寸,规格弹窗的向内凹陷折叠动画效果和标签流布局

本文主要是介绍iOS 仿淘宝加入购物车前选择尺寸,规格弹窗的向内凹陷折叠动画效果和标签流布局,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   项目中做了一套电商的购物流程,很多都是照着淘宝做的,之前一直疑惑淘宝的弹框

时,底部的控制器向内凹陷是什么鬼,这动画有点理解不了,一直就放着没有做,这周

突然在github上看到一个老外写的库,真的有点强啊,我这里简单写了个Demo给大家分析下,然后再用这个牛B的库集成下展示最终成果


老规矩,看图说话,一个是自己写的Demo,一个是通过库展示给大家      


在介绍库之前先自己写个Demo捋一捋思路

第一个View:根部控制器,我们设置为黑色


第二个View:根部VC上面加载另一个用来做动画的AnimationVC (addChildViewController)


第三个View:在AnimationVC上面add一个MaskView


第四个View:最后就是弹出的最终popView(加载到Window上面,类似于系统的Alert or sheet)


第一步:布局View

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. // 设置底部的背景颜色 (第一层)  
  2.     self.view.backgroundColor = [UIColor blackColor];  
  3.       
  4.     // 设置AnimationVC的属性 (第二层)  
  5.     self.mkjVC = [[MKJAnimationViewController alloc] init];  
  6.     self.mkjVC.view.backgroundColor = [UIColor whiteColor];  
  7.     self.mkjVC.view.frame = CGRectMake(00, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);  
  8.     self.mkjVC.title = @"Animation";  
  9.     self.nvc = [[UINavigationController alloc] initWithRootViewController:self.mkjVC];  
  10.   
  11.     [self addChildViewController:self.nvc];  
  12.     [self.view addSubview:self.nvc.view];  
  13.     // 设置开始按钮  
  14.     UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];  
  15.     [button setTitle:@"show" forState:UIControlStateNormal];  
  16.     [button setTitleColor:[UIColor purpleColor] forState:UIControlStateNormal];  
  17.     [button addTarget:self action:@selector(clickShow:) forControlEvents:UIControlEventTouchUpInside];  
  18.     button.frame = CGRectMake(0010030);  
  19.     button.center = self.nvc.view.center;  
  20.     [self.nvc.view addSubview:button];  
  21.       
  22.     // 设置maskView (第三层)  
  23.     self.maskView = [[UIView alloc] initWithFrame:self.mkjVC.view.bounds];  
  24.     self.maskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];  
  25.     self.maskView.alpha = 0;  
  26.     [self.nvc.view addSubview:self.maskView];  
  27.       
  28.     // 设置popVIew (第四层)  
  29.     self.popView = [[UIView alloc] initWithFrame:CGRectMake(0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height / 2)];  
  30.     self.popView.backgroundColor = [UIColor redColor];  
  31.     self.popView.layer.shadowColor = [UIColor blackColor].CGColor;  
  32.     self.popView.layer.shadowOffset = CGSizeMake(33);  
  33.     self.popView.layer.shadowOpacity = 0.8;  
  34.     self.popView.layer.shadowRadius = 5.0f;  
  35.       
  36.     // closeButton  
  37.     UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];  
  38.     [button1 setTitle:@"Cancel" forState:UIControlStateNormal];  
  39.     [button1 setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];  
  40.     button1.frame = CGRectMake(5510030);  
  41.     [button1 addTarget:self action:@selector(close:) forControlEvents:UIControlEventTouchUpInside];  
  42.     [self.popView addSubview:button1];  

第二步:形变动画(最关键,分两段)

先解释下M34是什么东西

transform本身就是个结构体,首先要实现View的透视效果(近大远小),就是通过它来实现的

CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;

rotationAndPerspectiveTransform.m34 = 1.0 / -500;


m34负责z轴方向的translation(移动),m34= -1/D,  默认值是0,也就是说D无穷大,这意味layer in projection plane(投射面)和layer in world coordinate重合了。


D越小透视效果越明显。所谓的D,是eye(观察者)到投射面的距离


形变1

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. // 第一次形变  
  2. - (CATransform3D)transform1{  
  3.     // 每次进来都进行初始化 回归到正常状态  
  4.     CATransform3D form1 = CATransform3DIdentity;  
  5.     // m34就是实现视图的透视效果的(俗称近大远小)  
  6.     form1.m34 = 1.0/-900;  
  7.     //缩小的效果  
  8.     form1 = CATransform3DScale(form10.950.951);  
  9.     //x轴旋转  
  10.     form1 = CATransform3DRotate(form115.0 * M_PI/180.0100);  
  11.     return form1;  
  12.       
  13. }  

形变2

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. // 第二次形变  
  2. - (CATransform3D)transform2{  
  3.     // 初始化 再次回归正常  
  4.     CATransform3D form2 = CATransform3DIdentity;  
  5.     // 用上面用到的m34 来设置透视效果  
  6.     form2.m34 = [self transform1].m34;  
  7.     //向上平移一丢丢 让视图平滑点  
  8.     form2 = CATransform3DTranslate(form20self.view.frame.size.height * (-0.08), 0);  
  9.     //最终再次缩小到0.8倍  
  10.     form2 = CATransform3DScale(form20.80.81);  
  11.     return form2;  
  12. }  



第三步:动画的开始和结束

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. // 点击动画开始  
  2. - (void)clickShow:(UIButton *)button  
  3. {  
  4.     // 开始的时候把popView加载到window上面去,类似于系统的actionSheet之类的弹窗  
  5.     [[UIApplication sharedApplication].windows[0] addSubview:self.popView];  
  6.     // 先计算出popView的弹出高度  
  7.     CGRect rec = self.popView.frame;  
  8.     rec.origin.y = self.view.bounds.size.height / 2;  
  9.     [UIView animateWithDuration:0.3 animations:^{  
  10.         // 先逆时针X轴旋转 缩小到0.95呗,向内凹陷的透视效果 如果不进行下一波操作,那么这个效果就是View向内倾斜了  
  11.         self.nvc.view.layer.transform = [self transform1];  
  12.     } completion:^(BOOL finished) {  
  13.         // 倾斜完之后,我们再进行第二段操作,先把transform设置为初始化,然后透视还是和第一段一样,让他回归到正常(不倾斜)同时让大小动画为0.8,高度向上移动一点点,maskView出来,popView也顺着出来指定高度  
  14.         [UIView animateWithDuration:0.3 animations:^{  
  15.               
  16.             self.nvc.view.layer.transform = [self transform2];  
  17.             self.maskView.alpha = 0.5;  
  18.             self.popView.frame = rec;  
  19.         } completion:^(BOOL finished) {  
  20.         }];  
  21.     }];  
  22. }  

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. // 动画关闭  
  2. - (void)close:(UIButton *)button  
  3. {  
  4.     // 先计算出popView回去的位置  
  5.     CGRect rec = self.popView.frame;  
  6.     rec.origin.y = self.view.bounds.size.height;  
  7.       
  8.     // 动画回去  
  9.     [UIView animateWithDuration:0.4 animations:^{  
  10.         // popView回去  
  11.         self.popView.frame = rec;  
  12.         // mask回0  
  13.         self.maskView.alpha = 0;  
  14.         // 在进行旋转,向内凹陷,大小缩为0.95倍  
  15.         self.nvc.view.layer.transform = [self transform1];  
  16.           
  17.     } completion:^(BOOL finished) {  
  18.           
  19.         // 折叠完之后让transform回归到正常水平就好了  
  20.         [UIView animateWithDuration:0.3 animations:^{  
  21.               
  22.             self.nvc.view.layer.transform = CATransform3DIdentity;  
  23.               
  24.         } completion:^(BOOL finished) {  
  25.               
  26.             // 把popView从Window中移除  
  27.             [self.popView removeFromSuperview];  
  28.               
  29.         }];  
  30.           
  31.     }];  
  32.       
  33. }  

    Demo就这样,该有的效果就出来了,大伙可以自己试试



OK,现在来个成熟的框架,效果那肯定是杠杠的KNSemiModalViewController点击打开链接

先看看官方给出的效果图



可以弹控制器也可以弹View,自定义非常高

-(void)presentSemiViewController:(UIViewController*)vc;

-(void)presentSemiViewController:(UIViewController*)vc withOptions:(NSDictionary*)options;

-(void)presentSemiView:(UIView*)vc;

-(void)presentSemiView:(UIView*)view withOptions:(NSDictionary*)options;


首先:导入source里面的两个文件,在需要的地方包含这个类扩展

然后:把需要弹出来的信息写在另一个控制器里面,直接在想要弹的地方调用

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. [self.navigationController presentSemiViewController:self.chooseVC withOptions:@{  
  2.                                                                KNSemiModalOptionKeys.pushParentBack    : @(YES),  
  3.                                                                KNSemiModalOptionKeys.animationDuration : @(2.0),  
  4.                                                                KNSemiModalOptionKeys.shadowOpacity     : @(0.3),  
  5.                                                                KNSemiModalOptionKeys.backgroundView : [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background_01"]]  
  6.                                                                }];  

喂喂喂,结束了么,我刚买了瓜子和饮料来看???你就给我看这个?

没错,结束了,各回各家,各找各妈,瓜子和饮料都给我吧


噢,对了,弹出来的View里面的tag布局传送门 点击打开链接tag布局


这里大家用库的时候绝对会遇到几个坑,最常见的给大家罗列下

1.问题一

ld: 1 duplicate symbol for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

方法:

add typedef

typedef NS_ENUM(NSUInteger, KNSemiModalTransitionStyle) {

KNSemiModalTransitionStyleSlideUp,

KNSemiModalTransitionStyleFadeInOut,

KNSemiModalTransitionStyleFadeIn,

KNSemiModalTransitionStyleFadeOut,

};


2.问题二

Exception: Defaults must have been set when accessing 

如果你要的根控制器是有导航栏的

[self.navigationController presentSemiViewController....

如果没有导航栏

[self presentSemiViewController....

不然我的做,你就飞了


可以了,再BB就要被打了


自己写的Demo:点击打开链接简单Demo


用库集成的超级Demo:点击打开链接超级Demo


tag标签布局传送:点击打开链接Tag



少年,点个赞再走好么,不会少块肉的。。。。。。


点你妹啊,你知道按一下鼠标有多累么!!??!?会触电的!!!


好吧。。。。。。

    


注意啦


如果你Push的时候没这么做,你的界面会

出BUG,下面是我的解决方案

[objc]  view plain copy
在CODE上查看代码片 派生到我的代码片
  1. - (void)show:(UITapGestureRecognizer *)tap  
  2. {  
  3.     if (!self.chooseVC)  
  4.     {  
  5.           
  6.         self.chooseVC = [[ChooseGoodsPropertyViewController alloc] init];  
  7.       
  8.     }  
  9.     self.chooseVC.enterType = FirstEnterType;  
  10.     __weak typeof(self)weakSelf = self;  
  11.     self.chooseVC.block = ^{  
  12.   
  13.         NSLog(@"点击回调去购物车");  
  14.         // 下面一定要移除,不然你的控制器结构就乱了,基本逻辑层级我们已经写在上面了,这个效果其实是addChildVC来的,最后的展示是在Window上的,一定要移除  
  15.         [weakSelf.chooseVC.view removeFromSuperview];  
  16.         [weakSelf.chooseVC removeFromParentViewController];  
  17.         weakSelf.chooseVC.view = nil;  
  18.         weakSelf.chooseVC = nil;  
  19.           
  20.         MKJShoppingCartViewController *shop = [MKJShoppingCartViewController new];  
  21.         [weakSelf.navigationController pushViewController:shop animated:YES];  
  22.           
  23.     };  
  24.     self.chooseVC.price = 256.0f;  
  25.     [self.navigationController presentSemiViewController:self.chooseVC withOptions:@{  
  26.                                                                                      KNSemiModalOptionKeys.pushParentBack    : @(YES),  
  27.                                                                                      KNSemiModalOptionKeys.animationDuration : @(0.6),  
  28.                                                                                      KNSemiModalOptionKeys.shadowOpacity     : @(0.3),  
  29.                                                                                      KNSemiModalOptionKeys.backgroundView : [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background_01"]]  
  30.                                                                                     }];  
  31. }  

这篇关于iOS 仿淘宝加入购物车前选择尺寸,规格弹窗的向内凹陷折叠动画效果和标签流布局的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/279858

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。