填充颜​​色动画在动画中调用块时闪烁确实停止了

2023-12-02

我无法弄清楚为什么动画块完成后动画从 fromValue 闪烁到 toValue。我知道,完成动画后,您必须将 CALayer 的值设置为动画的结束状态,以保持其外观一致。然而,无论我以什么顺序调用这些方法,我都会得到闪烁的结果。我正在做的是用 biezer 路径绘制一个复选标记,然后一旦 strokeEnd 动画完成,我就通过动画 fillColor 属性来填充复选标记。当用户选择与复选标记关联的 tableviewcell 的行时,填充复选标记函数和重置复选标记函数都会被触发。哦,是的,我正在使用自动布局,如果这有什么区别的话。

所以我想知道一些事情 1)显示表视图单元格后,我调用公共函数 shudSetCheckmarkToCheckedState ,它将布尔值 self.userSelectedCheckmark 设置为函数中传递的参数 isChecked 。从那里我调用[self setNeedsLayout],它触发layoutSubviews并调用shouldDrawCheckmark...函数。我这样做的原因是因为如果我第一次绘制单元格时不这样做,则没有框架设置,所以我的绘图看起来很乱。那么我应该在每次更改 userSelectedCheckmark 属性时调用 setNeedsLayout 还是有更好的方法。

2)为什么动画完成后复选标记会闪烁。我想我知道为什么,因为当动画完成时,图层属性将重置为图层开始动画时的相同状态。那么我该如何解决这个问题呢?我只是在动画结束前触发一个计时器来改变填充颜色一毫秒,但这感觉不对。

顺便说一句,这是代码

typedef void (^animationCompletionBlock)(void);
#define kAnimationCompletionBlock @"animationCompletionBlock"

#import "CheckmarkView.h"
#import "UIColor+HexString.h"

@interface CheckmarkView()
@property (nonatomic,strong) CAShapeLayer *checkmarkLayer;
@property (nonatomic,assign) BOOL userSelectedCheckmark;
- (void)shouldDrawCheckmarkToLayerWithAnimation:(BOOL)animateCheckmark;
@end

@implementation CheckmarkView

#pragma mark - Lifecycle
/**********************/
- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.translatesAutoresizingMaskIntoConstraints = FALSE;
        self.layer.cornerRadius = 5.0;
        [self setClipsToBounds:TRUE];
    }
    return self;
}
- (void)layoutSubviews{
   [self shouldDrawCheckmarkToLayerWithAnimation:self.userSelectedCheckmark];
}

#pragma mark - Public Methods
/***************************/
- (void)shouldSetCheckmarkToCheckedState:(BOOL)isChecked{
    self.userSelectedCheckmark = isChecked;
    [self setNeedsLayout];
}

