ios - 将 CGAffineTransformScale 与 UIAttachmentBehavior (UIDynamicAnimator) 结合使用

标签 ios iphone objective-c uikit-dynamics uidynamicbehavior

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

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

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

在应用 CGAffineTransformScale 之前,我尝试了 [_animator removeAllBehaviors],然后将行为添加回来。我还尝试了 [_animator updateItemUsingCurrentState:self] 在应用 CGAffineTransformScale 之后,就在添加附件行为之前。都无法解决问题。

更新 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];
}

最佳答案

UIAttachmentBehavior 如何影响 View ?

它通过修改 View 的转换来实现。

在此Ray Wenderlich tutorial Colin Eberhardt 在 View 受行为影响时记录转换。

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

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

在旁注中,如果您尝试将变换设置为按 1.5 缩放,您应该使用:

self.transform = CGAffineTransformMakeScale(1.5, 1.5);

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

在 UIDynamicAnimator 的文档中,它说:

"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."

所以只需在添加行为后调用您的转换,然后调用 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];
}

关于ios - 将 CGAffineTransformScale 与 UIAttachmentBehavior (UIDynamicAnimator) 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19969185/

相关文章:

iphone - 将 NSDictionary 转换为 NSString

ios - 自定义表格 View 行操作(图片)

ios - 在 Cocoa 中进行网络编程的方法

ios - 将 iPhone 应用程序分发给测试人员?

ios - objective-c : how to execute a function when app is in the background/killed automatically based on time Intervals

iphone - 如何在 iOS SDK 中使用 Glyph 获取 UIBezierpath

objective-c - 如何覆盖框架类(运行时)中的方法

ios - 当我创建一个新的 UIWindow 时,iPad airplay 显示器显示黑屏

objective-c - 如何在子类中访问父类(super class)变量

iphone - Titanium - 自定义 map 注释气泡?