Как насчет следующего?
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIImageView *imageView = nil;
BOOL moved = NO;
CGRect newPoint = imageView.frame;
// If off screen left
if (newPoint.origin.x < 0.0f){
newPoint.origin.x *= -1.0;
moved = YES;
}
// if off screen up
if (newPoint.origin.y < 0.0f){
newPoint.origin.y *= -1.0;
moved = YES;
}
// if off screen right
CGFloat howFarOffRight = (newPoint.origin.x + newPoint.size.width) - imageView.superview.frame.size.width;
if (howFarOffRight > 0.0)
{
newPoint.origin.x -= howFarOffRight * 2;
moved = YES;
}
// if off screen bottom
CGFloat howFarOffBottom = (newPoint.origin.y + newPoint.size.height) - imageView.superview.frame.size.height;
if (howFarOffBottom > 0.0)
{
newPoint.origin.y -= howFarOffBottom * 2;
moved = YES;
}
if (moved)
{
[UIView beginAnimations:@"BounceAnimations" context:nil];
[UIView setAnimationDuration:.5];
[letterOutOfBounds play];
[imageView setFrame:newPoint];
[UIView commitAnimations];
}
}
Когда я прочитал ваш код, логика «если с левой стороны, переместите его обратно в вид на то же расстояние, на котором он находился за пределами экрана». Честно говоря, это не совсем понятно для меня (почему при отскоке назад координата зависит от того, насколько далеко она находилась от экрана), но я попытался учесть это в «правом за пределами экрана» и логика «нижняя часть экрана». Очевидно, моя логика использует superview
из imageView
для определения ширины содержащего представления, но если это не подходит, замените его тем, что есть.
Изменить:
Я лично делаю это с помощью распознавателей жестов, таких как:
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[self.imageView addGestureRecognizer:pan];
self.imageView.userInteractionEnabled = YES;
Таким образом, распознаватель жестов для анимации перемещения изображения назад будет выглядеть так:
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGRect originalFrame; // you could make this an ivar if you want, but just for demonstration purposes
if (gesture.state == UIGestureRecognizerStateBegan)
{
originalFrame = self.imageView.frame;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint translate = [gesture translationInView:gesture.view];
CGRect newFrame = originalFrame;
newFrame.origin.x += translate.x;
newFrame.origin.y += translate.y;
gesture.view.frame = newFrame;
}
else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled)
{
CGRect newFrame = gesture.view.frame;
newFrame.origin.x = fmaxf(newFrame.origin.x, 0.0);
newFrame.origin.x = fminf(newFrame.origin.x, gesture.view.superview.bounds.size.width - newFrame.size.width);
newFrame.origin.y = fmaxf(newFrame.origin.y, 0.0);
newFrame.origin.y = fminf(newFrame.origin.y, gesture.view.superview.bounds.size.height - newFrame.size.height);
// animate how ever you want ... I generally just do animateWithDuration
[UIView animateWithDuration:0.5 animations:^{
gesture.view.frame = newFrame;
}];
}
}
Или, если вам нужен распознаватель жестов, который просто предотвращает перетаскивание изображения с экрана, это будет:
- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
static CGRect originalFrame;
if (gesture.state == UIGestureRecognizerStateBegan)
{
originalFrame = self.imageView.frame;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint translate = [gesture translationInView:gesture.view];
CGRect newFrame = originalFrame;
newFrame.origin.x += translate.x;
newFrame.origin.x = fmaxf(newFrame.origin.x, 0.0);
newFrame.origin.x = fminf(newFrame.origin.x, gesture.view.superview.bounds.size.width - newFrame.size.width);
newFrame.origin.y += translate.y;
newFrame.origin.y = fmaxf(newFrame.origin.y, 0.0);
newFrame.origin.y = fminf(newFrame.origin.y, gesture.view.superview.bounds.size.height - newFrame.size.height);
gesture.view.frame = newFrame;
}
}
Кстати, в iOS 7 вы можете сделать анимацию просмотра изображения обратно в исходное положение немного упругой, используя новый animationWithDuration
с параметрами usingSpringWithDampening
и initialSpringVelocity
:
[UIView animateWithDuration:1.0
delay:0.0
usingSpringWithDamping:0.3
initialSpringVelocity:0.1
options:0
animations:^{
// set the new `frame` (or update the constraint constant values that
// will dictate the `frame` and call `layoutViewsIfNeeded`)
}
completion:nil];
Кроме того, в iOS7 вы также можете использовать UIKit Dynamics для добавления UISnapBehavior
:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
self.animator.delegate = self;
UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.viewToAnimate snapToPoint:CGPointMake(self.viewToAnimate.center.x, self.view.frame.size.height - 50)];
// optionally, you can control how much bouncing happens when it finishes, e.g., for a lot of bouncing:
//
// snap.damping = 0.2;
// you can also slow down the snap by adding some resistance
//
// UIDynamicItemBehavior *resistance = [[UIDynamicItemBehavior alloc] initWithItems:@[self.viewToAnimate]];
// resistance.resistance = 20.0;
// resistance.angularResistance = 200.0;
// [self.animator addBehavior:resistance];
[self.animator addBehavior:snap];
person
Rob
schedule
17.11.2012