Jak powiększyć / pomniejszyć obiekt UIImage, gdy użytkownik szczypie ekran?

Chciałbym powiększyć / pomniejszyć obiekt UIImage, gdy użytkownik wykona standardową akcję pinch w mojej aplikacji. Obecnie używam interfejsu UIImageView, aby wyświetlić mój obraz, jeśli ten szczegół w jakikolwiek sposób pomaga.

Staram się wymyślić, jak to zrobić, ale na razie nie ma takiego szczęścia.

Jakieś wskazówki?

Author: pasawaya, 2009-02-01

9 answers

Innym łatwym sposobem na to jest umieszczenie UIImageView W UIScrollView. Jak tu opisuję , musisz ustawić contentSize widoku przewijania tak, aby był taki sam jak rozmiar UIImageView's. Ustaw instancję kontrolera jako delegata widoku przewijania i zaimplementuj metody viewForZoomingInScrollView: i scrollViewDidEndZooming:withView:atScale:, aby umożliwić powiększanie i panoramowanie obrazu. Tak działa rozwiązanie Bena, tylko w nieco bardziej lekki sposób, ponieważ nie masz narzutu pełnego widoku sieci.

One problem, który możesz napotkać, polega na tym, że skalowanie w widoku przewijania ma formę przekształceń zastosowanych do obrazu. Może to prowadzić do rozmycia przy wysokich współczynnikach powiększenia. W przypadku czegoś, co można przerysować, możesz postępować zgodnie z moimi sugestiami tutaj , aby zapewnić wyraźniejszy wyświetlacz po zakończeniu gestu szczypania. rozwiązanie hniels może być wykorzystane w tym momencie do przeskalowania obrazu.

 81
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Jak opisali inni, najprostszym rozwiązaniem jest umieszczenie interfejsu użytkownika w widoku UIScrollView. Zrobiłem to w Kreatorze interfejsów .plik xib.

W viewDidLoad ustaw następujące zmienne. Ustaw kontroler jako UIScrollViewDelegate.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.scrollView.minimumZoomScale = 0.5;
    self.scrollView.maximumZoomScale = 6.0;
    self.scrollView.contentSize = self.imageView.frame.size;
    self.scrollView.delegate = self;
}

Musisz zaimplementować następującą metodę, aby zwrócić obraz, który chcesz powiększyć.

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

W wersjach poprzedzających iOS9, może być również konieczne dodanie metody empty delegate:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
}

Jabłko Dokumentacja dobrze opisuje, jak to zrobić:

 86
Author: rogue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 19:48:39

Rozwiązanie Shefali dla UIImageView działa świetnie, ale wymaga małej modyfikacji:

- (void)pinch:(UIPinchGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateEnded
        || gesture.state == UIGestureRecognizerStateChanged) {
        NSLog(@"gesture.scale = %f", gesture.scale);

        CGFloat currentScale = self.frame.size.width / self.bounds.size.width;
        CGFloat newScale = currentScale * gesture.scale;

        if (newScale < MINIMUM_SCALE) {
            newScale = MINIMUM_SCALE;
        }
        if (newScale > MAXIMUM_SCALE) {
            newScale = MAXIMUM_SCALE;
        }

        CGAffineTransform transform = CGAffineTransformMakeScale(newScale, newScale);
        self.transform = transform;
        gesture.scale = 1;
    }
}
(Rozwiązanie Shefali miało tę zaletę, że nie skalowało się w sposób ciągły podczas szczypania. Ponadto, podczas uruchamiania nowego szczypania, bieżąca Skala obrazu została zresetowana.)
 47
Author: JRV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-19 12:55:47

Poniższy kod pomaga powiększyć UIImageView bez użycia UIScrollView:

-(void)HandlePinch:(UIPinchGestureRecognizer*)recognizer{
    if ([recognizer state] == UIGestureRecognizerStateEnded) {
        NSLog(@"======== Scale Applied ===========");
        if ([recognizer scale]<1.0f) {
            [recognizer setScale:1.0f];
        }
        CGAffineTransform transform = CGAffineTransformMakeScale([recognizer scale],  [recognizer scale]);
        imgView.transform = transform;
    }
}
 23