#pragma mark - Private Methods
/****************************/
- (void)shouldDrawCheckmarkToLayerWithAnimation:(BOOL)animateCheckmark{

    if(self.userSelectedCheckmark){

        CGRect superlayerRect = self.bounds;
        if(!self.checkmarkLayer){

            self.checkmarkLayer = [CAShapeLayer layer];
            [self.checkmarkLayer setStrokeColor:[UIColor whiteColor].CGColor];

            UIBezierPath *checkMarkPath = [UIBezierPath bezierPath];
            //Start Point
            [checkMarkPath moveToPoint:CGPointMake(CGRectGetMinX(superlayerRect) + 5, CGRectGetMinY(superlayerRect) + 14)];

            //Bottom Point
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMidX(superlayerRect), CGRectGetMaxY(superlayerRect) - 4)];

            //Top Right of self.checkmarkLayer
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMaxX(superlayerRect) - 5, CGRectGetMinY(superlayerRect) + 8)];
            [checkMarkPath addLineToPoint:CGPointMake(checkMarkPath.currentPoint.x - 3, checkMarkPath.currentPoint.y - 4)];

            //Top Middle Point
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMidX(superlayerRect) - 1, CGRectGetMidY(superlayerRect) + 2)];

            //Top left of self.checkmarkLayer
            [checkMarkPath addLineToPoint:CGPointMake(CGRectGetMinX(superlayerRect) + 7, CGRectGetMinY(superlayerRect) + 10)];
            [checkMarkPath closePath];
            [self.checkmarkLayer setPath:checkMarkPath.CGPath];
        }

        self.layer.backgroundColor = [UIColor colorWithHexString:UIColorOrangeB0].CGColor;
        [self.checkmarkLayer setFillColor:[UIColor colorWithHexString:UIColorOrangeB0].CGColor];
        [self.layer addSublayer:self.checkmarkLayer];

        if(animateCheckmark){

            animationCompletionBlock block;
            block = ^(void){
                [self.checkmarkLayer setFillColor:[UIColor whiteColor].CGColor];
            };

            CABasicAnimation *strokeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
            [strokeAnimation setBeginTime:0.0];
            [strokeAnimation setFromValue:@(0.0f)];
            [strokeAnimation setToValue:@(1.0f)];
            [strokeAnimation setDuration:.8];

            CABasicAnimation *fillAnimation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
            [fillAnimation setBeginTime:strokeAnimation.duration + .2];
            [fillAnimation setDuration:.2];
            [fillAnimation setFromValue:(id)[UIColor colorWithHexString:UIColorOrangeB0].CGColor];
            [fillAnimation setToValue:(id)[UIColor whiteColor].CGColor];

            CAAnimationGroup *group = [CAAnimationGroup animation];
            group.delegate = self;
            [group setDuration:1.5];
            [group setAnimations:@[strokeAnimation,fillAnimation]];
            [group setValue:block forKey:kAnimationCompletionBlock];
            [self.checkmarkLayer addAnimation:group forKey:nil];
        }
    }
    else{
        self.layer.backgroundColor = [UIColor colorWithHexString:UIColorWhiteOffset].CGColor;
        [self.checkmarkLayer setFillColor:[UIColor colorWithHexString:UIColorOrangeB0].CGColor];
        [self.checkmarkLayer removeFromSuperlayer];
    }

}


#pragma mark - CAAnimationBlock
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
    animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
    if (theBlock)
        theBlock();
}

回答你的第一个问题

每个运行循环只会调用一次layoutSubviews。您可以根据需要多次调用 [self setNeedsLayout],而不必担心不必要地布局视图会影响性能。

参考自: 库比切克、吉姆. “滥用 UIView。” 2012 年 10 月 11 日。http://jimkubicek.com/blog/2012/10/11/using-uiview/

要回答你的第二个问题,你对它闪烁的原因是正确的。问题在于,无法保证在重置图层外观之前调用animationDidStop回调方法。

有几种方法可以解决此问题,以下方法仅涉及添加一些额外的代码,而无需更改现有代码。

//kCAFillModeForwards: the animatable properties take on the end value once it has finished
[strokeAnimation setFillMode:kCAFillModeForwards];
[strokeAnimation setRemovedOnCompletion:NO];
[fillAnimation setFillMode:kCAFillModeForwards];
[fillAnimation setRemovedOnCompletion:NO];
[group setFillMode:kCAFillModeForwards];
[group setRemovedOnCompletion:NO];

[self.checkmarkLayer addAnimation:group forKey:nil];

当 CAAnimation 完成时,它会将自身从图层中删除并导致图层重置,因此我们要做的第一件事就是阻止动画被删除。

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
    animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
    if (theBlock)
        theBlock();

[self.checkmarkLayer removeAllAnimations];

}

当调用animationDidStop方法时,我们像以前一样设置图层的属性,然后从图层中删除动画。

另一件需要考虑的事情是,当您更改 CALayer 的外观时,它会隐式(自动)动画化。因此,当您设置完成块时,您需要明确告诉核心动画不要设置动画

animationCompletionBlock block;
        block = ^(void){
            [CATransaction begin];
            [CATransaction setDisableActions:YES];
            [self.checkmarkLayer setFillColor:[UIColor whiteColor].CGColor];
            [CATransaction commit];
        };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

