我想在用户触摸位置向我的视图添加UIImageView
,并在用户按下手指时让UIImageView
增长。想想一个气球被炸毁了。我希望UIImageView的中心在其成长过程中保持在用户的触摸位置。
我认为最好的方法是UILongPressGestureRecognizer
并写下面的内容。除了视觉效果有些不稳定和笨拙之外,这确实有效。
在UILongPressGestureRecognizer
调用UIGestureRecognizerStateEnded
之前,有没有办法让UIImageView的大小动画化?
或者,有没有更好的方法来完成这项工作?
在.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];
}
}
答案 0 :(得分:4)
计时器可能不顺畅。取而代之的是CADisplayLink
,它会在设备的屏幕重绘(~60hz)时提供代表回调,这样您就可以获得每帧调整气球大小的机会。
要考虑的另一件事是刷新之间的时间不是恒定的,它可能比最后一次刷新时要慢得多,所以如果你每次收到回调时将大小增加一个常数15,那么动画似乎并不顺畅。
为了解决这个问题,当您开始动画时,请使用时间戳并按住它,然后当您为气球充气时,请使用另一个时间戳并确定现在和最后一次重绘之间的差异,然后将差值乘以某个值,这将是确保持续平滑的大小增长 - 这称为时间步长。
答案 1 :(得分:2)
在这里发挥创意,但我认为这可行: 您启动动画,将图像帧从其当前大小设置为最大大小。
检测到长按手势后立即启动动画。
如果手势结束,请从动画视图/图像的presentationLayer
获取当前帧大小,并通过使用UIViewAnimationOptionBeginFromCurrentState
启动新动画将视图/图像的帧更新为该大小,以便旧动画将停止。
这应该会给你一个平稳增长的气球。
答案 2 :(得分:0)
试试这个......
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];
}
}
答案 3 :(得分:0)
这是一个Swift版本。我不得不用&#34;暂停&#34;替换invalidate()调用。为了避免通货膨胀失控。
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
}
}