NSImageView图像方面填充?

zum*_*zum 16 macos nsimageview

所以我习惯了UIImageView,并能够设置不同的方式来显示图像.比如AspectFill模式等......

我想在Mac应用程序上使用NSImageView完成同样的事情.在这方面,NSImageView的工作方式与UIImageView类似吗?或者我将如何在NSImageView中显示图像并选择不同的方式来显示该图像?

小智 24

您可能会发现将NSView子类化并提供一个为您填充方面填充的CALayer要容易得多.以下是此NSView子类的init可能是什么样子.

- (id)initWithFrame:(NSRect)frame andImage:(NSImage*)image
{
  self = [super initWithFrame:frame];
  if (self) {
    self.layer = [[CALayer alloc] init];
    self.layer.contentsGravity = kCAGravityResizeAspectFill;
    self.layer.contents = image;
    self.wantsLayer = YES;
  }
  return self;
}
Run Code Online (Sandbox Code Playgroud)

请注意,设置图层的顺序,然后设置wantsLayer非常重要(如果先设置wantsLayer,则会获得默认的背衬层).

您可以使用setImage方法来简单地更新图层的内容.


Pet*_*ete 14

这是我正在使用的,用 Swift 编写的。这种方法适用于故事板 - 只需使用普通的 NSImageView,然后将类框中的名称 NSImageView 替换为 MyAspectFillImageNSImageView ...

open class MyAspectFillImageNSImageView : NSImageView {
  
  open override var image: NSImage? {
    set {
      self.layer = CALayer()
      self.layer?.contentsGravity = kCAGravityResizeAspectFill
      self.layer?.contents = newValue
      self.wantsLayer = true
      
      super.image = newValue
    }
    
    get {
      return super.image
    }
  }

    public override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
    }
    
    //the image setter isn't called when loading from a storyboard
    //manually set the image if it is already set
    required public init?(coder: NSCoder) {
        super.init(coder: coder)
        
        if let theImage = image {
            self.image = theImage
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 没错 - 这是一个方面填充,而不是一个方面适合...Pet​​e (2认同)

one*_*sec 13

我有同样的问题.我希望缩放图像以填充,但保持原始图像的纵横比.奇怪的是,这并不像看起来那么简单,也不是NSImageView的开箱即用.我希望NSImageView在使用superview(s)调整大小时能够很好地扩展.我在github上找到了一个可插入的NSImageView子类:KPCScaleToFillNSImageView


wha*_*ale 6

您可以使用此方法:图像将被强制填充视图大小

(Aspect Fill)

imageView.imageScaling = .scaleAxesIndependently
Run Code Online (Sandbox Code Playgroud)


(外观适合)

imageView.imageScaling = .scaleProportionallyUpOrDown
Run Code Online (Sandbox Code Playgroud)


(中心顶部)

imageView.imageScaling = .scaleProportionallyDown
Run Code Online (Sandbox Code Playgroud)

这个对我有用。

  • 从文档中:_此设置不会保留图像的纵横比。_ (11认同)

Oly*_*tre 5

我很难弄清楚如何制作一个宽高比填充剪辑到边界

信用:https://osxentwicklerforum.de/index.php/Thread/28812-NSImageView-Scaling-Seitenverh%C3%A4ltnis/ 图片来源:https://osxentwicklerforum.de/index.php/Thread/28812-NSImageView-Scaling-Seitenverh%C3%A4ltnis/

最后我制作了自己的 NSImageView 子类,希望这可以帮助别人:

import Cocoa

@IBDesignable
class NSImageView_ScaleAspectFill: NSImageView {

    @IBInspectable
    var scaleAspectFill : Bool = false


    override func awakeFromNib() {
        // Scaling : .scaleNone mandatory
        if scaleAspectFill { self.imageScaling = .scaleNone }
    }

    override func draw(_ dirtyRect: NSRect) {

        if scaleAspectFill, let _ = self.image {

            // Compute new Size
            let imageViewRatio   = self.image!.size.height / self.image!.size.width
            let nestedImageRatio = self.bounds.size.height / self.bounds.size.width
            var newWidth         = self.image!.size.width
            var newHeight        = self.image!.size.height


            if imageViewRatio > nestedImageRatio {

                newWidth = self.bounds.size.width
                newHeight = self.bounds.size.width * imageViewRatio
            } else {

                newWidth = self.bounds.size.height / imageViewRatio
                newHeight = self.bounds.size.height
            }

            self.image!.size.width  = newWidth
            self.image!.size.height = newHeight

        }

        // Draw AFTER resizing
        super.draw(dirtyRect)
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,这样@IBDesignable您就可以在故事板中将其设置

警告

  • 我是 MacOS Swift 开发的新手,我来自 iOS 开发,这就是为什么我很惊讶我找不到ClipToBound属性,也许它存在但我找不到它!

  • 关于代码,我怀疑这会消耗大量资源,而且随着时间的推移,这还会产生修改原始图像比例的副作用。这种副作用对我来说似乎可以忽略不计。

再次,如果它们的设置允许NSImageView剪辑到边界,请删除此答案:]