填充颜​​色动画在动画中调用块时闪烁确实停止了 的相关文章

  • 获取 iOS 5 中最后一个重定向的 url?

    有人可以发布最简单的工作代码 当我 GET 请求一个 url 时 它可以获取最后一个重定向的 url nth 吗 我知道我需要使用异步请求 但我无法制定出解决问题的完整工作代码 我正在使用 ios5 因此我可以使用 ios5 中最新添加的异
  • UIWebView didFinishLoading 多次触发

    我有一些代码需要在 a 之后运行UIWebView完成加载文档 为此我设置了UIWebView的委托给我的控制器 并实现了webViewDidFinishLoading method 这会被多次调用 具体取决于要加载的页面类型 我不确定是否
  • 如何在 Xcode 4.5 中添加旧版本的 iOS SDK

    我在这里复制了 iOS 5 1 SDK 应用程序 Xcode app Contents Developer Platforms iPhoneOS platform Developer SDKs 但是 我仍然无法在 Xcode 中选择基础 S
  • ipatool 失败并出现异常:#

    将 Xcode 升级到 9 0 1 版本后 在我的项目之一中导出为 iPA 时 我遇到错误 ipatool 失败 出现异常 NoMethodError undefined method toolsPath for nil NilClass
  • 通过 NSDate 过滤 Realm 中的查询会抛出 NSInvalidArgumentException

    我到处寻找 甚至访问了一些带有永远不会消失的病毒警告消息的可疑网站 但我无法弄清楚这一点 我只是想过滤Results
  • 检测 AVPlayerViewController 是否正在播放视频或正在缓冲并向播放器添加覆盖

    我必须检测视频是否处于播放模式或缓冲模式 我正在从 URL 加载视频 我已经尝试了下面的代码 我可以在视频开始播放后进行跟踪 但不能在视频处于缓冲状态时进行跟踪 另外 我想在我的播放器中添加覆盖视图 我尝试在 AVPlayer 中添加叠加层
  • 函数“FBSDK_NOT_DESIGNATED_INITIALIZER”的隐式声明在 C99 中无效预期“)”

    我正在使用适用于 iOS 4 6 0 的 Facebook SDK 今天将 cocoapods 更新到 0 38 2 后遇到了上述错误 我不确定这个错误与 cocoapods 有什么关系 Error screenshot 我遇到过同样的问题
  • 外围 BLE 设备的唯一标识符

    所以我有外围设备BLE设备 我需要一些标识符以便稍后与另一部 iPhone 共享 我连接的示例iPhone A 为外围设备 iPhone A 将外围设备的标识符保存到数据库中 稍后我可以轻松获取iPhone B 并连接到通过该标识符找到的外
  • 记录使用 OpenAL 播放的样本

    我在 iOS 上使用 OpenAL 同时播放 9 个循环 为了使循环 100 同步 它们开始在不同的线程上运行 有关使用 OpenAL 记录正在播放的内容的任何指示 教程 如果我使用不同的线程 我会遇到录制问题吗 iOS 上的 OpenAL
  • 带有内容矩形抖动的核心动画

    在我的 益智 游戏中 这些碎片是使用CALayer对于每件作品 有 48 块 在 8x6 网格中 每块为 48x48 像素 我不确定这是否是太多层 但如果这不是最好的解决方案 我不知道什么是 因为使用 Quartz2D 每帧重新绘制整个显示
  • 是否可以?相机 API ios [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想在应用程序中实现一项功能 当用户
  • 从 Google/Facebook 帐户重新验证用户身份

    因此 我需要创建一个 REST API 来为 IOS 应用程序提供功能 我们允许用户仅使用普通帐户或使用脸书 谷歌登录 我最近一直在阅读 OAuth 我想我了解在我的情况下如何使用 OAuth 的过程 当用户使用脸书 谷歌登录 在我的应用程
  • 在 Alamofire 中快速发送 GET 请求中的 json 对象

    我正在尝试执行一个绑定了 json 对象的 GET 请求 这就是我生成 JSON 对象的方式 let jsonObject String AnyObject ean code type match value 16743799 然后我执行了
  • 如何在文本末尾添加按钮,如 Facebook 的“继续阅读”?

    当状态帖子太长时 Facebook 应用程序会剪切文本并在末尾添加 继续阅读 它如何知道在哪里剪切文本并添加 继续阅读 不仅仅是向 textView 或标签添加按钮 而是如何剪切字符串 例如 在下图中 我将行数限制为 7 我可以在 text
  • Swift NotificationCenter 删除观察者最快的方法

    我正在添加一些观察员viewController applicationWillResignActive applicationDidEnterBackground 以及许多其他人 我想删除self作为一行中所有已注册通知的观察者 我的问题
  • 使用 iOS 设备作为 TCP 客户端 - 无 Bonjour

    我想使用 iOS 设备作为 TCP 客户端 但我找不到可理解的 API 指南 示例来说明如何做到这一点 我试过SimpleNetworkStreams and PictureSharing 但他们都使用 Bonjour 我可以轻松建立 UD
  • iPhone / iPad IOS 应用程序仪器内存计数与 task_info 内存计数

    我一直在使用 Instruments Leak Tester 它给出了大约 1 3 meg 的应用程序总分配数字 但是 当使用 task info 时 它会报告更大的内存量 例如 10 20 meg 我想我只是想确认task info正在返
  • Apple Mach-O 链接器错误 armv7s 和 libGoogleAdMobAds.a

    我刚刚升级了我的应用程序以在新的 iPhone5 模拟器上运行 但是当我尝试为我的 iPhone 4S 设备构建它时 我收到此 Apple Mach O Liner 错误 ld 文件是通用的 3片 但不包含 n armv7s 切片 User
  • extern NSString *const 在类中。

    你好 我有这个头文件 import
  • Swift 3 和 Xcode8 - init 的使用不明确

    在我安装 Xcode 8 并将项目转换为 Swift 3 之前 以下行没问题 现在转换后看起来像这样 let valueData Data Data bytes UnsafePointer

随机推荐

  • 如何在角度独立组件中使用动画

    我正在尝试设置一个有角度的项目 独立组件 动画 Component selector my app standalone true imports CommonModule BrowserAnimationsModule template
  • 发送点击消息到另一个应用程序进程

    我有一个场景 我需要将点击事件发送到独立的应用程序 我使用以下代码启动了该应用程序 private Process app app new Process app StartInfo FileName app path app StartI
  • 有没有办法在Python中引用当前函数?

    我想要一个函数来引用它自己 例如是递归的 所以我做了类似的事情 def fib n return n if n lt 1 else fib n 1 fib n 2 大多数时候这都很好 但是fib实际上并不指代其自身 它指的是绑定fib在封闭
  • 将 System.Drawing.Bitmap 缩放到给定大小,同时保持纵横比

    我想扩展一个System Drawing Bitmap至少小于某个固定的宽度和高度 这是为了在网站上生成图片库的缩略图 所以我想保持纵横比相同 我有一些解决方案 但似乎没有一个真正能满足我的需要 它们围绕基于保持宽度或高度相同但不改变两者的
  • 模拟按键 C#

    I want to simulate F5 key press in my C program When IE is open I want to be able refresh my website automatically 我怎样才能
  • Java 中的动态泛型类型

    如果我有一个使用泛型类型的类 例如 public class Record
  • 谷歌地图 API 从 v2 升级到 v3,建议

    我在我的网络应用程序中完全集成了谷歌地图版本 2 具有获取方向 集群标记 选项卡式信息窗口 上下文菜单 右键单击 等功能 该实现的设计非常糟糕 导致了一些问题 所以现在我需要修改核心实现以更好的设计 我正在考虑升级到 google 地图 A
  • 不区分大小写的列表搜索

    我有一个清单testList包含一堆字符串 我想添加一个新字符串到testList仅当列表中尚不存在时 因此 我需要对列表进行不区分大小写的搜索并使其高效 我不能使用Contains因为这没有考虑外壳 我也不想用ToUpper ToLowe
  • Symfony2 表单中的数据对象与需要填写的内容不完全匹配

    我们有监控服务 我们的监控单元可以监视某些机器 我正在创建一个表单来在 Symfony2 中注册一台新机器 所以我们有机器实体 id 机器名称 显示器编号 And the 监控实体 id 序列号 对于新机器 客户需要填写form with
  • Internet Explorer 显然不支持 MouseEvent movingX 属性

    我正在开发一个需要兼容 IE 9 及以上版本的应用程序 我在 MouseEvent 对象上使用 movingX 属性 但是该 MouseEvent 对象在 Internet Explorer 9 或 11 中没有 movingX 属性 我浏
  • 如何使用php在mysql中生成下一个自动递增编号?

    我试图使用 php 获取 mysql 中的下一个自动递增数字 我尝试了这样的方法 但是 当删除任何行时 这不起作用 我希望你明白我的意思 我怎样才能使用 php 来做到这一点 您无法执行此操作来获取表数据 您必须使用 php 获取表状态才能
  • 为什么Python 2.7的namedtuple实现__dict__?

    The namedtuplePython 2 7 中的实现实现 dict 我很困惑这是在做什么 为什么我们需要做一个特别的 dict 如果已经定义了属性 C tmp gt python Python 2 7 12 Anaconda 4 1
  • 从 Python 数据中学习二元决策图 (BDD)

    是否可以从数据中学习二元决策图 BDD 以机器学习的方式 如果是这样 怎么办 背景 我在 Python 中看到过一些工具可以完成此任务 例如决策树 DT scikit学习 但我还没有看到任何 BDD 举个例子 我想做的事情如下 前三列对应于
  • 在 SQL Server 中读取并递增 int 值

    我需要使用 C 在 SQL Server 2008 中自动读取并递增一个值 例如 我必须插入 批次 的项目 为此我需要最后一批的编号 并确保没有其他人获得该编号 因此 我有一张仅包含最后批号的表格 并找到一种只需一步即可获取和更新编号的方法
  • 使用ClassLoader方法检索类下的所有资源作为输入流

    我的问题是一个你可能认为很常见的问题 但到目前为止我还没有找到解决方案 在 Tomcat 5 5 下构建 Java Web 应用程序 尽管要求它可以部署在任何地方 例如在 WebLogic 环境下 因此需要将资源作为流加载 良好的实践表明资
  • 为什么 System.Transactions TransactionScope 默认隔离级别可序列化

    我只是想知道什么是好的使用可序列化的原因作为创建时的默认隔离级别系统 交易 交易范围 因为我想不出任何 而且似乎你无法通过更改默认值web app config所以你总是必须在你的代码中设置它 using var transaction T
  • WCF,从服务访问 Windows 窗体控件

    我有一个托管在 Windows 窗体内的 WCF 服务 如何从我的服务中的方法访问表单的控件 例如我有 public interface IService ServiceContract string PrintMessage string
  • Gwt 插件在 Chrome 42 中不起作用 [重复]

    这个问题在这里已经有答案了 新版chrome 42 不支持gwt插件在 Windows 8 1 上 即使我将兼容模式更改为 Windows 7 我仍然会收到再次下载插件的提示 我已尝试删除它并重新安装 但仍然收到此消息 有任何想法吗 来自
  • 这段Python代码能更高效吗?

    我编写了一些代码来查找字符串中有多少个子串是字谜对 要查找的函数anagram anagramSolution 复杂度为 O N substring函数的复杂度小于N平方 但是 这里的代码是有问题的 能不能再优化一点 for i in ra
  • 填充颜​​色动画在动画中调用块时闪烁确实停止了

    我无法弄清楚为什么动画块完成后动画从 fromValue 闪烁到 toValue 我知道 完成动画后 您必须将 CALayer 的值设置为动画的结束状态 以保持其外观一致 然而 无论我以什么顺序调用这些方法 我都会得到闪烁的结果 我正在做的