问题描述
我在xib上有一个UIView
,当我在viewDidLoad
上检查它的框架时,它说:
- some : <UIView: 0x7fcc3948b8a0; frame = (56.3333 122; 262.333 262.333); clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x600003a62060>>
在调用layoutIfNeeded()
之后,紧接在上一条日志之后,它显示:
- some : <UIView: 0x7fcc3948b8a0; frame = (56.5 121.917; 262 262.5); clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x600003a62060>>
在viewDidLayoutSubviews()
上,框架为:
- some : <UIView: 0x7fcc3948b8a0; frame = (62 122; 290 289.5); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600003477420>; layer = <CALayer: 0x600003a62060>>
为什么对我很重要?因为我在该视图内设置了UIScrollView
,并且在UIImage
内设置了具有缩放功能的UIScrollView
,这使图像正确的缩放框断裂。
我该如何解决?
解决方法
这是一个非常简单的示例,可能会对您有所帮助。
我有一个1200 x 1200
图像,网格线为100像素。绿色矩形位于600,200
,像素为300 x 400
。那将是我的目标“缩放到”矩形。
当然,我的滚动视图将没有确切的3:4
比率,因此绿色矩形将在缩放时最终在滚动视图的中心。
此处为iPhone 11 Pro Max。我使用的是导航控制器,因此您会在顶部看到导航栏...视图背景为白色...滚动视图被限制在视图的安全区域,每侧各有8点:
以下是生成该代码的代码:
class ScrollTestViewController : UIViewController,UIScrollViewDelegate {
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .cyan
return v
}()
let zoomImageView: UIImageView = {
let v = UIImageView()
v.translatesAutoresizingMaskIntoConstraints = false
v.contentMode = .scaleToFill
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
guard let img = UIImage(named: "img1200x1200") else {
fatalError("Could not load image!!!")
}
print(img.size)
zoomImageView.image = img
view.backgroundColor = .white
// add the scroll view
self.view.addSubview(scrollView)
// add contentView to scroll view
scrollView.addSubview(zoomImageView)
// respect safe-area
let g = view.safeAreaLayoutGuide
// we're going to constrain the zoomImageView to the scroll view's content layout guide
let scg = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
// constrain scrollView Top / Leading / Trailing / Bottom to view (safe-area)
// with 8-pts on each side
scrollView.topAnchor.constraint(equalTo: g.topAnchor,constant: 8.0),scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor,scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor,constant: -8.0),scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor,// constrain zoomImageView Top / Leading / Trailing / Bottom to scroll view's Content Layout Guide
zoomImageView.topAnchor.constraint(equalTo: scg.topAnchor,constant: 0.0),zoomImageView.leadingAnchor.constraint(equalTo: scg.leadingAnchor,zoomImageView.trailingAnchor.constraint(equalTo: scg.trailingAnchor,zoomImageView.bottomAnchor.constraint(equalTo: scg.bottomAnchor,// constrain zoomImageView's width and height to the width and height of the image
zoomImageView.widthAnchor.constraint(equalToConstant: img.size.width),zoomImageView.heightAnchor.constraint(equalToConstant: img.size.height),])
scrollView.minimumZoomScale = 0.25
scrollView.maximumZoomScale = 10.0
scrollView.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// we need to set the "zoom to" rect *after* auto-layout
// has finished everything else
let r = CGRect(x: 600,y: 200,width: 300,height: 400)
scrollView.zoom(to: r,animated: false)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return zoomImageView
}
}