Подтвердить что ты не робот

IOS: frame.size.width/2 не создает круг на каждом устройстве

Я знаю, что формулы frame.size.width/2 должны создавать границу круга, однако в XCode я в настоящее время испытываю некоторые несоответствия.

У меня есть два тестовых устройства (iPhone6 ​​и iPod touch 5-го поколения). У меня также работает симулятор. Оба моих устройства отображаются правильно, но симулятор рисует круг как закругленный прямоугольник:

enter image description here

Код, который я использую для достижения этого (хотя и очень простой):

imgAvatar.layer.masksToBounds = true
imgAvatar.clipsToBounds = true
imgAvatar.layer.cornerRadius = imgAvatar.frame.size.width/2
imgAvatar.layer.borderWidth = 5
imgAvatar.layer.borderColor = UIColor.whiteColor().CGColor

Есть ли причина, почему это происходит? Это сводит меня с ума!

ОБНОВЛЕНИЕ Чтобы очистить путаницу, UIImageView объявлен в моем раскадровке как 190x190, он также имеет ограничение на соотношение сторон 1:1, чтобы гарантировать, что он поддерживает пропорциональную ширину и высоту.

ОБНОВЛЕНИЕ 2 Чтобы помещать какие-либо подозрения в отношении ограничений, связанных с автоматической компоновкой, я добавил следующее изображение, которое показывает ограничения, установленные для imgAvatar. Поскольку вы можете видеть совпадение по ширине и высоте, и AR установлен, чтобы гарантировать, что он поддерживает соотношение 1:1. Я надеюсь, что это устранит любые дальнейшие сомнения.

enter image description here

ANSWER Леонардо указал на чрезвычайно практичное и многоразовое решение для решения этой проблемы, используя расширения Swift, можно гарантировать, что данный UIImage всегда квадратный, поэтому всегда создавая круг, я опубликовал решение Leonardo ниже:

extension UIImage {
    var circleMask: UIImage {
        let square = size.width < size.height ? CGSize(width: size.width, height: size.width) : CGSize(width: size.height, height: size.height)
        let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square))
        imageView.contentMode = UIViewContentMode.ScaleAspectFill
        imageView.image = self
        imageView.layer.cornerRadius = square.width/2
        imageView.layer.borderColor = UIColor.whiteColor().CGColor
        imageView.layer.borderWidth = 5
        imageView.layer.masksToBounds = true
        UIGraphicsBeginImageContext(imageView.bounds.size)
        imageView.layer.renderInContext(UIGraphicsGetCurrentContext())
        let result = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return result
    }
}

imgAvatar.image = yourImage.circleMask
4b9b3361

Ответ 1

Вы можете создать расширение, чтобы применить маску и границу прямо к вашему изображению, чтобы она всегда работала без учета размера/масштаба экрана:

extension UIImage {
    var circleMask: UIImage {
        let square = CGSize(width: min(size.width, size.height), height: min(size.width, size.height))
        let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square))
        imageView.contentMode = UIViewContentMode.ScaleAspectFill
        imageView.image = self
        imageView.layer.cornerRadius = square.width/2
        imageView.layer.borderColor = UIColor.whiteColor().CGColor
        imageView.layer.borderWidth = 5
        imageView.layer.masksToBounds = true
        UIGraphicsBeginImageContext(imageView.bounds.size)
        imageView.layer.renderInContext(UIGraphicsGetCurrentContext())
        let result = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return result
    }
}

imgAvatar.image = yourImage.circleMask

Ответ 2

Ну, Autolayout должна быть проблема. Как видно, высота imgAvatar на праве больше высоты imgAvatar на слева.

Размер imgAvatar справа - 190 x 190, а один слева - 200 x 200, а слева - радиус угла, который вы устанавливаете 190/2, т.е. 95px, тогда как он должен быть 100px.

