1

我使用以下代码使用UISwipeGestureRecognizer左右滑动,以类似于 iPhoto 的方式在我的应用程序中显示照片。

    CATransition *animation = [CATransition animation];
    [animation setDuration:0.5];
    [animation setType:kCATransitionPush];
    [animation setSubtype:kCATransitionFromRight];
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [[self.imageHolder layer] addAnimation:animation forKey:@"SwitchToView"];

这会将下一张图像滑入并滑出旧图像,如下图所示:

图一:

图一

过渡:

过渡视图

图二:

图二

当我突然意识到我应该使用UIPanGestureRecognizer时,我想知道如何让它像 iPhoto 一样。

我需要像 iPhoto 那样用手指“控制”动画,即允许我开始拖动到下一张图像,然后反转拖动方向。此外,以与 iPhoto 类似的方式,如果在显示的下一张图像比第一张图像更多时松开手指,我希望下一张图像滑入(这在上面的过渡图片中没有发生,如果我释放我的手指此时在 iPhoto 中它会滑回第一张图像。

我以前从未使用过UIPanGestureRecognizer,所以如果有人可以帮助我,那就太好了。

编辑:

使用Levi提供的代码,我创建了一个适用于 3 个示例图像的解决方案。对于任何有兴趣使用UIPanGestureRecognizer的人,代码是:

界面:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>
{
int imageIndex;
}

@property (nonatomic, strong) UIImageView* imageView;
@property (nonatomic, strong) UIImageView* leftImageView;
@property (nonatomic, strong) UIImageView* rightImageView;

@end

执行:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];

self->imageIndex = 0;

float xFactor;

UIInterfaceOrientation currentOrientation = self.interfaceOrientation;
if(UIInterfaceOrientationIsLandscape(currentOrientation)){

    xFactor = 256;

}
else{

    xFactor = 0;

}

self.imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.image = [UIImage imageNamed:@"69B4356B-1CB2-4A2F-867E-9C086251DF11-12668-0000036A534E9B6D"];
self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

CGRect leftFrame = self.view.frame;
leftFrame.origin.x -= leftFrame.size.width+xFactor;
self.leftImageView = [[UIImageView alloc] initWithFrame:leftFrame];
self.leftImageView.contentMode = UIViewContentModeScaleAspectFit;
self.leftImageView.image = [UIImage imageNamed:@"42517D93-F8BF-42E7-BB44-53B099A482AA-12668-0000036A49BCECAA"];
self.leftImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

CGRect rightFrame = self.view.frame;
rightFrame.origin.x += rightFrame.size.width+xFactor;
self.rightImageView = [[UIImageView alloc] initWithFrame:rightFrame];
self.rightImageView.contentMode = UIViewContentModeScaleAspectFit;
self.rightImageView.image = [UIImage imageNamed:@"C6AC2508-243B-464B-A71F-96DD7F18673D-12668-00000369F3AFD3FC"];
self.rightImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

[self.view addSubview:self.imageView];
[self.view addSubview:self.leftImageView];
[self.view addSubview:self.rightImageView];

