5

Is there any option in swift to make new UIKeyboardType with only HEX(0-9,A,B,C,D,E,F) value using extension or any other way ? I want keyboard that has only hex character enable on it, user can see clearly that he can only enter hex character, or only hex character is visible on keyboard

Varun Naharia
  • 5,318
  • 10
  • 50
  • 84

2 Answers2

4

This following code creates a hexadecimal keyboard and passes it to inputView, as suggested by Saurabh Prajapati.

The keyboard is designed like this:

enter image description here

The design was based on a layout by David Mulder https://ux.stackexchange.com/a/58605/128044

The class HexadecimalKeyboard creates the keyboard.

protocol RemoveKeyboardDelegate: class {
    func removeKeyboard()
}

class HexButton: UIButton {
    var hexCharacter: String = ""
}

class HexadecimalKeyboard: UIView {
    weak var target   : UIKeyInput?
    weak var delegate : RemoveKeyboardDelegate?
    
    var hexadecimalButtons: [HexButton] = ["0","7","8","9","4","5","6","1","2","3","A","B","C","D","E","F"].map {
        let button = HexButton(type: .system)
        button.hexCharacter = $0
        button.setTitle("\($0)", for: .normal)
        button.backgroundColor = UIColor.secondarySystemGroupedBackground
        button.addTarget(self, action: #selector(didTapHexButton(_:)), for: .touchUpInside)
        return button
    }
    
    var deleteButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("⌫", for: .normal)
        button.backgroundColor = UIColor.systemGray4
        button.accessibilityLabel = "Delete"
        button.addTarget(self, action: #selector(didTapDeleteButton(_:)), for: .touchUpInside)
        return button
    }()
    
    var okButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("OK", for: .normal)
        button.backgroundColor = UIColor.systemGray4
        button.accessibilityLabel = "OK"
        button.addTarget(self, action: #selector(didTapOKButton(_:)), for: .touchUpInside)
        return button
    }()
    
    var mainStack: UIStackView = {
        let stackView = UIStackView()
        stackView.distribution = .fillEqually
        stackView.spacing      = 10
        stackView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        stackView.isLayoutMarginsRelativeArrangement = true
        stackView.layoutMargins = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        return stackView
    }()
    
    init(target: UIKeyInput) {
        self.target = target
        super.init(frame: .zero)
        configure()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


// MARK: - Actions

extension HexadecimalKeyboard {
    @objc func didTapHexButton(_ sender: HexButton) {
        target?.insertText("\(sender.hexCharacter)")
    }
    
    @objc func didTapDeleteButton(_ sender: HexButton) {
        target?.deleteBackward()
    }
    
    @objc func didTapOKButton(_ sender: HexButton) {
        delegate?.removeKeyboard()
    }
}


// MARK: - Private initial configuration methods

private extension HexadecimalKeyboard {
    func configure() {
        self.backgroundColor = .systemGroupedBackground
        autoresizingMask     = [.flexibleWidth, .flexibleHeight]
        buildKeyboard()
    }
    
    func buildKeyboard() {
        //MARK: - Add main stackview to keyboard
        mainStack.frame = bounds
        addSubview(mainStack)
        
        //MARK: - Create stackviews
        let panel1         = createStackView(axis: .vertical)
        let panel2         = createStackView(axis: .vertical)
        let panel2Group    = createStackView(axis: .vertical)
        let panel2Controls = createStackView(axis: .horizontal, distribution : .fillProportionally)
 
        
        //MARK: - Create multiple stackviews for numbers
        for row in 0 ..< 3 {
            let panel1Numbers = createStackView(axis: .horizontal)
            panel1.addArrangedSubview(panel1Numbers)
            
            for column in 0 ..< 3 {
                panel1Numbers.addArrangedSubview(hexadecimalButtons[row * 3 + column + 1])
            }
        }
        
        //MARK: - Create multiple stackviews for letters
        for row in 0 ..< 2 {
            let panel2Letters = createStackView(axis: .horizontal)
            panel2Group.addArrangedSubview(panel2Letters)
            
            for column in 0 ..< 3 {
                panel2Letters.addArrangedSubview(hexadecimalButtons[9 + row * 3 + column + 1])
            }
        }
        
        //MARK: - Nest stackviews
        mainStack.addArrangedSubview(panel1)
        panel1.addArrangedSubview(hexadecimalButtons[0])
        mainStack.addArrangedSubview(panel2)
        panel2.addArrangedSubview(panel2Group)
        panel2.addArrangedSubview(panel2Controls)
        panel2Controls.addArrangedSubview(deleteButton)
        panel2Controls.addArrangedSubview(okButton)
        
        //MARK: - Constraint - sets okButton width to two times the width of the deleteButton plus 10 points for the space
        panel2Controls.addConstraint(NSLayoutConstraint(
                                        item       : okButton,
                                        attribute  : .width,
                                        relatedBy  : .equal,
                                        toItem     : deleteButton,
                                        attribute  : .width,
                                        multiplier : 2,
                                        constant   : 10))
    }
    
    func createStackView(axis: NSLayoutConstraint.Axis, distribution: UIStackView.Distribution = .fillEqually) -> UIStackView {
        let stackView = UIStackView()
        stackView.axis         = axis
        stackView.distribution = distribution
        stackView.spacing      = 10
        return stackView
    }
}

The code was derived from the decimal keyboard example provided by Rob https://stackoverflow.com/a/57275689/1816667

Then following is an example of how to use the keyboard. In the example, two textfields are set up with the hexadecimal keyboard:

class ViewController: UIViewController {

    @IBOutlet var hexField: [UITextField]!
    
    override func viewDidLoad() {
        hexField[0].inputView  = HexadecimalKeyboard(target: hexField[0])
        hexField[1].inputView  = HexadecimalKeyboard(target: hexField[1])
    }
    
    @IBAction func clickTextField(_ sender: UITextField) {
        sender.reloadInputViews()
        sender.inputView  = HexadecimalKeyboard(target: sender)
        
        let hexadecimalKeyboard  = HexadecimalKeyboard(target: sender)
                sender.inputView = hexadecimalKeyboard
                hexadecimalKeyboard.delegate = self
    }
} // end of View Controller

extension ViewController: RemoveKeyboardDelegate {
    func removeKeyboard() {
        _ = hexField.map { $0.inputView?.removeFromSuperview() }
    }
}

An example Xcode 12 project using Swift 5 is provided here: https://github.com/PepperoniJoe/HexadecimalKeyboard

enter image description here

Marcy
  • 4,611
  • 2
  • 34
  • 52
0

First case, there are keyboard type given as mentioned below we can set the textField.keyboardType property and use it.

public enum UIKeyboardType : Int {    
    case `default` // Default type for the current input method.    
    case asciiCapable // Displays a keyboard which can enter ASCII characters    
    case numbersAndPunctuation // Numbers and assorted punctuation.    
    case URL // A type optimized for URL entry (shows . / .com prominently).    
    case numberPad // A number pad with locale-appropriate digits (0-9, ۰-۹, ०-९, etc.). Suitable for PIN entry.    
    case phonePad // A phone pad (1-9, *, 0, #, with letters under the numbers).    
    case namePhonePad // A type optimized for entering a person's name or phone number.
    case emailAddress // A type optimized for multiple email address entry (shows space @ . prominently).
    @available(iOS 4.1, *)
    case decimalPad // A number pad with a decimal point.
    @available(iOS 5.0, *)
    case twitter // A type optimized for twitter text entry (easy access to @ #)
    @available(iOS 7.0, *)
    case webSearch // A default keyboard type with URL-oriented addition (shows space . prominently).
    @available(iOS 10.0, *)
    case asciiCapableNumberPad // A number pad (0-9) that will always be ASCII digits.
    public static var alphabet: UIKeyboardType { get } // Deprecated
}

The Second case is, you want to restrict the user not to enter unwanted values (like you only need 1-9 and a-z) in that case you can use func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool delegate and validate the user input and input character is according to your requirement return true else return false.

And the Third case if it is optional to use given keyboard as the user than better create a custom keyboard, see this Apple developer reference. and nice tutorial that I have also used to learn.

Buntylm
  • 7,345
  • 1
  • 31
  • 51
  • Yes I know that but I just want to know that is it possible to extend existing keyboard type ? – Varun Naharia Oct 05 '17 at 06:53
  • There are also ways to create custom keyboards but it will be really good if you explain your requirement clearly. – Buntylm Oct 05 '17 at 06:59
  • I want keyboard that has only hex character enable on it, user can see clearly that he can only enter hex character, or only hex character is visible on keyboard – Varun Naharia Oct 05 '17 at 07:02
  • Correct but as a user can I switch it back to normal keyboard? or forcefully I need to use only hex characters? – Buntylm Oct 05 '17 at 07:04