Подскажите Высота и Ширина. Ограничение в файле nib для imgAvatar, если вы не хотите, чтобы imgAvatar изменил размер на 1:. 1

  • Выберите imgAvatar в своем nib.
  • Редактоp > Вывод > Высота
  • Выберите imgAvatar в своем nib.
  • Редактоp > Вывод > Ширина

ИЛИ

Попробуйте переместить код на viewDidLayoutSubviews

ИЛИ

Подкласс your UIImageView и установите его радиус угла в методе awakeFromNib

Пожалуйста, сообщите нам, если это сработает. Спасибо!

Ответ 3

Если вы тестируете в iOS8.3, вы должны вызвать layoutIfNeed на свой объект пользовательского интерфейса, прежде чем получить его фрейм. Пожалуйста, прочитайте примечания о выпуске iOS8.3

Например:

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// code that sets up the button, but doesn’t yet add it to a window
CGRect titleFrame = button.titleLabel.frame;
// code that relies on the correct value for titleFrame

Теперь вам нужно:

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
// code that sets up the button, but doesn’t yet add it to a window
[button layoutIfNeeded]; // This is also safe pre-iOS 8.3
CGRect titleFrame = button.titleLabel.frame;
// code that relies on the correct value for titleFrame

Он сказал, что для UIButton и подклассов, но вы можете попробовать его также с вашим объектом пользовательского интерфейса.

При связывании с iOS 8.3 любой код, который опирается на макет информацию (например, фрейм) подпрограммы UIButton, когда кнопка не в иерархии окон, нужно будет отправить layoutIfNeeded в перед извлечением информации о макете (например, button.titleLabel.frame), чтобы убедиться, что значения макета до дата.

Кроме того, поскольку для параметра imgAvatar cornerRadius установлено значение 1/2 размера imgFrame, вы получите круг, только если это значение cornerRadius = 1/2 от ширины imgAvatar (и высоты).

Итак, после вызова:

imgAvatar.layer.cornerRadius = imgFrame.frame.size.width/2

проверьте:

  • размер кадра imgAvatar и его cornerRadius
  • убедитесь, что изображение квадратно.

Ответ 4

Проблема заключается в том, что при использовании круга границы представления по-прежнему считаются по умолчанию (320x480), поэтому, если вы установили ограничения, связанные с экраном, изображение будет больше например, на iPhone 6/6 +.

Существуют различные решения, но если вы хотите быстрый, просто поместите свой код:

imgAvatar.layer.cornerRadius = imgFrame.frame.size.width/2

в - viewDidLayoutSubviews в вашем контроллере просмотра или в - layoutSubviews в вашем представлении, проверить раньше, если cornerRadius отличается от ширины /2 кадра изображения. Что-то вроде этого:

if (imgAvatar.layer.cornerRadius != imgFrame.frame.size.width/2) {
    imgAvatar.layer.cornerRadius = imgFrame.frame.size.width/2
}

Ответ 5

Используемая вами формула будет работать только для квадрата изображения. Вы используете автоматическую раскладку? Возможно, это может быть растянуто для устройства, которое вы использовали. Если это так, то высота будет выше, чем ширина, или наоборот. То есть изображение будет своего рода прямоугольником, и оно не будет создавать идеальный круг.

Ответ 6

Спасибо @leo Dabus за оригинальное решение. Это просто обновление для swift 4.2.

import UIKit
extension UIImage {
    var circleMask: UIImage {
        let square = size.width < size.height ? CGSize(width: size.width, height: size.width) : CGSize(width: size.height, height: size.height)
        let imageView = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: square))
        imageView.contentMode = UIView.ContentMode.scaleAspectFill
        imageView.image = self
        imageView.layer.cornerRadius = square.width/2
        imageView.layer.borderColor = UIColor.white.cgColor
        imageView.layer.borderWidth = 5
        imageView.layer.masksToBounds = true
        UIGraphicsBeginImageContext(imageView.bounds.size)
        imageView.layer.render(in: UIGraphicsGetCurrentContext()!)
        let result = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return result!
    }
}