数据输入自定义视图的 Swift 示例(自定义应用内键盘) [英] A Swift example of Custom Views for Data Input (custom in-app keyboard)

查看:23
本文介绍了数据输入自定义视图的 Swift 示例(自定义应用内键盘)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标

我想制作一个仅在我的应用中使用的自定义键盘,而不是需要安装的系统键盘.

我读过和尝试过的

文档

  • 或者,如果您也需要小数点分隔符,您可以:

    textField.inputView = NumericKeyboard(target: textField, useDecimalSeparator: true)

    以上内容相当原始,但它说明了这个想法:让您拥有自己的输入视图并使用 UIKeyInput 协议将键盘输入传达给控件.

    另外请注意使用 accessibilityTraits 来获得正确的Spoken Content"»Speak Screen"行为.如果您的按钮使用图像,请确保也设置 accessibilityLabel.

    Goal

    I want to make a custom keyboard that is only used within my app, not a system keyboard that needs to be installed.

    What I have read and tried

    Documentation

    The first article above states:

    Make sure a custom, systemwide keyboard is indeed what you want to develop. To provide a fully custom keyboard for just your app or to supplement the system keyboard with custom keys in just your app, the iOS SDK provides other, better options. Read about custom input views and input accessory views in Custom Views for Data Input in Text Programming Guide for iOS.

    That is what led me to the second article above. However, that article did not have enough detail to get me started.

    Tutorials

    I was able to get a working keyboard from the second tutorial in the list above. However, I couldn't find any tutorials that showed how to make an in app only keyboard as described in the Custom Views for Data Input documentation.

    Stack Overflow

    I also asked (and answered) these questions on my way to answering the current question.

    Question

    Does anyone have a minimal example (with even one button) of an in app custom keyboard? I am not looking for a whole tutorial, just a proof of concept that I can expand on myself.

    解决方案

    The key is to use the existing UIKeyInput protocol, to which UITextField already conforms. Then your keyboard view need only to send insertText() and deleteBackward() to the control.

    The following example creates a custom numeric keyboard:

    class DigitButton: UIButton {
        var digit: Int = 0
    }
    
    class NumericKeyboard: UIView {
        weak var target: UIKeyInput?
        var useDecimalSeparator: Bool
    
        var numericButtons: [DigitButton] = (0...9).map {
            let button = DigitButton(type: .system)
            button.digit = $0
            button.setTitle("($0)", for: .normal)
            button.titleLabel?.font = .preferredFont(forTextStyle: .largeTitle)
            button.setTitleColor(.black, for: .normal)
            button.layer.borderWidth = 0.5
            button.layer.borderColor = UIColor.darkGray.cgColor
            button.accessibilityTraits = [.keyboardKey]
            button.addTarget(self, action: #selector(didTapDigitButton(_:)), for: .touchUpInside)
            return button
        }
    
        var deleteButton: UIButton = {
            let button = UIButton(type: .system)
            button.setTitle("⌫", for: .normal)
            button.titleLabel?.font = .preferredFont(forTextStyle: .largeTitle)
            button.setTitleColor(.black, for: .normal)
            button.layer.borderWidth = 0.5
            button.layer.borderColor = UIColor.darkGray.cgColor
            button.accessibilityTraits = [.keyboardKey]
            button.accessibilityLabel = "Delete"
            button.addTarget(self, action: #selector(didTapDeleteButton(_:)), for: .touchUpInside)
            return button
        }()
    
        lazy var decimalButton: UIButton = {
            let button = UIButton(type: .system)
            let decimalSeparator = Locale.current.decimalSeparator ?? "."
            button.setTitle(decimalSeparator, for: .normal)
            button.titleLabel?.font = .preferredFont(forTextStyle: .largeTitle)
            button.setTitleColor(.black, for: .normal)
            button.layer.borderWidth = 0.5
            button.layer.borderColor = UIColor.darkGray.cgColor
            button.accessibilityTraits = [.keyboardKey]
            button.accessibilityLabel = decimalSeparator
            button.addTarget(self, action: #selector(didTapDecimalButton(_:)), for: .touchUpInside)
            return button
        }()
    
        init(target: UIKeyInput, useDecimalSeparator: Bool = false) {
            self.target = target
            self.useDecimalSeparator = useDecimalSeparator
            super.init(frame: .zero)
            configure()
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    // MARK: - Actions
    
    extension NumericKeyboard {
        @objc func didTapDigitButton(_ sender: DigitButton) {
            target?.insertText("(sender.digit)")
        }
    
        @objc func didTapDecimalButton(_ sender: DigitButton) {
            target?.insertText(Locale.current.decimalSeparator ?? ".")
        }
    
        @objc func didTapDeleteButton(_ sender: DigitButton) {
            target?.deleteBackward()
        }
    }
    
    // MARK: - Private initial configuration methods
    
    private extension NumericKeyboard {
        func configure() {
            autoresizingMask = [.flexibleWidth, .flexibleHeight]
            addButtons()
        }
    
        func addButtons() {
            let stackView = createStackView(axis: .vertical)
            stackView.frame = bounds
            stackView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            addSubview(stackView)
    
            for row in 0 ..< 3 {
                let subStackView = createStackView(axis: .horizontal)
                stackView.addArrangedSubview(subStackView)
    
                for column in 0 ..< 3 {
                    subStackView.addArrangedSubview(numericButtons[row * 3 + column + 1])
                }
            }
    
            let subStackView = createStackView(axis: .horizontal)
            stackView.addArrangedSubview(subStackView)
    
            if useDecimalSeparator {
                subStackView.addArrangedSubview(decimalButton)
            } else {
                let blank = UIView()
                blank.layer.borderWidth = 0.5
                blank.layer.borderColor = UIColor.darkGray.cgColor
                subStackView.addArrangedSubview(blank)
            }
    
            subStackView.addArrangedSubview(numericButtons[0])
            subStackView.addArrangedSubview(deleteButton)
        }
    
        func createStackView(axis: NSLayoutConstraint.Axis) -> UIStackView {
            let stackView = UIStackView()
            stackView.axis = axis
            stackView.alignment = .fill
            stackView.distribution = .fillEqually
            return stackView
        }
    }
    

    Then you can:

    textField.inputView = NumericKeyboard(target: textField)
    

    That yields:

    Or, if you want a decimal separator, too, you can:

    textField.inputView = NumericKeyboard(target: textField, useDecimalSeparator: true)
    

    The above is fairly primitive, but it illustrates the idea: Make you own input view and use the UIKeyInput protocol to communicate keyboard input to the control.

    Also please note the use of accessibilityTraits to get the correct "Spoken Content" » "Speak Screen" behavior. And if you use images for your buttons, make sure to set accessibilityLabel, too.

    这篇关于数据输入自定义视图的 Swift 示例(自定义应用内键盘)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