Як збільшити / зменшити об’єкт UIImage, коли користувач стискає екран?


84

Я хотів би збільшити / зменшити об’єкт UIImage, коли користувач виконує стандартну дію притискання мого додатка. На даний момент я використовую UIImageView для відображення свого зображення, якщо ця деталь якось допомагає.

Я намагаюся зрозуміти, як це зробити, але поки що такої удачі немає.

Будь-які підказки?

Відповіді:


85

Ще один простий спосіб зробити це - помістити свій UIImageViewфайл у UIScrollView. Як я тут описую , вам потрібно встановити розмір вмісту подання прокрутки таким самим, як ваш UIImageView'sрозмір. Встановіть екземпляр вашого контролера як делегат подання прокрутки та застосуйте методи viewForZoomingInScrollView:and, scrollViewDidEndZooming:withView:atScale:що дозволяють масштабувати та зменшувати зображення. Це ефективно, що робить рішення Бена, лише дещо полегшене, оскільки у вас немає накладних витрат на повний веб-перегляд.

Одне питання, з яким ви можете зіткнутися, полягає в тому, що масштабування у поданні прокрутки виконується у формі перетворень, застосованих до зображення. Це може призвести до розмитості при великих коефіцієнтах збільшення. Щось, що можна перемалювати, ви можете слідувати моїм пропозиціям тут, щоб надати чіткіший дисплей після закінчення жесту. Розчин hniels може бути використаний в цей момент для масштабування вашого зображення.


2
Переконайтеся, що ви змінили maxZoomScale та / або minimumZoomScale :).
Кріс Принс

94

Як описано іншими, найпростішим рішенням є розміщення вашого UIImageView у UIScrollView. Я зробив це у файлі .xib конструктора інтерфейсів.

В viewDidLoad встановіть такі змінні. Встановіть для свого контролера 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;
}

Вам потрібно застосувати наступний метод, щоб повернути imageView, який потрібно збільшити.

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

У версіях до iOS9 вам також може знадобитися додати цей порожній метод делегування:

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

Apple , документація робить хорошу роботу по опису , як це зробити:


3
Нормально видалити scrollViewDidEndZooming: withView: зараз я тестував на iOS9 Xcode7
ElonChan,

1
Це працює для мене! Без реалізації scrollViewDidEndZooming :методу.
Джонні Чжан,

48

Рішення Шефалі для UIImageView чудово працює, але потребує невеликої модифікації:

- (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;
    }
}

(Рішення Шефалі мало негативну сторону, оскільки воно не змінювало масштаб безперервно під час защемлення. Крім того, при запуску нового пінча поточний масштаб зображення було скинуто.)


Я хочу, щоб жест панорамування увімкнувся після запуску жесту. Як це зробити?
Gajendra K Chauhan

@Gajendra: У такому випадку, я думаю, вам слід використовувати вбудовування своїх компонентів у режим прокрутки, який підтримує обидва варіанти
JRV,

Але я хочу функціональність як для натискання, так і для натискання. Я також використовую сітку (шари) у Imageview. Чи можу я знати, чи можна використовувати жест перетискання та натискання в режимі прокрутки.?
Gajendra K Chauhan

@GajendraKChauhan: вид прокрутки підтримує стискання для збільшення та панорамування з поля - просто не забудьте встановити мінімальний / максимальний масштаб масштабування, але також зверніть увагу на відповідь Бреда Ларсонса. А якщо ви хочете також натиснути жест, ви можете додати це як жест.
JRV

@JRV, яких делегатів мені потрібно додати, щоб визначити ширину self.frame.size.width?

23

Нижче код допомагає збільшити UIImageView без використання 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;
    }
}

Це найвище рішення :). Дякую.
sabiland

19

Майте на увазі, що ви НІКОЛИ не наближаєте a UIImage. НІКОЛИ.

Натомість ви збільшуєте та зменшуєте те, viewщо відображає UIImage.

У цьому конкретному випадку ви можете вибрати створити власний за UIViewдопомогою власного креслення для відображення зображення, UIImageViewякий відображає зображення для вас, або UIWebViewякий потребує додаткового HTML для його резервного копіювання.

У всіх випадках вам потрібно буде застосувати touchesBegan, touchesMovedтощо, щоб визначити, що намагається зробити користувач (масштабування, панорамування тощо).


+1 для роз’яснень, ніколи не думав про це так, ура, чувак
Ельмо

@August, чи можете ви надати мені будь-який приклад збільшення масштабу та повороту зображення при дотиках Початок, дотик Переміщення?
Mitesh Dobareeya

7

Ось рішення, яке я використовував раніше, і не вимагає від вас використання 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;
}

Статтю можна знайти в службі підтримки Apple за адресою: http://discussions.apple.com/message.jspa?messageID=7276709#7276709


-1 для розміщеної на jsp сторінки підтримки. трясе кулаком крапковий синтаксис
esharp

Чи можете ви, будь ласка, надати мені, як зателефонувати за цим методом (при русі миші або дотику)?
Бумеш Пурохіт,

5

Відповіді Шафалі та JRV розширені, включаючи панорамування та натискання для збільшення:

#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;
    }
}

будь ласка, уникайте згадування відповіді інших, оскільки вони можуть у будь-який час видалити свою відповідь.
Enamul Hassan

3

Найпростіший спосіб зробити це, якщо все, що вам потрібно, це масштабування за допомогою UIWebViewдрібного масштабу - це розмістити зображення всередині (напишіть невелику кількість коду обгортки HTML, посилайтеся на своє зображення, і ви в основному готові). Більш складний спосіб зробити це - використовувати touchesBegan, touchesMovedі, touchesEndedщоб відстежувати пальці користувача, і правильно налаштувати властивість перетворення вашого подання.


можеш запропонувати мені будь-який приклад, пов’язаний з твоєю відповіддю. Як я можу збільшити та повернути зображення за допомогою методів дотиків Початок, дотиків Переміщення. Моє питання посилання => stackoverflow.com/questions/36833841 / ...
Mitesh Dobareeya

0

Майте на увазі, що ви не хочете збільшувати / зменшувати UIImage. Натомість спробуйте збільшити / зменшити вигляд, який містить контролер перегляду UIImage.

Я вирішив цю проблему. Погляньте на мій код:

@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()
    }

Примітка: Не забудьте підключити PinchGestureRecognizer.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.