UIImage Контентный режим aspectFit и bottom - PullRequest
0 голосов
/ 10 апреля 2020

Можно ли установить contentMode для моих UIImage на .scaleAspectFit и .bottom одновременно?

Вот так выглядит мое изображение в данный момент:

enter image description here

UIImageView:

let nightSky: UIImageView = {
    let v = UIImageView()
    v.image = UIImage(named: "nightSky")
    v.translatesAutoresizingMaskIntoConstraints = false
    v.contentMode = .scaleAspectFit
    return v
}()

Ограничения:

nightSky.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        nightSky.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -120).isActive = true
        nightSky.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
        nightSky.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true

1 Ответ

1 голос
/ 10 апреля 2020

Вот пользовательский класс, который допускает свойства Aspect Fit и Alignment.

Он помечен @IBDesignable, поэтому его можно увидеть в Storyboard / Interface Builder.

Свойства @IBInspectable являются:

  • Изображение
  • Горизонтальное выравнивание
  • Вертикальное выравнивание

enter image description here

Выберите изображение, как для обычного UIImageView.

Допустимые значения для HAlign - «влево», «по центру», «вправо» или оставить пустым значение по умолчанию (по центру).

Допустимые значения для VAlign - «сверху», «центр» "внизу" или оставьте пустым значение по умолчанию (в центре).

@IBDesignable
class AlignedAspectFitImageView: UIView {

    enum HorizontalAlignment: String {
        case left, center, right
    }

    enum VerticalAlignment: String {
        case top, center, bottom
    }

    private var theImageView: UIImageView = {
        let v = UIImageView()
        return v
    }()

    @IBInspectable var image: UIImage? {
        get { return theImageView.image }
        set {
            theImageView.image = newValue
            setNeedsLayout()
        }
    }

    @IBInspectable var hAlign: String = "center" {
        willSet {
            // Ensure user enters a valid alignment name while making it lowercase.
            if let newAlign = HorizontalAlignment(rawValue: newValue.lowercased()) {
                horizontalAlignment = newAlign
            }
        }
    }

    @IBInspectable var vAlign: String = "center" {
        willSet {
            // Ensure user enters a valid alignment name while making it lowercase.
            if let newAlign = VerticalAlignment(rawValue: newValue.lowercased()) {
                verticalAlignment = newAlign
            }
        }
    }

    var horizontalAlignment: HorizontalAlignment = .center
    var verticalAlignment: VerticalAlignment = .center

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    func commonInit() -> Void {
        addSubview(theImageView)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        guard let img = theImageView.image else {
            return
        }

        var newRect = bounds

        let viewRatio = bounds.size.width / bounds.size.height
        let imgRatio = img.size.width / img.size.height

        // if view ratio is equal to image ratio, we can fill the frame
        if viewRatio == imgRatio {
            theImageView.frame = newRect
            return
        }

        // otherwise, calculate the desired frame

        if imgRatio < 1.0 {
            // image is taller than wide
            let heightFactor = bounds.size.height / img.size.height
            let w = img.size.width * heightFactor
            newRect.size.width = w
            switch horizontalAlignment {
            case .center:
                newRect.origin.x = (bounds.size.width - w) * 0.5
            case .right:
                newRect.origin.x = bounds.size.width - w
            default: break  // left align - no changes needed
            }
        } else {
            // image is wider than tall
            let widthFactor = bounds.size.width / img.size.width
            let h = img.size.height * widthFactor
            newRect.size.height = h
            switch verticalAlignment {
            case .center:
                newRect.origin.y = (bounds.size.height - h) * 0.5
            case .bottom:
                newRect.origin.y = bounds.size.height - h
            default: break  // top align - no changes needed
            }
        }

        theImageView.frame = newRect
    }
}

Использование этого изображения:

enter image description here

Вот как это выглядит с 240 x 240 AlignedAspectFitImageView с заданным желтым цветом фона (чтобы мы могли видеть рамку):

enter image description here

Свойства также могут быть установлены с помощью кода. Например:

override func viewDidLoad() {
    super.viewDidLoad()

    let testImageView = AlignedAspectFitImageView()
    testImageView.image = UIImage(named: "bkg640x360")
    testImageView.verticalAlignment = .bottom

    view.addSubview(testImageView)

    // set frame / constraints / etc
    testImageView.frame = CGRect(x: 40, y: 40, width: 240, height: 240)
}
...