我正在编写一个iOS应用程序,用户可以在其中添加文本字段,然后在屏幕上拖动它们以重新定位它们,布局样式,有点像Keynote。
我目前正在将用户添加的UITextFields附加到@IBOutlet集合并默认为.borderStyle = .roundedRect以获得所选文本周围的微弱边框,表示该字段已被选中。调用textFieldDidBeginEditing时,任何UITextField都将设置为.roundedRect边框样式,并在调用textFieldDidEndEditing时切换到textField.borderStyle = .none。
一切似乎都有一个问题:当将边框样式切换为.none时,文本字段会丢失边框周围的缩进,向外移动文本并将其放在用户不想要的位置(图形会添加背景颜色为红色) ,只是为了显示转变,但我最终会允许用户设置背景颜色,所以只是移动UITextField不是一个选项)。
我也试过调整答案:Create space at the beginning of a UITextField为TextView设置一个无填充插入,当它是.roundedRect时,但是当.borderStyle是.none时添加填充。这似乎没有效果。
其他答案建议设置textField.layer.borderColor = UIColor.clear.cgColor或textField.layer.borderWidth = 0.0但这些似乎没有任何影响,要么
我最终将允许用户更改每个TextField的字体和大小,所以我希望任何缩进都是一致的,无论UITextField是否被选中,无论字体选择如何。
代码如下。如果我错过了一个更好的解决方案,建议是最受欢迎的,并且让我采用新的方法。
谢谢!约翰
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var screenView: UIView! // a 320 x 240 view
@IBOutlet var fieldCollection: [UITextField]! // Not connected, fields created programmatically
// below are used in .inset(by:) but seems to have no effect
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
let noPadding = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
override func viewDidLoad() {
super.viewDidLoad()
// hide keyboard if we tap outside of a field
let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:)))
tap.cancelsTouchesInView = false
self.view.addGestureRecognizer(tap)
createNewField()
}
// Select / deselect text fields
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.borderStyle = .roundedRect
// textField.bounds.inset(by: noPadding) // effect is the same if left out
}
func textFieldDidEndEditing(_ textField: UITextField) {
textField.borderStyle = .none
// textField.bounds.inset(by: padding) // effect is the same if left out
}
// UITextField created & added to fieldCollection
func createNewField() {
let newFieldRect = CGRect(x: 0, y: 0, width: 320, height: 30)
let newField = UITextField(frame: newFieldRect)
newField.borderStyle = .roundedRect
newField.isUserInteractionEnabled = true
newField.addGestureRecognizer(addGestureToField())
screenView.addSubview(newField)
if fieldCollection == nil {
fieldCollection = [newField]
} else {
fieldCollection.append(newField)
}
newField.delegate = self
newField.becomeFirstResponder()
}
func addGestureToField() -> UIPanGestureRecognizer {
var panGesture = UIPanGestureRecognizer()
panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))
return panGesture
}
// event handler when a field(view) is dragged
@objc func draggedView(_ sender:UIPanGestureRecognizer){
sender.view!.becomeFirstResponder()
let selectedView = sender.view as! UITextField
selectedView.bringSubviewToFront(selectedView)
let translation = sender.translation(in: screenView)
selectedView.center = CGPoint(x: selectedView.center.x + translation.x, y: selectedView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: screenView)
}
@IBAction func addFieldPressed(_ sender: UIButton) {
createNewField()
}
}
我能够通过子类化UITextField来解决这个问题:
class PaddedTextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
let noPadding = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
if self.borderStyle == .none {
let content = bounds.inset(by: padding)
return content
} else {
return bounds.inset(by: noPadding)
}
}
}
然后我将newField对象创建从使用UITextField更改为:let newField = PaddedTextField(frame:newFieldRect)
还有一个变化。需要更适当地计算高度。由于我的所有文本字段都可以从封闭的超级视图的全长开始(320个点),因此我修改了原始的newFieldRect,使用.sizeToFit()来创建具有适当高度的文本框。其他维度不正确b / c我在文本视图中没有任何内容,但我提取.height并将其与原始initliazation参数一起使用。
newField.sizeToFit()
let newFieldHeight = newField.frame.height
newFieldRect = CGRect(x: 0, y: 0, width: 320, height: newFieldHeight)
newField.frame = newFieldRect
这里希望它有助于节省时间。