我希望我的UIImageView增长或缩小,取决于它所显示的实际图像的大小。但我希望它保持垂直中心和10分,从前沿的超级视图。
但是,如果设置这两个约束,它会抱怨我没有设置足够的约束来满足自动布局。在我看来,它似乎完美地描述了我想要的东西。我遗漏了什么?
发布于 2014-11-10 00:22:05
图像视图的内在大小已经取决于图像的大小。你的假设(和约束是正确的)。
但是,如果您已经在接口构建器中设置了图像视图,并且没有为其提供图像,那么布局系统(接口构建器)将不知道在编译时图像视图应该有多大。您的布局是模棱两可的,因为您的图像视图可能有许多大小。这就是抛出错误的原因。
设置图像视图的图像属性后,图像视图的内在大小由图像大小定义。如果您在运行时设置视图,那么您可以按照Anna提到的那样做,并在图像视图的属性检查器中为接口生成器提供“占位符”内在大小。这告诉界面生成器,“现在使用这个大小,稍后我会给您一个真正的大小”。占位符约束在运行时被忽略。
您的另一个选择是直接将图像分配给接口生成器中的图像视图(但我假设您的图像是动态的,所以这对您不起作用)。
发布于 2017-03-07 17:19:45
这是一个基本的问题:UIImageView与自动布局交互的唯一方式是通过它的intrinsicContentSize属性。该属性提供图像本身的内在大小,仅此而已。这产生了三种情况,有不同的解决方案。
案例1:具有图像大小的视图
在第一种情况下,如果将UIImageView放置在外部自动布局约束只影响其位置的上下文中,则视图的intrinsicContentSize将声明它希望成为其图像的大小,而自动布局将自动调整视图的大小以等于其图像的大小。这有时正是你想要的,然后生活是美好的!
例2:全约束视图大小,保持图像的纵横比
其他时候,你的情况就不一样了。您知道您希望图像视图的大小,但也希望它保持显示图像的高宽比。在这种情况下,您可以使用自动布局来限制图像的大小,同时在图像视图上将旧的contentMode属性设置为.scaleAspectFit。该属性将导致图像视图重新显示显示的图像,并根据需要添加填充。如果这是你想要的,生活就是美好的!
案例3:部分受限的视图大小,适应图像的纵横比
但通常情况下,你会遇到棘手的第三种情况。您希望使用“自动布局”来部分确定视图的大小,同时允许图像的高宽比确定另一部分。例如,您可能希望使用“自动布局”约束来确定大小的一个维度(如垂直时间线滚动中的宽度),同时依赖该视图告诉“自动布局”它希望一个与图像的纵横比匹配的高度(因此可滚动项不会太短或太高)。
您不能配置一个普通的图像视图来实现这一点,因为图像视图只通信其intrinsicContentSize。因此,如果您将图像视图放置在自动布局约束一维的上下文中(例如,将其限制在较短的宽度),则图像视图不会告诉Auto Layout它希望将其高度串联起来。它继续报告它的内在内容大小,与图像本身未经修改的高度。
为了配置图像视图以告诉Auto布局它想要接受它包含的图像的纵横比,您需要为此添加一个新的约束。此外,每当图像本身被更新时,您将需要更新该约束。您可以构建一个执行此操作的UIImageView子类,因此行为是自动的。下面是一个例子:
public class ScaleAspectFitImageView : UIImageView {
  /// constraint to maintain same aspect ratio as the image
  private var aspectRatioConstraint:NSLayoutConstraint? = nil
  required public init?(coder aDecoder: NSCoder) {
    super.init(coder:aDecoder)
    self.setup()
  }
  public override init(frame:CGRect) {
    super.init(frame:frame)
    self.setup()
  }
  public override init(image: UIImage!) {
    super.init(image:image)
    self.setup()
  }
  public override init(image: UIImage!, highlightedImage: UIImage?) {
    super.init(image:image,highlightedImage:highlightedImage)
    self.setup()
  }
  override public var image: UIImage? {
    didSet {
      self.updateAspectRatioConstraint()
    }
  }
  private func setup() {
    self.contentMode = .scaleAspectFit
    self.updateAspectRatioConstraint()
  }
  /// Removes any pre-existing aspect ratio constraint, and adds a new one based on the current image
  private func updateAspectRatioConstraint() {
    // remove any existing aspect ratio constraint
    if let c = self.aspectRatioConstraint {
      self.removeConstraint(c)
    }
    self.aspectRatioConstraint = nil
    if let imageSize = image?.size, imageSize.height != 0
    {
      let aspectRatio = imageSize.width / imageSize.height
      let c = NSLayoutConstraint(item: self, attribute: .width,
                                 relatedBy: .equal,
                                 toItem: self, attribute: .height,
                                 multiplier: aspectRatio, constant: 0)
      // a priority above fitting size level and below low
      c.priority = (UILayoutPriorityDefaultLow + UILayoutPriorityFittingSizeLevel) / 2.0
      self.addConstraint(c)
      self.aspectRatioConstraint = c
    }
  }
}如需更多评论,请访问这个要旨
发布于 2018-01-27 13:47:38
对于@algal案例3,我所要做的就是
class ScaledHeightImageView: UIImageView {
    override var intrinsicContentSize: CGSize {
        if let myImage = self.image {
            let myImageWidth = myImage.size.width
            let myImageHeight = myImage.size.height
            let myViewWidth = self.frame.size.width
            let ratio = myViewWidth/myImageWidth
            let scaledHeight = myImageHeight * ratio
            return CGSize(width: myViewWidth, height: scaledHeight)
        }
        return CGSize(width: -1.0, height: -1.0)
    }
}这将缩放intrinsicContentSize的高度组件。(-1.0,-1.0)在没有图像时返回,因为这是超类中的默认行为。
此外,我不需要为包含图像视图的单元格的表设置UITableViewAutomaticDimension,而且单元格仍然自动大小。图像视图的内容模式是Aspect Fit。
https://stackoverflow.com/questions/26833627
复制相似问题