Как создать UITextField со способностью функционировать как UIButton? - PullRequest
0 голосов
/ 08 мая 2020

У меня проблема с созданием красивого макета с выполнением того, что я хочу. Я хочу задать вопрос (мне не нужна помощь с этим) и 4 варианта ответа ниже. Я создал эти варианты ответов как текстовые поля, потому что это позволяет мне получить красивую границу, которая тонкая и такая, какой я хочу. Но я также хочу, чтобы это нельзя было редактировать, но в то же время можно было нажимать. Я имею в виду, что пользователь не может редактировать ответ, но когда они нажимают на правильный ответ, граница становится зеленой или что-то в этом роде. Я так много искал, но всегда получаю ошибки, и это никогда не работает.

Это пример типа макета, который я хочу .

Я не могу превратить это в кнопку, потому что у нее действительно уродливые и квадратные границы, но я не могу использовать UITextView, потому что я не могу создать @IBAction и изменить определенные атрибуты c при нажатии. Я не могу использовать UITextField, потому что когда я нажимаю текстовое поле, оно ничего не делает. Я не могу отключить «Взаимодействие с пользователем», потому что тогда они не смогут щелкнуть по нему. Как я могу заставить его работать так, чтобы при нажатии он становился похожим на на , но сохранял тот же формат?

(Не беспокойтесь о различиях шрифтов и всем остальном.)

У меня нет кода для показа, потому что я не нашел ничего работающего.

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Вы можете добиться того, чего хотите, с помощью специального класса UIButton.

import UIKit

class CustomButton: UIButton {

    override func awakeFromNib() {
        super.awakeFromNib()

        layer.borderWidth = 1.0
        layer.borderColor = UIColor.systemGray4.cgColor
        layer.cornerRadius = 5.0
        contentEdgeInsets = UIEdgeInsets(top: 0.0, left: 10.0, bottom: 0.0, right: 0.0)
    }
}

Это даст вам кнопку с рамкой и вставкой, которая выглядит так, как вы пытаетесь достичь:

enter image description here

Хороший способ проверить, нажата ли кнопка правильного ответа, - это использовать свойство tag в UIButton. Например, 0 за неправильный ответ, 1 за правильный ответ. Затем вы можете проверить значение тега при нажатии каждой кнопки. (все кнопки подключены к одному IBAction). Если нажата правильная кнопка, вы можете установить зеленый цвет границы и сделать все, что вам нужно, перед повторением цикла.

import UIKit

class ViewController: UIViewController {

    @IBOutlet var answerAButton: CustomButton!
    @IBOutlet var answerBButton: CustomButton!
    @IBOutlet var answerCButton: CustomButton!
    @IBOutlet var answerDButton: CustomButton!

    var answerButtons: [UIButton]!

    override func viewDidLoad() {
        super.viewDidLoad()
        answerButtons = [answerAButton, answerBButton, answerCButton, answerDButton]
        setCorrectAnswer()
    }

    func setCorrectAnswer() {
        answerButtons.forEach {
            // Reset the border on each button
            $0.layer.borderColor = UIColor.systemGray4.cgColor
            // Reset the tag on each button
            $0.tag = 0
        }

        // Set the correct answer button tag
        answerButtons[2].tag = 1
    }

    @IBAction func answerTapped(_ sender: UIButton) {
        if sender.tag == 1 {
            sender.layer.borderColor = UIColor.green.cgColor
        }
    }
}

enter image description here


Ответы на дополнительные вопросы:

1. Куда бы я поместил пользовательскую кнопку?

2. Какой тип файла мне следует создать для этого?

  1. Создайте файл Swift с именем CustomButton.swift (или как вы хотите его назвать).
  2. В Storyboard используйте стандартный UIButton, а в Identity Inspector измените настраиваемый класс, чтобы он соответствовал. Убедитесь, что IBOutlets для ваших кнопок имеет тип CustomButton для вашего IBOutlet соединения. Как показано выше. Вы не увидите эффекты в раскадровке, только во время выполнения.

enter image description here

0 голосов
/ 08 мая 2020

Вы можете использовать обычный вид, где вы можете настроить границу и радиус угла, чтобы он выглядел так, как вы хотите. Поместите этикетку внутрь и снова установите нужный стиль. Чтобы обнаружить касание, вы можете либо поместить на него кнопку (без текста, чтобы он не был виден), либо добавить UITapGestureRecognizer в представление и использовать его для обнаружения касаний.

Вот как вы бы добиться желаемого вида границы в представлении:

view.layer.borderColor = UIColor.lightGray.cgColor
view.layer.borderWidth = 1.0
view.layer.cornerRadius = 5.0

Вот как вы добавили бы распознаватель жестов:

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(gestureRecognized(gesture:)))
view.addGestureRecognizer(tapGesture)

// Somewhere below in code put the method that is called when gesture is recognized
@objc
func gestureRecognized(gesture: UITapGestureRecognizer) {
    // Gesture recognized
}

Вот краткий пример того, как вы должны все настроить:

import UIKit

protocol AnswerViewDelegate: AnyObject {
    func answerViewUserDidTap(sender: AnswerView)
}

class AnswerView: UIView {

    weak var delegate: AnswerViewDelegate?

    private lazy var tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapGestureRecognized(gesture:)))

    var answerId: String?
    var answer: String?

    override func awakeFromNib() {
        super.awakeFromNib()
        layer.borderColor = UIColor.lightGray.cgColor
        layer.borderWidth = 1.0
        layer.cornerRadius = 5.0

        addGestureRecognizer(tapGestureRecognizer)
    }

    @objc private func tapGestureRecognized(gesture: UITapGestureRecognizer) {
        delegate?.answerViewUserDidTap(sender: self)
    }

}

class ViewController: UIViewController {

    @IBOutlet private weak var answerView1: AnswerView!
    @IBOutlet private weak var answerView2: AnswerView!
    @IBOutlet private weak var answerView3: AnswerView!
    @IBOutlet private weak var answerView4: AnswerView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // This is just for demonstration purposes, to keep the code as short as possible
        [answerView1, answerView2, answerView3, answerView4].enumerated().forEach { offset, answerView in
            answerView?.answerId = String(offset)
            answerView?.answer = "Answer number: \(offset)"
            answerView?.delegate = self
        }
    }

}

// MARK: - AnswerViewDelegate

extension ViewController: AnswerViewDelegate {

    func answerViewUserDidTap(sender: AnswerView) {
        print("User tapped answer: \(String(describing: sender.answerId)) with id: \(String(describing: sender.answerId)).")
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...