英文:
Can't position UIImage through CGRect
问题
我正在尝试构建一个社交媒体用户个人资料的UIView,但在一开始就遇到了问题 - 当我尝试将用户图像(UIImage)添加到我的UIView时。以下是我尝试使用的代码:
import UIKit
class ProfileHeaderView: UIView {
private lazy var profileImage: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "hipsterCat"))
// 让图像变成圆形
imageView.layer.cornerRadius = imageView.frame.size.width / 2
imageView.clipsToBounds = true
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 3
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
backgroundColor = .lightGray
addSubview(profileImage)
}
override func layoutSubviews() {
super.layoutSubviews()
profileImage.frame = CGRect(
x: bounds.midX - 64,
y: bounds.midY - 64,
width: 128,
height: 128
)
}
}
我的任务是使用CGRect在父视图上定位UIImage,但一旦运行项目,它就不会显示在屏幕上(只有浅灰色背景可见)。
UIImageView没问题,当注释掉layoutSubviews()重写时图像会出现,但它没有定位。
英文:
I'm trying to build a UIView of Social Media User's Profile and got stuck right in the beginning - when adding a User Image (UIImage) to my UIView. Here's the code I'm trying to use:
import UIKit
class ProfileHeaderView: UIView {
private lazy var profileImage: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "hipsterCat"))
// Making Image Round
imageView.layer.cornerRadius = imageView.frame.size.width / 2
imageView.clipsToBounds = true
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 3
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
backgroundColor = .lightGray
addSubview(profileImage)
}
override func layoutSubviews() {
super.layoutSubviews()
profileImage.frame = CGRect(
x: bounds.midX - 64,
y: bounds.midY - 64,
width: 128,
height: 128
)
}
}
My task is to use CGRect to position UIImage on the superView, yet once I run the project it just doesn't appear on the screen (only light gray background is there).
UIImageView is all right, the image appears when commenting layoutSubviews() override but it's not positioned.
答案1
得分: 1
有多个可能出错的地方。你看到的最奇怪的结果是,一旦调整大小,你就完全看不到图像。
我最好的猜测是你也在ProfileHeaderView
实例上设置了frame。请注意,有两个用于布局视图的API;一个是使用frame
,另一个是自动布局。从自动布局中将调用一个名为layoutSubviews
的方法。但是使用frame
时,只会调用frame
。因此,你可能漏掉了另一个重写。
尝试添加以下内容:
override var frame: CGRect {
didSet {
updateImagePosition()
}
}
override func layoutSubviews() {
super.layoutSubviews()
updateImagePosition()
}
private func updateImagePosition() {
profileImage.contentMode = .scaleAspectFit
profileImage.frame = CGRect(
x: bounds.midX - 64,
y: bounds.midY - 64,
width: 128,
height: 128
)
profileImage.layer.cornerRadius = 64
}
除了添加对frame的重写之外,我还添加了两个选项,以确定视图的content mode。你可能想将其移到设置方法中,但如果保留在这里也不太糟糕。另一个是设置圆角半径,这肯定需要在这里设置。两者都由@HangarRash提到。
最后,公平地说,最好有类似以下的内容:
@IBDesignable
class ProfileHeaderView: UIView {
@IBInspectable
private var imageName: String = "hipsterCat" {
didSet {
profileImage.image = UIImage(named: imageName)
}
}
@IBInspectable
private var imageRadius: CGFloat = 64 {
didSet {
updateImagePosition()
}
}
private lazy var profileImage: UIImageView = {
let imageView = UIImageView(image: UIImage(named: imageName))
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 3
return imageView
}()
override var frame: CGRect {
didSet {
updateImagePosition()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
backgroundColor = .lightGray
addSubview(profileImage)
}
override func layoutSubviews() {
super.layoutSubviews()
updateImagePosition()
}
private func updateImagePosition() {
profileImage.frame = CGRect(
x: bounds.midX - imageRadius,
y: bounds.midY - imageRadius,
width: imageRadius*2.0,
height: imageRadius*2.0
)
profileImage.layer.cornerRadius = imageRadius
}
}
英文:
There are multiple things that might have gotten wrong. The strangest result you are seeing is that you don't see the image at all once it is resized.
My best guess is that you are also setting the frame for the ProfileHeaderView
instance. Note that there are 2 APIs for lay outing the views; one is using frame
and the other one is auto layout. From auto layout a method layoutSubviews
will be called. But using frame
then only frame
will be called. So you may be missing another override.
Try to add the following:
override var frame: CGRect {
didSet {
updateImagePosition()
}
}
override func layoutSubviews() {
super.layoutSubviews()
updateImagePosition()
}
private func updateImagePosition() {
profileImage.contentMode = .scaleAspectFit
profileImage.frame = CGRect(
x: bounds.midX - 64,
y: bounds.midY - 64,
width: 128,
height: 128
)
profileImage.layer.cornerRadius = 64
}
Next to adding an override for frame I have also added to option to determine content mode of your view. You might want to move that into your setup method but it is not too bad if it stays here. And the other one is setting corner radius which for sure needs to be set in here. Both mentioned by @HangarRash.
In the end it would be nice to have something like the following to be fair:
@IBDesignable
class ProfileHeaderView: UIView {
@IBInspectable
private var imageName: String = "hipsterCat" {
didSet {
profileImage.image = UIImage(named: imageName)
}
}
@IBInspectable
private var imageRadius: CGFloat = 64 {
didSet {
updateImagePosition()
}
}
private lazy var profileImage: UIImageView = {
let imageView = UIImageView(image: UIImage(named: imageName))
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 3
return imageView
}()
override var frame: CGRect {
didSet {
updateImagePosition()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
backgroundColor = .lightGray
addSubview(profileImage)
}
override func layoutSubviews() {
super.layoutSubviews()
updateImagePosition()
}
private func updateImagePosition() {
profileImage.frame = CGRect(
x: bounds.midX - imageRadius,
y: bounds.midY - imageRadius,
width: imageRadius*2.0,
height: imageRadius*2.0
)
profileImage.layer.cornerRadius = imageRadius
}
}
答案2
得分: 0
我遵循了@HangarRash在评论中的建议,并成功解决了问题。我所做的是在layoutSubViews
中设置了圆角半径(使图像变成圆形),同时还向UIImageView添加了.scaleAspectFill
。最终的代码如下:
import UIKit
class ProfileHeaderView: UIView {
private lazy var profileImage: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "hipsterCat"))
imageView.contentMode = .scaleAspectFill
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
backgroundColor = .lightGray
addSubview(profileImage)
}
override func layoutSubviews() {
super.layoutSubviews()
profileImage.frame = CGRect(
x: bounds.minX + 16,
y: bounds.minY + 16,
width: 128,
height: 128
)
//Making image round
profileImage.layer.cornerRadius = profileImage.frame.size.width / 2
profileImage.clipsToBounds = true
profileImage.layer.borderColor = UIColor.white.cgColor
profileImage.layer.borderWidth = 3
}
}
英文:
I was following @HangarRash advice from the comments and managed to fix the issue. The thing I did is setting corner radius (and making image rounded) in layoutSubViews
while also adding .scaleAspectFill
to UIImageView. The final code is:
import UIKit
class ProfileHeaderView: UIView {
private lazy var profileImage: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "hipsterCat"))
imageView.contentMode = .scaleAspectFit
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
private func setupView() {
backgroundColor = .lightGray
addSubview(profileImage)
}
override func layoutSubviews() {
super.layoutSubviews()
profileImage.frame = CGRect(
x: bounds.minX + 16,
y: bounds.minY + 16,
width: 128,
height: 128
)
//Making image round
profileImage.layer.cornerRadius = profileImage.frame.size.width / 2
profileImage.clipsToBounds = true
profileImage.layer.borderColor = UIColor.white.cgColor
profileImage.layer.borderWidth = 3
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论