在UilongPressEntrereragnizer活跃的同时,生长一个uiimageView



我想在用户触摸位置的视图中添加一个UIImageView,并在用户握住手指时使UIImageView生长。想想一个呼吸的人被炸毁。我希望UIImageView的中心在增长时保留在用户的触摸位置。

我认为最好的方法是UILongPressGestureRecognizer并写下以下内容。除了视觉效果有些断断续续和笨拙,这确实可以按照我的计划工作。

有什么方法可以使UIImageView的大小动画,直到UILongPressGestureRecognizer调用UIGestureRecognizerStateEnded

或,有更好的方法可以完全做这件事吗?

在.h: CGPoint longPressLocation;

中声明

.m:

- (IBAction) handleInflation:(UILongPressGestureRecognizer *) inflateGesture {
     longPressLocation= [inflateGesture locationInView:self.view];
    switch (inflateGesture.state) {
        case UIGestureRecognizerStateBegan:{
            NSLog(@"Long press Began .................");
            inflateTimer = [NSTimer scheduledTimerWithTimeInterval:.4 target:self selector:@selector(inflate) userInfo:nil repeats:YES];
            UIImage *tempImage=[UIImage imageNamed:@"bomb.png"];
            UIImageView *inflatableImageView = [[UIImageView alloc] initWithFrame:CGRectMake(longPressLocation.x-tempImage.size.width/2,
                                                                                             longPressLocation.y-tempImage.size.height/2,
                                                                                             tempImage.size.width, tempImage.size.height)];
            inflatableImageView.image = tempImage;
            [bonusGame addSubview:inflatableImageView];
            inflatable=inflatableImageView;
        }
            break;
        case UIGestureRecognizerStateChanged:{
            NSLog(@"Long press Changed .................");
        }
            break;
        case UIGestureRecognizerStateEnded:{
            NSLog(@"Long press Ended .................");
            [inflateTimer invalidate];
        }
            break;
        default:
            break;
    }
}
-(void)inflate{
    inflatable.frame=CGRectMake(inflatable.frame.origin.x,inflatable.frame.origin.y , inflatable.bounds.size.width+15, inflatable.bounds.size.height+15);
    inflatable.center=longPressLocation;
}

最终工作代码:

- (IBAction) handleInflation:(UILongPressGestureRecognizer *) inflateGesture {
    inflateGesture.minimumPressDuration = .01;
     longPressLocation= [inflateGesture locationInView:self.view];
    switch (inflateGesture.state) {
        case UIGestureRecognizerStateBegan:{
            NSLog(@"Long press Began .................");
            inflateStart = [NSDate date];
            inflateDisplayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(inflate)];
            [inflateDisplayLink setFrameInterval:1];
            [inflateDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            UIImage *tempImage=[UIImage imageNamed:@"bomb.png"];
            UIImageView *inflatableImageView = [[UIImageView alloc] initWithFrame:CGRectMake(longPressLocation.x-tempImage.size.width/2,
                                                                                             longPressLocation.y-tempImage.size.height/2,
                                                                                             tempImage.size.width, tempImage.size.height)];
            inflatableImageView.image = tempImage;
            [bonusGame addSubview:inflatableImageView];
            inflatable=inflatableImageView;
        }
            break;
        case UIGestureRecognizerStateChanged:{
            NSLog(@"Long press Changed .................");
        }
            break;
        case UIGestureRecognizerStateEnded:{
            NSLog(@"Long press Ended .................");
            [inflateDisplayLink invalidate];
        }
            break;
        default:
            break;
    }
}
-(void)inflate{
    NSDate *inflateEnd = [NSDate date];
    NSTimeInterval inflateInterval;
    inflateInterval = ([inflateEnd timeIntervalSince1970] - [inflateStart timeIntervalSince1970])*25;
    inflatable.frame=CGRectMake(inflatable.frame.origin.x,
                                inflatable.frame.origin.y ,
                                inflatable.bounds.size.width+inflateInterval,
                                inflatable.bounds.size.height+inflateInterval);
    inflatable.center=longPressLocation;
    if(inflatable.bounds.size.width>200){
        [inflateDisplayLink invalidate];
    }
}

计时器可能不会平滑。相反,请查看CADisplayLink,每当设备的屏幕重新绘制(〜60Hz)时,它将提供代表回调,因此您将获得调整气球尺寸的每一帧机会。

要考虑的另一件事是,刷新之间的时间不是恒定的,它可能比上次刷新时要慢得多,因此,如果您每次收到回调时将大小增加一个常数15,则动画可能看起来不流畅。

