正在try 将UITextfield添加到Pinch的顶部以zoom 图像.我能够让按键在图像上放大,但添加UITextfield是我被卡住的地方.我正在try 让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
    }
}

推荐答案

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

  1. 更改textField,使其仅创建一个实例.每次引用textField属性时,您的代码都会创建一个新的UITextField实例.使其与其他视图属性一样:

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

    imageView.addSubview(textField)
    
  3. 不要创建新的UIImageView实例.替换该行:

    imageView = UIImageView(image: image)
    

    有:

    imageView.image = image
    
  4. 您正在使用约束.不必费心设置图幅.删除设置任何视图的frame属性的所有行.

接下来是更新滚动视图约束,以使用frameLayoutGuidecontentLayoutGuide.然后将文本字段锚定到内容的顶部/尾部角落.

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),
])

所有这些都准备就绪后,您最初可以看到完整的图像,文本字段位于右上角.但是,当您zoom 图像时,文本字段保持在顶部,但不会像预期的那样向右移动.如果一直向左滚动,则文本字段将显示在屏幕的右边缘,而不是图像视图的右边缘.

这个问题可以通过在滚动视图的zoom 级别更改时更新文本字段的约束来解决.

添加以下额外的滚动视图委托方法:

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,
    ])
}

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


这对我来说似乎是一个UIKit错误.contentLayoutGuide似乎没有随着内容的zoom 而更新.不需要手动将scale应用于约束multiplier.


我try 了另一种方法,将文本字段直接添加到图像视图中,并设置文本字段相对于图像视图的约束.除了文本字段的大小也随着图像视图而改变之外,这在没有任何额外代码的情况下工作.由于目标是保持文本字段的原始大小,所以这是行不通的.对文本字段应用"scale"转换可以很容易地使其达到所需的大小,但这会导致其位置发生一点变化.我放弃了在对视图应用各种转换时让约束工作的try .

Ios相关问答推荐

ITMS—91053:Flutter Project中缺少API声明

Xcode版本15.2上未显示iOS 16.4的模拟器

CIKernel的Metal Shader裁剪问题

安装新版本 XCode 15.0 后无法运行应用程序 XCode

当应用程序被杀死时是否还能获取位置?

从包含 5 个以上项目的自定义选项卡栏的导航视图中删除更多按钮

更改订单时如何保存商品的位置?

SwiftUI 图表 BarMark 将注释对齐到图表顶部

SwiftUI:如何为 ScrollView 制作可拉伸(灵活)的粘性标题?

在 Swift 中映射 MySQL 数据

.onChange(of: ) 一次用于多个 @State 属性?

如何在 Swift 中从另一个视图控制器将元素附加到数组中

在 UICollectionView 上从右到左对齐

无法验证客户端 3000

没有 Mac 的 Xamarin Visual Studio IOS 开发?

UITextView 从文本的底部或中间开始

aps-environment 始终在发展

如何使用完成按钮制作 UIPickerView?

AFNetworking 发布请求

iOS 7 应用程序图标、启动图像和命名约定,同时保留 iOS 6 图标