Заполнение изображения NSImageView?

Так что я привык к UIImageView, и могу устанавливать разные способы отображения его изображения в нем. Как, например, режим AspectFill т.д...

Я хотел бы добиться того же, используя NSImageView в приложении Mac. NSImageView ли NSImageView аналогично UIImageView в этом отношении, или как мне показать изображение в NSImageView и выбрать различные способы отображения этого изображения?

Ответ 1

Возможно, вам будет гораздо проще NSView подкласс NSView и предоставить CALayer который выполняет этот аспект за вас. Вот как может выглядеть init для этого подкласса NSView.

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

Обратите внимание, что порядок установки слоя, а затем настройки wantLayer очень важен (если вы сначала зададите wantLayer, вместо этого вы получите слой подложки по умолчанию).

Вы можете иметь метод setImage который просто обновляет содержимое слоя.

Ответ 2

У меня была та же проблема. Я хотел, чтобы изображение масштабировалось для заполнения, но сохраняло соотношение сторон исходного изображения. Как ни странно, это не так просто, как кажется, и не выходит из строя с NSImageView. Я очень хотел, чтобы шкала NSImageView красиво изменялась с помощью супервизора. Я создал подкаталог NSImageView, который вы можете найти в github: KPCScaleToFillNSImageView

Ответ 3

Вы можете использовать это: изображение будет принудительно заполнить размер представления

(Аспект заполнения)

imageView.imageScaling = .scaleAxesIndependently


(Aspect Fit)

imageView.imageScaling = .scaleProportionallyUpOrDown


(Центр сверху)

imageView.imageScaling = .scaleProportionallyDown

Это работает для меня.

Ответ 4

Вот что я использую, написанное с помощью Swift. Этот подход хорошо подходит для раскадровки - просто используйте обычный NSImageView, а затем замените имя NSImageView в поле Class с помощью 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
    }
  }
}

Ответ 5

Для получения AspectFit свойства UIImageView в Cocoa NSImageView используйте этот метод

[imageView setImageScaling:NSScaleProportionally];

Здесь вы можете изменить свойства отображения изображения.

enum {
    NSScaleProportionally = 0, // Deprecated. Use NSImageScaleProportionallyDown
    NSScaleToFit,              // Deprecated. Use NSImageScaleAxesIndependently
    NSScaleNone                // Deprecated. Use NSImageScaleNone
};

Ответ 6

Я с трудом пытался понять, как сделать Aspect Fill Clip to Bounds:

Credit : 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)
    }
}

Плюс это @IBDesignable так что вы можете установить его в StoryBoard

ПРЕДУПРЕЖДЕНИЯ

  • Я новичок в разработке MacOS Swift, я пришел из разработки для iOS, поэтому я удивился, что не смог найти свойство clipToBound, возможно, оно существует, и я не смог его найти!

  • Что касается кода, я подозреваю, что это потребляет много, а также имеет побочный эффект для изменения исходного соотношения изображения с течением времени. Этот побочный эффект казался мне незначительным.

Еще раз, если это настройка, которая позволяет NSImageView обрезать границы, удалите этот ответ:]