如何在捏合顶部添加 UITextfield 以缩放图像

问题描述 投票:0回答:1

尝试在捏合顶部添加 UITextfield 以缩放图像。我能够通过捏合来缩放图像,但添加 UITextField 是我遇到困难的地方。我试图让 UITextField 在放大/缩小图像时保留在图像的特定部分。我以为我已经接近了,但 Xcode 似乎不喜欢我添加到 UITextfield 的约束。谢谢您的帮助。

当前代码:

import UIKit
import Foundation

class ZoomImage: UIViewController, UITextFieldDelegate {
    
    private var textField: UITextField {
        let ut = UITextField()
        ut.backgroundColor = .black
        return ut
    }
    
    // create scrollView
    private let scrollView: UIScrollView = {
        let sv = UIScrollView()
        sv.backgroundColor = .red
        return sv
    }()
    
    // create imageView
    private var imageView: UIImageView = {
        let v = UIImageView()
        v.backgroundColor = .blue
        return v
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }
    
    func setup() {
        // Allows us to have this view be the delegate of the textfield
        self.textField.delegate = self
        // Allows us to have this view be the delegate of the scrollview
        scrollView.delegate = self
        // add Scrollview to view
        self.view.addSubview(scrollView)
        
        // Defining imageView
        let image = UIImage(named: "test.png")!
        imageView = UIImageView(image: image)
        imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image.preferredPresentationSizeForItemProvider)
        imageView.contentMode = .scaleAspectFit
        imageView.addSubview(textField)
        
        //Defining Textfield
        textField.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image.preferredPresentationSizeForItemProvider)
        textField.placeholder = "TEsting"
        
        // add UIImageView to scroll view
        scrollView.addSubview(imageView)
        scrollView.addSubview(textField)
        
        imageView.translatesAutoresizingMaskIntoConstraints = false
        textField.translatesAutoresizingMaskIntoConstraints = false
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        
        // respect safe-area
        let safeG = view.safeAreaLayoutGuide
        
        // Zoom range
        scrollView.minimumZoomScale = 1.0
        scrollView.maximumZoomScale = 10.0
        
        // constraints
        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 0),
            scrollView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: 0),
            scrollView.bottomAnchor.constraint(equalTo: safeG.bottomAnchor, constant: 0),
            scrollView.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 0),
            
            imageView.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor, constant: 0),
            imageView.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor, constant: 0),
            imageView.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor, constant: 0),
            imageView.topAnchor.constraint(equalTo: self.scrollView.topAnchor, constant: 0),
            
            imageView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            imageView.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
            
            textField.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0),
            textField.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0),
            textField.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0),
            textField.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0)
            
        ])
    }
}

extension ZoomImage:  UIScrollViewDelegate {
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return imageView
    }
}
ios swift uikit
1个回答
1
投票

首先我们需要修复代码中的一些严重错误。

  1. 更改

    textField
    ,使其只创建一个实例。每次引用
    UITextField
    属性时,您的代码都会创建一个新的
    textField
    实例。使其像其他视图属性一样:

    private let textField: UITextField = {
        let ut = UITextField()
        ut.backgroundColor = .gray
        return ut
    }()
    
  2. 不要尝试将文本字段添加到两个不同的超级视图。删除该行:

    imageView.addSubview(textField)
    
  3. 不要创建新的

    UIImageView
    实例。更换线路:

    imageView = UIImageView(image: image)
    

    与:

    imageView.image = image
    
  4. 您正在使用约束。不必费心设置视图框架。删除设置任何视图的

    frame
    属性的所有行。

下一步是更新滚动视图约束以利用

frameLayoutGuide
contentLayoutGuide
。然后将文本字段锚定到内容的顶部/尾部角。

NSLayoutConstraint.activate([
    scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 0),
    scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: 0),
    scrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: safeG.bottomAnchor, constant: 0),
    scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 0),

    imageView.leadingAnchor.constraint(equalTo: self.scrollView.contentLayoutGuide.leadingAnchor, constant: 0),
    imageView.trailingAnchor.constraint(equalTo: self.scrollView.contentLayoutGuide.trailingAnchor, constant: 0),
    imageView.bottomAnchor.constraint(equalTo: self.scrollView.contentLayoutGuide.bottomAnchor, constant: 0),
    imageView.topAnchor.constraint(equalTo: self.scrollView.contentLayoutGuide.topAnchor, constant: 0),

    imageView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
    imageView.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor),

    textField.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: 0),
    textField.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: 0),
])

完成所有这些后,您最初可以看到完整的图像,文本字段位于右上角。但当您缩放图像时,文本字段仍位于顶部,但不会按预期移动到右侧。如果一直向左滚动,则文本字段会出现在屏幕的右边缘,但不会出现在图像视图的右边缘。

可以通过在滚动视图的缩放级别发生变化时更新文本字段的约束来解决此问题。

添加以下附加滚动视图委托方法:

func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
    textField.removeFromSuperview()
    scrollView.addSubview(textField)
    let xC = NSLayoutConstraint(item: self.textField, attribute: .trailing, relatedBy: .equal, toItem: scrollView.contentLayoutGuide, attribute: .trailing, multiplier: scale, constant: 0)
    let yC = NSLayoutConstraint(item: self.textField, attribute: .top, relatedBy: .equal, toItem: scrollView.contentLayoutGuide, attribute: .top, multiplier: scale, constant: 0)
    NSLayoutConstraint.activate([
        xC,
        yC,
    ])
}

这可确保文本字段在每次缩放(放大或缩小)结束时正确定位。


对我来说这似乎是一个 UIKit bug。当内容缩放时,

contentLayoutGuide
似乎没有更新。无需手动将
scale
应用于约束的
multiplier


我尝试了另一种方法,将文本字段直接添加到图像视图并设置文本字段相对于图像视图的约束。除了文本字段的大小也随着图像视图的变化而变化之外,无需任何额外的代码即可工作。由于目标是保持文本字段的原始大小,因此这是行不通的。对文本字段应用“缩放”变换可以很容易地使其达到所需的大小,但这会导致其位置发生一些变化。我放弃了尝试在对视图应用各种变换时使约束起作用。

© www.soinside.com 2019 - 2024. All rights reserved.