UIPanGestureRecognizer *recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[self.view addGestureRecognizer:recognizer];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];

}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateEnded) {
    CGRect leftFrame = self.leftImageView.frame;
    CGRect currentFrame = self.imageView.frame;
    CGRect rightFrame = self.rightImageView.frame;

    float duration = 0.0;

    float factor;

    UIInterfaceOrientation currentOrientation = self.interfaceOrientation;
    if(UIInterfaceOrientationIsPortrait(currentOrientation)){

        factor = 768;
    }
    else{
        factor = 1024;
    }

    if (self.imageView.center.x < 0) { // Present the right image
        duration = 0.3 * ABS(self.rightImageView.frame.origin.x / factor);
        leftFrame.origin.x = -2 * factor;
        currentFrame.origin.x = -1 * factor;
        rightFrame.origin.x = 0;
        self->imageIndex = 1;

    } else if (self.imageView.center.x > factor) { // Present the left image
        duration = 0.3 * ABS(self.leftImageView.frame.origin.x / factor);
        leftFrame.origin.x = 0;
        currentFrame.origin.x = factor;
        rightFrame.origin.x = 2 * factor;
        self->imageIndex = -1;

    } else { // leave the middle image
        duration = 0.3 * ABS(self.imageView.frame.origin.x / factor);
        leftFrame.origin.x = -1 * factor;
        currentFrame.origin.x = 0;
        rightFrame.origin.x = factor;
        self->imageIndex = 0;

    }

    [UIView animateWithDuration:duration
                          delay:0
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         self.leftImageView.frame = leftFrame;
                         self.imageView.frame = currentFrame;
                         self.rightImageView.frame = rightFrame;
                     } completion:^(BOOL finished) {
                     }];

} else {
    CGPoint translation = [recognizer translationInView:recognizer.view];
    CGPoint leftCenter = self.leftImageView.center;
    CGPoint currentCenter = self.imageView.center;        
    CGPoint rightCenter = self.rightImageView.center;

    leftCenter.x += translation.x;
    currentCenter.x += translation.x;
    rightCenter.x += translation.x;
    self.leftImageView.center = leftCenter;
    self.imageView.center = currentCenter;
    self.rightImageView.center = rightCenter;

    [recognizer setTranslation:CGPointMake(0, 0) inView:self.imageView];
}

}

- (void)willAnimateRotationToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
                                     duration:(NSTimeInterval)duration
{ 
CGPoint leftCenter = self.leftImageView.center;
CGPoint currentCenter = self.imageView.center;
CGPoint rightCenter = self.rightImageView.center;

if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){

    leftCenter.x = 384+(((-self->imageIndex)-1)*768);
    currentCenter.x = 384+((-self->imageIndex)*768);
    rightCenter.x = 384+(((-self->imageIndex)+1)*768);

}
else{

    leftCenter.x = 512+(((-self->imageIndex)-1)*1024);
    currentCenter.x = 512+((-self->imageIndex)*1024);
    rightCenter.x = 512+(((-self->imageIndex)+1)*1024);

}

self.leftImageView.center = leftCenter;
self.imageView.center = currentCenter;
self.rightImageView.center = rightCenter;

}

@end
4

2 回答 2

1

如果您想要像照片应用程序这样的滚动行为,则根本不应该使用 a UIGestureRecognizer。使用 a UIPageViewControllerwith UIPageViewControllerTransitionStyleScroll,或者如果您需要支持低于 iOS6 的版本,使用 a UIScrollView

查看 Apple 的示例项目PhotoScroller以获取使用UIScrollView.

于 2012-12-15T19:45:14.140 回答
1

您可以添加一个UIPanGestureRecognizer到您的图像视图。您将有一个分配给它的方法,您可以在其中执行以下操作:

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    if (recognizer.state == UIGestureRecognizerStateEnded) {

    } else {
        CGPoint translation = [recognizer translationInView:recognizer.view];
        CGPoint center = recognizer.view.center;
        UIImageView *imageViewToPresent = nil;
        if (translation.x > 0) {
            imageViewToPresent = [self leftImageView];
        } else {
            imageViewToPresent = [self leftImageView];
        }
        CGPoint actualCenter = recognizer.view.center;
        CGPoint nextCenter = imageViewToPresent.center;
        actualCenter.x += translation.x;
        nextCenter.x += translation.x;
        recognizer.view.center = actualCenter;
        imageViewToPresent.view.center = nextCenter;
        [recognizer setTranslation:CGPointMake(0, 0) inView:self.imageView];
    }
}

在该UIGestureRecognizerStateEnded部分中,您可以决定显示哪张图片。

或者只使用启用分页的 ScrollView。它应该具有相同的效果。但是,它需要同时加载所有图像。使用平移识别器,您需要 3 个顶部图像视图(左、右、当前)。

希望这可以帮助!

编辑:

