Сложность удаления границы UITextView при сохранении отступа - PullRequest
0 голосов
/ 30 апреля 2019

Я пишу приложение для iOS, где пользователь может добавлять текстовые поля, а затем перетаскивать их по экрану, чтобы изменить их расположение, стиль макета, что-то вроде Keynote.

В настоящее время я добавляю пользователя-добавил UITextFields в коллекцию @IBOutlet и по умолчанию .borderStyle = .oundedRect, чтобы получить слабую границу вокруг выделенного текста, указывая, что поле выбрано.При вызове textFieldDidBeginEditing любой стиль UITextField будет установлен в стиль грани .oundedRect, а при вызове textFieldDidEndEditing переключиться на textField.borderStyle = .none.

Кажется, что все работает с одной проблемой: при переключении стиля границы на .none текстовое поле теряет отступ, который был вокруг границы, смещая текст наружу и помещая его в то место, где пользователь не планировал (Графика добавляет красный цвет фона, просто чтобы показать смещение, но я в конечном итоге позволю пользователю устанавливать цвета фона, так что просто сместить UITextField не вариант).

enter image description here

Я также попытался адаптировать ответ по адресу: Создать пробел в начале UITextField , установив отсутствие заполнениявставка для TextView, когда это .oundedRect, но добавление отступов, когда .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()
    }
}

1 Ответ

0 голосов
/ 01 мая 2019

Мне удалось обойти эту проблему, создав подкласс 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 () для создания текстового поля с соответствующей высотой. Другие размеры не будут правильными, потому что у меня нет ничего в текстовом представлении, но я извлекаю .height и повторно использую это с моими исходными параметрами инициализации.

newField.sizeToFit()
let newFieldHeight = newField.frame.height
newFieldRect = CGRect(x: 0, y: 0, width: 320, height: newFieldHeight)
newField.frame = newFieldRect

Здесь надеемся, что это поможет сэкономить время.

...