UIImageView捏缩放和重新定位以适合叠加

时间:2014-03-17 23:29:38

标签: ios uiimageview overlay pinchzoom

我正在使用UIImagePickerView从相机或相机胶卷中抓取照片。当用户选择'一个图像,我将图像插入UIImageView,它嵌套在UIScrollView中以允许捏/平移。我在图像视图上方有一个叠加层,它表示图像将被裁剪的区域(就像UIImagePickerView的.allowEditing属性为YES时一样)。

Apple提供的" allowEditing"功能也有同样的问题,我看到我的代码(我为什么我自己尝试自己编写它,我需要在叠加层中自定义形状)。问题是,我似乎无法找到让用户平移所有图像的好方法。总是有部分图像无法放置在裁剪窗口中。它总是满足于图像的边缘(可能是外部10%),无法平移到裁剪窗口。

unusable crop area

在上面的照片中,顶部和底部的棕色区域是滚动视图的背景颜色。图像视图的大小适合图像。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Calculate what height/width we'll need for our UIImageView.
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    float width = 0.0f, height = 0.0f;
    if (image.size.width > image.size.height) {
        width = screenSize.width;
        height =  image.size.height / (image.size.width/screenSize.width);
    } else {
        height = screenSize.height;
        width = image.size.width / (image.size.height/screenSize.height);
    }

    if (width > screenSize.width) {
        height /= (width/screenSize.width);
        width = screenSize.width;
    }
    if (height > screenSize.height) {
        width /= (height/screenSize.height);
        height = screenSize.height;
    }

    // Update the image view to the size of the image and center it.
    // Image view is a subview of the scroll view.
    imageView.frame = CGRectMake((screenSize.width - width) / 2, (screenSize.height - height) / 2, width, height);
    imageView.image = image;
    // Setup our scrollview so we can scroll and pinch zoom the image!
    imageScrollView.contentSize = CGSizeMake(screenSize.width, screenSize.height);

    // Close the picker.
    [[picker presentingViewController] dismissViewControllerAnimated:YES completion:NULL];
}

我已经考虑过监控滚动视图的滚动位置和缩放级别,并禁止图像的一侧进入裁剪"最佳位置"图像。然而,这似乎过度工程化了。

有谁知道如何实现这个目标?

1 个答案:

答案 0 :(得分:2)

我是个白痴。晚安的睡眠可以带来多大的不同;-)希望它能帮助将来的某个人。

设置正确的滚动视图 contentSize contentInset 可以解决问题。工作代码如下。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Change the frame of the image view so that it fits the image!
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    float width = 0.0f, height = 0.0f;
    if (image.size.width > image.size.height) {
        width = screenSize.width;
        height = image.size.height / (image.size.width/screenSize.width);
    } else {
        height = screenSize.height;
        width = image.size.width / (image.size.height/screenSize.height);
    }

    // Make sure the new height and width aren't bigger than the screen
    if (width > screenSize.width) {
        height /= (width/screenSize.width);
        width = screenSize.width;
    }
    if (height > screenSize.height) {
        width /= (height/screenSize.height);
        height = screenSize.height;
    }

    CGRect overlayRect = cropOverlay.windowRect;

    imageView.frame = CGRectMake((screenSize.width - width) / 2, (screenSize.height - height) / 2, width, height);
    imageView.image = image;

    // Setup our scrollview so we can scroll and pinch zoom the image!
    imageScrollView.contentSize = imageView.frame.size;
    imageScrollView.contentInset = UIEdgeInsetsMake(overlayRect.origin.y - imageView.frame.origin.y,
                                                    overlayRect.origin.x,
                                                    overlayRect.origin.y + imageView.frame.origin.y,
                                                    screenSize.width - (overlayRect.origin.x + overlayRect.size.width));

    // Dismiss the camera's VC
    [[picker presentingViewController] dismissViewControllerAnimated:YES completion:NULL];
}

滚动视图和图像视图的设置如下:

imageScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
imageScrollView.showsHorizontalScrollIndicator = NO;
imageScrollView.showsVerticalScrollIndicator = NO;
imageScrollView.backgroundColor = [UIColor blackColor];
imageScrollView.userInteractionEnabled = YES;
imageScrollView.delegate = self;
imageScrollView.minimumZoomScale = MINIMUM_SCALE;
imageScrollView.maximumZoomScale = MAXIMUM_SCALE;
[self.view addSubview:imageScrollView];

imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.backgroundColor = [UIColor grayColor]; // I had this set to gray so I could see if/when it didn't align properly in the scroll view.  You'll likely want to change it to black
[imageScrollView addSubview:imageView];

编辑3-21-14更新,更漂亮,更好地实现计算将图像放在屏幕和滚动视图中的位置的方法。那么更好的是什么?此新实现将检查正在设置为宽度或高度为SMALLER的scrollview中的任何图像,并调整图像视图的框架,使其扩展为至少与叠加矩形,因此您无需担心用户选择的图像不适合您的叠加层。耶!

- (void)imagePickerController:(UIImagePickerController *)pickerUsed didFinishPickingMediaWithInfo:(NSDictionary *)info {

    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Change the frame of the image view so that it fits the image!
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    float width = 0.0f, height = 0.0f;
    if (image.size.width > image.size.height) {
        width = screenSize.width;
        height = image.size.height / (image.size.width/screenSize.width);
    } else {
        height = screenSize.height;
        width = image.size.width / (image.size.height/screenSize.height);
   }

   CGRect overlayRect = cropOverlay.windowRect;

    // We should check the the width and height are at least as big as our overlay window
    if (width < overlayRect.size.width) {
        float ratio = overlayRect.size.width / width;
        width *= ratio;
        height *= ratio;
    }
    if (height < overlayRect.size.height) {
        float ratio = overlayRect.size.height / height;
        height *= ratio;
        width *= ratio;
    }

    CGRect imageViewFrame = CGRectMake((screenSize.width - width) / 2, (screenSize.height - height) / 2, width, height);
    imageView.frame = imageViewFrame;
    imageView.image = image;

    // Setup our scrollview so we can scroll and pinch zoom the image!
    imageScrollView.contentSize = imageView.frame.size;
    imageScrollView.contentInset = UIEdgeInsetsMake(overlayRect.origin.y - imageView.frame.origin.y,
                                                    (imageViewFrame.origin.x * -1) + overlayRect.origin.x,
                                                    overlayRect.origin.y + imageView.frame.origin.y,
                                                    imageViewFrame.origin.x + (screenSize.width - (overlayRect.origin.x + overlayRect.size.width)));

    // Calculate the REAL minimum zoom scale!
    float minZoomScale = 1 - MIN(fabsf(fabsf(imageView.frame.size.width) -  fabsf(overlayRect.size.width)) /  imageView.frame.size.width,
                           fabsf(fabsf(imageView.frame.size.height) - fabsf(overlayRect.size.height)) / imageView.frame.size.height);
    imageScrollView.minimumZoomScale = minZoomScale;

    // Dismiss the camera's VC
    [[picker presentingViewController] dismissViewControllerAnimated:YES completion:NULL];
}