3lvis/Form

Highly Customized UITextFields, is it possible?

n8stowell82 opened this issue · 6 comments

Hello, first off great work on this project. This project works really well. I have a question about implementing a custom field as a very highly customized UITextField. In my project I have been using this very awesome set of textfields found here: https://github.com/raulriera/TextFieldEffects and specifically this style of textfield: https://github.com/raulriera/TextFieldEffects/blob/master/TextFieldEffects/TextFieldEffects/HoshiTextField.swift

so looking through your "custom field" demo I am noticing that both custom fields are derived off of UITextView. How would I instead use UITextField and from there how could I use one of the customized textFields from above?

Thanks so much for your time and consideration!

Ok, so after rolling up my sleeves and getting to work I got this working...mostly. I will post my code below for review but here are my two main problems right now

  1. How do I retrieve values from the JSON object that should affect this field? i.e. the title of the field?
    a. updateWithField(field: FORMField!) does not seem to be getting called
  2. Do I really need to implement every single delegate callback to do things like validate and update the value?

Thanks again for this tool, very good stuff.

import UIKit

protocol HoshiFormTextFieldDelegate: class {
    func hoshiFormFieldWasUpdated(text: String)
}

class HoshiFormTextField: FORMBaseFieldCell, FORMTextFieldDelegate {
    static let CellIdentifier = "HoshiFormTextFieldIdentifier"

    weak var hoshiFormFieldDelegate: HoshiFormTextFieldDelegate? = nil

    var textView: HoshiTextField = HoshiTextField()

    override init(frame: CGRect) {
        super.init(frame: frame)

        setupTextField()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        self.textView.frame = self.textFieldFrame()
    }

    func textFieldFrame() -> CGRect{
        let marginX = FORMTextFieldCellMarginX
        let marginTop = FORMFieldCellMarginTop
        let marginBottom = FORMFieldCellMarginBottom

        let width = CGRectGetWidth(self.frame) - (marginX * 2)
        let height = CGRectGetHeight(self.frame) - marginTop - marginBottom
        let frame = CGRectMake(marginX, marginTop, width, height)

        return frame
    }

    func setupTextField(){
        textView.placeholder = "Title for field"
        textView.borderActiveColor = UIColor ( red: 0.1137, green: 0.6275, blue: 0.4745, alpha:
            1.0 )
        textView.borderInactiveColor = UIColor ( red: 0.7843, green: 0.7843, blue: 0.7843, alpha:
            1.0 )
        textView.borderErrorColor = UIColor.redColor()

        self.addSubview(self.textView)

    }

    override func updateWithField(field: FORMField!) {

        //This is not getting called!!!


        super.updateWithField(field)
        self.textView.placeholder = field.title
    }

    func validateField(){
        if self.field.validate == FORMValidationResultType.Valid {
            self.textView.hasError = false
        }else {
            self.textView.hasError = true
        }
    }

    func textFormFieldDidBeginEditing(textField: FORMTextField!) {
        print("hoshi field did start editing")
    }

    func textFormFieldDidEndEditing(textField: FORMTextField!) {

        validateField()
    }

    func textFormField(textField: FORMTextField!, didUpdateWithText text: String!) {
        self.field.value = text;
        self.validateField()
    }
}

extension HoshiFormTextField: UITextViewDelegate {
    func textViewDidChange(textView: UITextView) {
        self.hoshiFormFieldDelegate?.hoshiFormFieldWasUpdated(textView.text)
    }
}`
3lvis commented

Hi @n8stowell82,

Support for custom fields right now is very basic, custom fields aren't attached to the same validations than other fields, and don't receive the callbacks by default. I have considered several ways to make this work but is going to take some heavy work and rewrite of core parts of Form. Not that isn't going to make, is just that it will take a while to get it done.

I'll make a task to explain more of the internal infrastructure of Form, in case you want to tackle this problem. I'm sure a lot of Form users will appreciate this.

Coming back to the UITextField with the custom animation, I think is going to be easier for you to just add this animation to the FORMBaseFieldCell.

There are several implementations and just getting the basics working and activating it behind a flag would probably be less work than adding support for custom UITextFields. If the header animations what you like or what is it in general?

http://bradfrost.com/blog/post/float-label-pattern
https://github.com/Skyscanner/SkyFloatingLabelTextField

Thanks @3lvis for the response and the information. I wanted to be clear that the code posted above does work. It renders the textField, with all the animations and everything seems to work well. The things I need or would like to have would be the ability to retrieve data from the JSON object that builds the form. For instance setting the placeholder of the textfield to the "title" object in the json. And of course validation

Some thoughts on implementation. could you achieve these results by subclassing the FORMTextField class to build these custom forms? So my FORMBaseFieldCell could contain a textField of base type FORMField. Would something like that work?

And to answer question about the textField. the ability to do custom animations is what I would really be after. That could possibly be accomplished by extending some of the examples you have posted in the "CustomFields" demo

3lvis commented

Hi Nathan,

I order to be able to have a text field be part of the FORMDataSource, it has to be one of the existing ones, right now there's no support to store the contents of your text field in the FORMDataSource that's why I was saying that might be easier to just include the animation inside Form.

3lvis commented

Hi Nathan,

Were you able to fix this issue?

@3lvis Hi,

I am trying to write a custom field to support multiple selection (like a checkbox), how could I get the "values" fromt the form fields json? I need it to render the selection UI, kindly advise. thank you!