要打击这一点,当您启动动画时,请使用时间戳并握住它,然后当您夸大气球时,请使用另一个时间戳,确定现在和最后一个重新绘制的差异,然后将差异乘以一定的值,这将确保恒定的平滑尺寸增长 - 这称为 timeStep

https://developer.apple.com/library/ios/documentation/quartzcore/reference/cadisplaylink_classref/reference/reference/Reference.html

在这里变得有创意,但我认为这可能有效:您启动一个动画,将图像框架从其当前尺寸到最大尺寸的动画动画。

一旦检测到长按手势,请立即开始动画。

如果手势结束,请从动画视图/图像的presentationLayer获取当前的帧大小,并通过使用UIViewAnimationOptionBeginFromCurrentState启动新动画将视图/图像的帧更新为该大小,以便旧动画停止。

应该给您一个平稳生长的气球。

尝试这个....

imageView = [[UIImageView alloc] initWithFrame:(CGRectMake(120, 100, 30, 30))];
imageView.backgroundColor = [UIColor redColor];
[self.view addSubview:imageView];
imageView.userInteractionEnabled = TRUE;
UILongPressGestureRecognizer *g = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[g setMinimumPressDuration:0.001];
[imageView addGestureRecognizer:g];

并添加这些方法

-(void)longPress:(UITapGestureRecognizer *)t
{
    if (t.state == UIGestureRecognizerStateBegan)
    {
        [timer invalidate];
        timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(makeIncrc) userInfo:nil repeats:TRUE];
    }
    else if (t.state == UIGestureRecognizerStateEnded || t.state == UIGestureRecognizerStateCancelled)
    {
        [timer invalidate];
        timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(makeDec) userInfo:nil repeats:TRUE];
    }
}
-(void)makeIncrc
{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.5];
    [UIView setAnimationCurve:(UIViewAnimationCurveLinear)];
    CGRect frame = imageView.frame;
    frame.origin.x = frame.origin.x - 5;
    frame.origin.y = frame.origin.y - 5;
    frame.size.width = frame.size.width + 10;
    frame.size.height = frame.size.height + 10;
    imageView.frame = frame;
    [UIView commitAnimations];
}
-(void)makeDec
{
    if (imageView.frame.size.width < 20 || imageView.frame.size.height < 20)
    {
        [timer invalidate];
    }
    else
    {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.5];
        [UIView setAnimationCurve:(UIViewAnimationCurveLinear)];

        CGRect frame = imageView.frame;
        frame.origin.x = frame.origin.x + 5;
        frame.origin.y = frame.origin.y + 5;
        frame.size.width = frame.size.width - 10;
        frame.size.height = frame.size.height - 10;
        imageView.frame = frame;
        [UIView commitAnimations];
    }
}

这是一个快速版本。为了避免失控的通货膨胀,我必须用"暂停"替换无效的()呼叫。

var inflateDisplayLink: CADisplayLink?
var inflateStart: NSDate!
var longPressLocation: CGPoint!
var inflatable: UIImageView!
func handleInflation(inflateGesture: UILongPressGestureRecognizer) {
    longPressLocation = inflateGesture.locationInView(self.view)
    let imageView = inflateGesture.view as! UIImageView
    switch (inflateGesture.state) {
        case .Began:
            println("Long press Began .................")
            inflateStart = NSDate()
            let tempImageView = UIImageView(image: imageView.image)
            tempImageView.contentMode = .ScaleAspectFit
            tempImageView.frame = imageView.frame
            self.view.addSubview(tempImageView)
            inflatable = tempImageView
            if inflateDisplayLink == nil {
                inflateDisplayLink = CADisplayLink(target: self, selector: Selector("inflate"))
                inflateDisplayLink!.frameInterval = 1
                inflateDisplayLink!.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
            } else {
                inflateDisplayLink!.paused = false
            }
            break
        case .Changed:
            println("Long press Changed .................")
            break
        case .Ended:
            println("Long press Ended .................")
            inflateDisplayLink!.paused = true
            break
        default:
            break
    }
}
func inflate() {
    var inflateEnd = NSDate()
    // Convert from Double to CGFloat, due to bug (?) on iPhone5
    var inflateInterval: CGFloat = CGFloat((Double(inflateEnd.timeIntervalSince1970) - Double(inflateStart.timeIntervalSince1970))) * 5.0
    inflatable.frame = CGRectMake(inflatable.frame.origin.x, inflatable.frame.origin.y, inflatable.bounds.size.width + inflateInterval, inflatable.bounds.size.height + inflateInterval)
    inflatable.center = longPressLocation.center
    if inflatable.bounds.size.width > 200  {
        inflateDisplayLink!.paused = true
    }
}

最新更新