POP Animation 和 layoutSubviews 的冲突
来源:互联网 发布:2017淘宝店名可以改吗 编辑:程序博客网 时间:2024/06/06 20:30
问题现象
因为 Facebook 的 POP 框架用起来很舒服,于是一直慢慢来习惯了用 POP 做动画,最近做了一个很简单的让一个 Button 旋转的动画,程序却异常的崩溃了,崩溃的地方在 -layoutSubviews
这个地方,如下图目测,应该是因为动画的时候,触发了 -layoutSubviews
方法,于是崩溃,就像这样
并且在终端输出了这样的信息
Jun 27 07:05:17 shenzhenren[5868] <Error>: CGAffineTransformInvert: singular matrix.Jun 27 07:05:17 shenzhenren[5868] <Error>: CGAffineTransformInvert: singular matrix.
原因分析
我们先来看下关键的几处代码是怎么写的:
- (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.isShowAll = NO; [self loadShowAllButton]; } return self;}- (void)layoutSubviews { [super layoutSubviews]; self.showAllButton.top = 8.0f; self.showAllButton.right = self.width;}- (void)loadShowAllButton { self.showAllButton = [[UIButton alloc] init]; [self addSubview:self.showAllButton]; self.showAllButton.width = 36.0f; self.showAllButton.height = 36.0f; self.showAllButton.left = 0.0f; self.showAllButton.top = 0.0f; self.showAllButton.contentMode = UIViewContentModeCenter; [self.showAllButton setImage:[UIImage imageNamed:@"default-show-more-arrow"] forState:UIControlStateNormal]; [self.showAllButton addTarget:self action:@selector(showAllButtonPushed:) forControlEvents:UIControlEventTouchUpInside];}- (void)showAllButtonPushed:(UIButton *)sender { self.isShowAll = !self.isShowAll; POPBasicAnimation *animation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation]; if (self.isShowAll) { animation.toValue = @M_PI; } else { animation.toValue = @0; } [sender pop_removeAllAnimations]; [sender pop_addAnimation:animation forKey:nil];}
上面的代码并不复杂,我想要实现的东西就是在点击按钮的时候,让他旋转180度,再次点击的时候让他转回来
那么根据上面代码,崩溃的过程其实是这样的:
- 点击按钮,触发 POP 动画
- POP 的动画为 UIView 添加对应的 Transform,同时产生动画
- 因为 UIView 添加了 Transform,所以 UIView 触发了需要重新计算 layout 的过程
- 调用
- (void)layoutSubviews
重新计算布局 - 因为 UIView 有 Transform 了,再通过
-setFrame:(GRect)frame
设置 UIView 的 frame 出现错误,参考官方文档
如何解决
既然找到了原因,那么我们就根据原因来跳坑吧,既然是触发了 View 重新计算布局,那么我们不要让他在这个父 View 触发即可,那么最简单粗暴的解决方法就是,创建一个新的 View 包裹住我们需要动画的 View 于是,这样修改
- (void)layoutSubviews { [super layoutSubviews]; self.showAllButtonContainerView.top = 8.0f; self.showAllButtonContainerView.right = self.width;}- (void)loadShowAllButton { self.showAllButtonContainerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 36.0f, 36.0f)]; [self addSubview:self.showAllButtonContainerView]; self.showAllButton = [[UIButton alloc] init]; [self.showAllButtonContainerView addSubview:self.showAllButton]; self.showAllButton.width = 36.0f; self.showAllButton.height = 36.0f; self.showAllButton.left = 0.0f; self.showAllButton.top = 0.0f; self.showAllButton.contentMode = UIViewContentModeCenter; [self.showAllButton setImage:[UIImage imageNamed:@"default-show-more-arrow"] forState:UIControlStateNormal]; [self.showAllButton addTarget:self action:@selector(showAllButtonPushed:) forControlEvents:UIControlEventTouchUpInside];}
其实问题的原因还是没有好好阅读官方文档
0 0
- POP Animation 和 layoutSubviews 的冲突
- layoutSubviews和layoutSubviews
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- initWithFrame和layoutSubviews的用法
- drawRect和layoutSubviews的区别
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- drawRect和layoutSubviews的区别
- UIView的layoutSubviews和drawRect
- UIView的layoutSubviews和drawRect
- iOS横向滚动的scrollView和系统pop手势返回冲突的解决办法
- CSS3中transition和animation冲突
- 暑期二(A)(hdu2041)
- 程序员如何保持优秀
- Android应用程序的debug属性
- Java swing使用皮肤后出现Component creation must be done on Event Dispatch Thread错误解决方法
- session过期时间
- POP Animation 和 layoutSubviews 的冲突
- LeetCode—367. Valid Perfect Square
- Android资源文件中各种XML的作用与解释
- Oracle存储过程基本语法介绍
- sublime text 2 JS 代码提示和代码格式化format
- 网页上的“返回上一页”的几种实现代码
- C和C++中的字符串操作
- Win7(WinDbg) + VMware(Win7) 双机调试环境搭建之三
- iOS 使用Https访问网络(一)