在头文件中,您应该再添加 2 个图像视图:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIGestureRecognizerDelegate>

@property (nonatomic, strong) UIImageView* imageView;
@property (nonatomic, strong) UIImageView* leftImageView;
@property (nonatomic, strong) UIImageView* rightImageView;

@end

实施将是:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    self.imageView.image = [UIImage imageNamed:@"69B4356B-1CB2-4A2F-867E-9C086251DF11-12668-0000036A534E9B6D"];
    self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    CGRect leftFrame = self.view.frame;
    leftFrame.origin.x -= leftFrame.size.width;
    self.leftImageView = [[UIImageView alloc] initWithFrame:leftFrame];
    self.leftImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.leftImageView.image = [UIImage imageNamed:@"42517D93-F8BF-42E7-BB44-53B099A482AA-12668-0000036A49BCECAA"];
    self.leftImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    CGRect rightFrame = self.view.frame;
    rightFrame.origin.x += rightFrame.size.width;
    self.rightImageView = [[UIImageView alloc] initWithFrame:rightFrame];
    self.rightImageView.contentMode = UIViewContentModeScaleAspectFit;
    self.rightImageView.image = [UIImage imageNamed:@"C6AC2508-243B-464B-A71F-96DD7F18673D-12668-00000369F3AFD3FC"];
    self.rightImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:self.imageView];
    [self.view addSubview:self.leftImageView];
    [self.view addSubview:self.rightImageView];

    UIPanGestureRecognizer *recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [self.view addGestureRecognizer:recognizer];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        CGRect leftFrame = self.leftImageView.frame;
        CGRect currentFrame = self.imageView.frame;
        CGRect rightFrame = self.rightImageView.frame;
        float duration = 0.0;
        if (self.imageView.center.x < 0) { // Present the right image
            duration = 0.3 * ABS(self.rightImageView.frame.origin.x / self.view.frame.size.width);
            leftFrame.origin.x = -2 * self.view.frame.size.width;
            currentFrame.origin.x = -1 * self.view.frame.size.width;
            rightFrame.origin.x = 0;
        } else if (self.imageView.center.x > self.view.frame.size.width) { // Present the left image
            duration = 0.3 * ABS(self.leftImageView.frame.origin.x / self.view.frame.size.width);
            leftFrame.origin.x = 0;
            currentFrame.origin.x = self.view.frame.size.width;
            rightFrame.origin.x = 2 * self.view.frame.size.width;
        } else { // leave the middle image
            duration = 0.3 * ABS(self.imageView.frame.origin.x / self.view.frame.size.width);
            leftFrame.origin.x = -1 * self.view.frame.size.width;
            currentFrame.origin.x = 0;
            rightFrame.origin.x = self.view.frame.size.width;
        }

        [UIView animateWithDuration:duration
                              delay:0
                            options:UIViewAnimationOptionCurveEaseInOut
                         animations:^{
            self.leftImageView.frame = leftFrame;
            self.imageView.frame = currentFrame;
            self.rightImageView.frame = rightFrame;
        } completion:^(BOOL finished) {
        }];
    } else {
        CGPoint translation = [recognizer translationInView:recognizer.view];
        CGPoint currnetCenter = self.imageView.center;
        CGPoint leftCenter = self.leftImageView.center;
        CGPoint rightCenter = self.rightImageView.center;

        currnetCenter.x += translation.x;
        leftCenter.x += translation.x;
        rightCenter.x += translation.x;
        self.imageView.center = currnetCenter;
        self.leftImageView.center = leftCenter;
        self.rightImageView.center = rightCenter;


        [recognizer setTranslation:CGPointMake(0, 0) inView:self.imageView];
    }

}

@end

当然,它仍然需要工作(例如,支持超过 3 个硬编码图像)。如果您使用 IBOutlets 并从 Interface Builder 设置自动调整大小的掩码,它可能会帮助您解决旋转问题。

玩得开心!

于 2012-12-15T19:50:09.333 回答