Author: Shefali Soni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-23 13:54:19

Pamiętaj, że nigdy nie powiększasz UIImage. Nigdy.

Zamiast tego powiększasz i pomniejszasz view, który wyświetla UIImage.

W tym konkretnym przypadku należy utworzyć niestandardowy UIView z niestandardowym rysunkiem, aby wyświetlić obraz, UIImageView, który wyświetla obraz dla Ciebie, lub UIWebView, który będzie potrzebował dodatkowego kodu HTML, aby wykonać kopię zapasową.

We wszystkich przypadkach musisz wdrożyć touchesBegan, touchesMoved, i jak określić, co użytkownik próbuje zrobić (zoom, pan, itp.).

 18
Author: August,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 06:23:29

Oto rozwiązanie, z którego korzystałem wcześniej, które nie wymaga korzystania z UIWebView.

- (UIImage *)scaleAndRotateImage(UIImage *)image
{
    int kMaxResolution = 320; // Or whatever

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);


    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = bounds.size.width / ratio;
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }

    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

    }

    UIGraphicsBeginImageContext(bounds.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

Artykuł można znaleźć na Apple Support pod adresem: http://discussions.apple.com/message.jspa?messageID=7276709#7276709

 8
Author: Niels Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-16 08:42:35

Odpowiedzi Shafali i JRV rozszerzone o panoramowanie i szczypanie w celu powiększenia:

#define MINIMUM_SCALE 0.5
#define MAXIMUM_SCALE 6.0
@property CGPoint translation;


- (void)pan:(UIPanGestureRecognizer *)gesture {
    static CGPoint currentTranslation;
    static CGFloat currentScale = 0;
    if (gesture.state == UIGestureRecognizerStateBegan) {
        currentTranslation = _translation;
        currentScale = self.view.frame.size.width / self.view.bounds.size.width;
    }
    if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) {

        CGPoint translation = [gesture translationInView:self.view];

        _translation.x = translation.x + currentTranslation.x;
        _translation.y = translation.y + currentTranslation.y;
        CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x , _translation.y);
        CGAffineTransform transform2 = CGAffineTransformMakeScale(currentScale, currentScale);
        CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
        self.view.transform = transform;
    }
}


- (void)pinch:(UIPinchGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) {
//        NSLog(@"gesture.scale = %f", gesture.scale);

        CGFloat currentScale = self.view.frame.size.width / self.view.bounds.size.width;
        CGFloat newScale = currentScale * gesture.scale;

        if (newScale < MINIMUM_SCALE) {
            newScale = MINIMUM_SCALE;
        }
        if (newScale > MAXIMUM_SCALE) {
            newScale = MAXIMUM_SCALE;
        }

        CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x, _translation.y);
        CGAffineTransform transform2 = CGAffineTransformMakeScale(newScale, newScale);
        CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
        self.view.transform = transform;
        gesture.scale = 1;
    }
}
 5
Author: paul king,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-22 00:30:21

Najprostszym sposobem, aby to zrobić, jeśli wszystko, co chcesz, to powiększanie szczypty, jest umieszczenie obrazu wewnątrz UIWebView (Napisz niewielką ilość kodu HTML, odwołaj się do obrazu i w zasadzie gotowe). Bardziej skomplikowanym sposobem na to jest użycie touchesBegan, touchesMoved, i touchesEnded aby śledzić palce użytkownika i odpowiednio dostosować właściwość przekształcania widoku.

 3
Author: Ben Gottlieb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 06:23:05

Pamiętaj, że nie chcesz powiększać/pomniejszać interfejsu użytkownika. Zamiast tego spróbuj powiększyć / pomniejszyć widok, który zawiera kontroler widoku UIImage.

Przygotowałem rozwiązanie tego problemu. Spójrz na mój kod:

@IBAction func scaleImage(sender: UIPinchGestureRecognizer) {
        self.view.transform = CGAffineTransformScale(self.view.transform, sender.scale, sender.scale)
        sender.scale = 1
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        view.backgroundColor = UIColor.blackColor()
    }
Uwaga: nie zapomnij podłączyć PinchGestureRecognizer.
 0
Author: G Azam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-17 13:08:27