我目前正在通过Udacity
iOS开发Nanaodegree工作,并遇到了一个我真正难以解决的问题。我是开发人员和Stackoverflow的新手,所以这是我的第一篇文章....这里就是了;
我正在构建一个用于生成Memes的应用程序。它允许用户选择图像并输入一些文本。
我有UIView
。在那UIView
我有2x UIToolbar
,2x UITextField
和UIImageView
。工具栏位于视图的顶部和底部,文本字段分别位于其下方和上方。 UIImageView
空间与视图的完整位置和高度,位于工具栏和textInputs下方。
请参阅此处查看screenshots of Storyboard and app
用户可以从其相册中选择图像,或使用相机拍照,以填充UIImageView
。然后将UIImageView
设置为Aspect Fit
以保持其正确的宽高比。
我在Interface Builder中设置了约束,以便UITextFields
与顶部和底部工具栏保持恒定距离。
我遇到的问题是用户需要旋转设备以定位文本字段,以便它们位于图像的顶部和底部。我的意思是,如果用户选择横向图像,并且设备是纵向的,则用户需要旋转他们的设备以确保文本字段位于图像的顶部。
我想要做的是在用户选择或拍摄图像并且图像已应用Aspect Fit后重新定位textFields。
有人建议我可以使用AVMakeRectWithAspectRatioInside
生成CGRect
与UIImage
相同的尺寸后应用Aspect Fit,使用CGRect更新框架UIImageView
,然后更新约束。
我设法生成了新的CGRect
并更新了UIImageView
的框架。然后我更改了UITextFields
上的约束,以便它们与UIImageView
而不是工具栏对齐,但UITextFields
在更新框架时不会重新定位。
我在更新框架后调用以下内容;
view.setNeedUpdateConstraints()
如果有人有最好的方法来解决这个问题会很棒。
编辑:
以下是我创建的项目中viewController的代码,用于隔离并尝试解决此问题。
import UIKit
import AVFoundation
class ViewController: UIViewController {
@IBOutlet weak var imageViewPic: UIImageView!
@IBOutlet weak var topTextToToolberContraint: NSLayoutConstraint!
@IBOutlet weak var bottomTextToToolbarConstraint: NSLayoutConstraint!
@IBOutlet weak var topText: UILabel!
@IBOutlet weak var bottomText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
let imageToDisplay = UIImage(named: "Captain-Picard-Facepalm")
imageViewPic.image = imageToDisplay
}
func updateFrame() {
let resizedImageSize = imageViewPic.image!.size
let imageViewBounds = imageViewPic.bounds
let newRect = AVMakeRectWithAspectRatioInsideRect(resizedImageSize, imageViewBounds)
imageViewPic.frame = newRect
}
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
updateFrame()
view.setNeedsLayout()
}
}
答案 0 :(得分:0)
我观察到这里的问题是绘制/渲染视图。所以像视图之类的东西在实际布局发生之前绘制,这意味着在视图不渲染之前帧不会改变。
这里你可以做的是在实际绘图发生之前的早期强制布局。有一种方法可用,可以在查看框架更新时处理强制布局视图。
func setNeedsLayout()
func layoutIfNeeded()
以上两种方法都用于强制视图布局。
尝试使用以下代码来处理更新布局。
func updateFrame() {
let resizedImageSize = imageViewPic.image!.size
let imageViewBounds = imageViewPic.bounds
let newRect = AVMakeRectWithAspectRatioInsideRect(resizedImageSize, imageViewBounds)
imageViewPic.frame = newRect
imageViewPic.layoutIfNeeded()
self.view.layoutIfNeeded()
}
还在ViewController中覆盖以下方法。用于更新自定义约束的updateViewConstraints()
方法。
override func updateViewConstraints() {
super.updateViewConstraints()
self.view.layoutIfNeeded()
self.imageViewPic.layoutIfNeeded()
}
答案 1 :(得分:0)
我能够找到一个非常相似的人的例子。这就是方法。
在故事板中,只对每个UITextField应用3个约束,保留topTextField的顶部约束和bottomTextField的底部约束。
为ViewController添加两个属性,用于顶部和底部约束。
var topConstraint : NSLayoutConstraint!
var bottomConstraint : NSLayoutConstraint!
创建以下辅助方法;
func layoutTextFields() {
//Remove any existing constraints
if topConstraint != nil {
view.removeConstraint(topConstraint)
}
if bottomConstraint != nil {
view.removeConstraint(bottomConstraint)
}
//Get the position of the image inside the imageView
let size = memeImageView.image != nil ? memeImageView.image!.size : memeImageView.frame.size
let frame = AVMakeRectWithAspectRatioInsideRect(size, memeImageView.bounds)
//A margin for the new constrains; 10% of the frame's height
let margin = frame.origin.y + frame.size.height * 0.10
//Create and add the new constraints
topConstraint = NSLayoutConstraint(
item: topTextField,
attribute: .Top,
relatedBy: .Equal,
toItem: memeImageView,
attribute: .Top,
multiplier: 1.0,
constant: margin)
view.addConstraint(topConstraint)
bottomConstraint = NSLayoutConstraint(
item: bottomTextField,
attribute: .Bottom,
relatedBy: .Equal,
toItem: memeImageView,
attribute: .Bottom,
multiplier: 1.0,
constant: -margin)
view.addConstraint(bottomConstraint)
}
调用viewDidLayoutSubviews()
函数
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
layoutTextFields()
}
当UIImageView没有图像时,以及没有图像时,这似乎都能很好地工作。它也适用于旋转设备。
我抓到的两个方面是认为我需要首先在Storyboard中定义所有约束,并且认为我需要使用CGRect
生成的AVMakeRectWithAspectRatioInsideRect
添加视图。 1}}