将 CGAffineTransformScale 与 UIAttachmentBehavior (UIDynamicAnimator) 一起使用

Posted

技术标签:

【中文标题】将 CGAffineTransformScale 与 UIAttachmentBehavior (UIDynamicAnimator) 一起使用【英文标题】:Using CGAffineTransformScale with UIAttachmentBehavior (UIDynamicAnimator) 【发布时间】:2013-11-14 03:48:06 【问题描述】:

在 UIButton 的一个子类中,我将 UIButton 附加到一个 UIAttachmentBehavior,它允许用户用手指在屏幕上拖动按钮。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 中,我将按钮添加到 UIAttachmentBehavior,然后将行为添加到 UIDynamicAnimator。在- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 期间,我将 UIAttachmentBehavior 的锚点更新为触摸点;这将创建所需的拖动效果。

现在我希望在触摸开始时使用 CGAffineTransformScale 来增加按钮的大小,以便用户可以看到他们手指下的按钮。 我的问题是,我使用 CGAffineTransformScale 应用的转换在我添加附件行为的第二次被立即覆盖。结果是按比例放大按钮快速闪烁,但随后又恢复到原始大小。

我在应用 CGAffineTransformScale 之前尝试了[_animator removeAllBehaviors],然后将行为添加回来。在应用 CGAffineTransformScale 之后,在添加附件行为之前,我也尝试过 [_animator updateItemUsingCurrentState:self]。两者都不能解决问题。

更新 1:考虑到 HalR 在下面的回答,我决定尝试在每次触摸时应用缩放变换。因此,我将 CGAffineTransformScale 调用添加到 touchesMoved:touchesEnded。我正在使用 CGAffineTransformScale 与 CGAffineTransformMakeScale,因为它允许我保留附件行为添加的轻微旋转。它让我更接近了。该按钮现在在缩放时在屏幕上移动。虽然它并不完美。当您不在屏幕上移动时会出现闪烁,如果您停止移动,但按住触摸,按钮将恢复到原始大小。差不多了……有什么建议吗?

这是我的更新代码:

@interface DragButton : UIButton < UIDynamicAnimatorDelegate >

#import "DragButton"
#import <QuartzCore/QuartzCore.h>

@implementation DragButton

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    [super touchesBegan:touches withEvent:event];

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self.referenceView];

    self.transform = CGAffineTransformMakeScale(1.5, 1.5);

    _touchAttachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self attachedToAnchor:touchLocation];
    [_animator addBehavior:_touchAttachmentBehavior];


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

    [super touchesMoved:touches withEvent:event];

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self.referenceView];

    self.transform = CGAffineTransformScale(self.transform, 1.5, 1.5);

    _touchAttachmentBehavior.anchorPoint = touchLocation;


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

    [super touchesEnded:touches withEvent:event];

    self.transform = CGAffineTransformScale(self.transform, 1.5, 1.5);

    [_animator removeBehavior:_touchAttachmentBehavior];

【问题讨论】:

您是否尝试过将 UIImageView 子视图添加到您的按钮,并将您的转换应用到该子视图的图层,从而让您的行为与按钮保持一致,然后子视图将在顶部应用其转换那个? 【参考方案1】:

UIAttachmentBehavior 如何影响视图?

它通过修改视图的变换来实现。

在此Ray Wenderlich tutorial Colin Eberhardt 中记录了转换,因为视图受到行为的影响。

即使从未直接设置或修改转换,它也会随着视图被行为移动而改变。

所以你不能设置你的变换,并希望它保持设置,因为它是由行为设置的。

附带说明,如果您尝试将变换设置为按 1.5 缩放,您应该使用以下命令:

self.transform = CGAffineTransformMakeScale(1.5, 1.5);

否则每次调用touchesBegan 时,它都会再增长 50%。

在 UIDynamicAnimator 的文档中,它说:

"动态动画师自动读取初始状态(位置 和旋转)添加到它的每个动态项目,然后采取 负责更新项目的状态。如果你主动改变 将动态项添加到动态项后的状态 动画师,调用此方法要求动画师阅读并合并 新的状态。”

所以只需在添加行为后调用您的转换,然后调用 updateItemUsingCurrentState:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    [super touchesBegan:touches withEvent:event];

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self.referenceView];

    _touchAttachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self attachedToAnchor:touchLocation];
    [_animator addBehavior:_touchAttachmentBehavior];
    self.transform = CGAffineTransformMakeScale(1.5, 1.5);
    [_animator updateItemUsingCurrentState:self];

【讨论】:

对,UIAttachmentBehavior 修改了转换。但是,为什么我不能告诉它“修改修改过的”转换?我对updateItemUsingCurrentState: 文档的解释是它应该允许我主动修改比例。 A dynamic animator automatically reads the initial state (position and rotation) of each dynamic item you add to it, and then takes responsibility for updating the item’s state. If you actively change the state of a dynamic item after you’ve added it to a dynamic animator, call this method to ask the animator to read and incorporate the new state. 顺便说一句,感谢有关 CGAffineTransformMakeScale 的提示...好电话。

以上是关于将 CGAffineTransformScale 与 UIAttachmentBehavior (UIDynamicAnimator) 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用 CGAffineTransformScale 自定义 UIView 缩放

求解答CGAffineTransformScale造成字体模糊的问题

求解答CGAffineTransformScale造成字体模糊的问题

通过 CGAffineTransformScale 计算的 bounds、frame 和 frame 之间的差异

如何使用 CGAffineTransform Scale 从右到左添加动画和放大动画

捏手势IOS的手势绑定限制