使用AutoLayout调整UIImageView大小以匹配图像

19

我想把我的UIImageView的高度/宽度改成与我从相册选择的图片相匹配,我在这里找到了一个能做到这一点的代码片段。

-(CGRect)frameForImage:(UIImage *)imgs inImageViewAspectFit:(UIImageView *)imagev
{
  float imageRatio = imgs.size.width / imgs.size.height;
  float viewRatio = imagev.frame.size.width / imagev.frame.size.height;
  if(imageRatio < viewRatio)
  {
    float scale = imagev.frame.size.height / imgs.size.height;
    float width = scale * imgs.size.width;
    float topLeftX = (imagev.frame.size.width - width) * 0.5;
    NSLog(@"image after aspect fit: width=%f",width);
    imagev.frame = CGRectMake(topLeftX, 0, width, imagev.frame.size.height);
    return CGRectMake(topLeftX, 0, width, imagev.frame.size.height);
  }
  else
  {
    float scale = imagev.frame.size.width / imgs.size.width;
    float height = scale * imgs.size.height;
    float topLeftY = (imagev.frame.size.height - height) * 0.5;
    NSLog(@"image after aspect fit: height=%f", height);
    imagev.frame = CGRectMake(0, topLeftY, imagev.frame.size.width, height);
    return CGRectMake(0, topLeftY, imagev.frame.size.width, height);
  }
}
问题在于当我从按钮调用它时,它会改变UIImageView的高度/宽度。
- (IBAction)changeSize:(id)sender
{
  [self frameForImage:image inImageViewAspectFit:self.imageView];    
}

但是我希望在选择相册中的图片后立即执行此操作,这就是我的设置方式。

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  image = [info objectForKey:UIImagePickerControllerOriginalImage];
  [self.imageView setImage:image];
  [self frameForImage:image inImageViewAspectFit:self.imageView];
  [self dismissViewControllerAnimated:YES completion:NULL];
}

请仅在询问IDE本身的问题时使用[tag:xcode]标记。谢谢! - Undo
只需在UIImageView(检查器中)中选择ASPECT FIT - 就完成了。就是这样简单,完全自动化。 - Fattie
2个回答

32

自动布局解决方案

既然您在项目中使用了自动布局,我已经制作了一个演示应用程序,以展示您如何更改图像视图的图像并调整其高度。自动布局将自动完成这项工作,但问题是您将使用来自用户库的照片,因此它们很可能非常大。

请查看该应用程序:https://bitbucket.org/danielphillips/auto-layout-imageview

诀窍是创建图像视图高度的NSLayoutConstraint引用。当您更改图像时,需要根据固定的宽度将其常量调整为正确的高度。

您的另一个解决方案可以是在图像视图上设置contentMode,通过使用UIViewContentModeScaleAspectFit,您的图像将始终完全显示,但将锁定为图像视图的边界,该边界可以根据您拥有的自动布局约束而更改。

初始回复

看起来您把问题搞得太复杂了,除非我错过了什么。

当您从图像选择器获得新图像时,您只需根据UIImage的大小更改图像视图的框架即可。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  image = [info objectForKey:UIImagePickerControllerOriginalImage];
  [self.imageView setImage:image];
  self.imageView.frame = CGRectMake(self.imageView.frame.origin.x
                                    self.imageView.frame.origin.y
                                    image.size.width
                                    image.size.height);
  [self dismissViewControllerAnimated:YES completion:NULL];
}

当然,这可能会非常庞大(它使用可能非常大的原始图像)。

所以让我们将宽度锁定为280个点... 这样我们可以在竖屏模式下始终完整地显示图像。

因此,假设您的图像大小为1000x800,而我们的图像视图可能是280x100。我们可以像这样计算保留图像视图宽度的正确高度:

CGSize imageSize        = CGSizeMake(1000.0, 800.0);
CGSize imageViewSize    = CGSizeMake(280.0, 100.0);

CGFloat correctImageViewHeight = (imageViewSize.width / imageSize.width) * imageSize.height;

self.imageView.frame = CGRectMake(  self.imageView.frame.origin.x,
                                    self.imageView.frame.origin.x,
                                    CGRectGetWidth(self.imageView.bounds),
                                    correctImageViewHeight);

3
我尝试了你的第一段代码,但如果我不添加 [self.imageView setTranslatesAutoresizingMaskIntoConstraints:YES]; 的话,它不会改变宽度和高度。 - Mike Tyson
1
控制台输出显示“将尝试通过打破约束<NSLayoutConstraint:0x71ad740 UIImageView:0x71ac340.trailing == UIView:0x71ac5f0.trailing>来恢复在调试器中捕获objc_exception_throw异常。在<UIKit/UIView.h>中列出的UIView上的UIConstraintBasedLayoutDebugging类别中的方法也可能有所帮助。”但它仍然可以工作。 - Mike Tyson
2
你正在使用AutoLayout。这是一个非常重要的细节。 - Daniel

5
这是一个Swift类,可以帮助根据您选择的宽度或高度限制返回正确的图像大小:
class func returnImageSizeForHeightLimit(heightLimit:CGFloat?, orWidthLimit widthLimit:CGFloat?, forImage theImage:UIImage)->CGSize?{

    if let myHeightLimit = heightLimit {

        let theWidth = (myHeightLimit/theImage.size.height) * theImage.size.width

        return CGSizeMake(theWidth, myHeightLimit)
    }

    if let myWidthLimit = widthLimit {

        let theHeight = (myWidthLimit/theImage.size.width) * theImage.size.height

        return CGSizeMake(myWidthLimit, theHeight)
    }

    return nil
}

1
最好将其重写为UIImage扩展 ;) - Shmidt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接