开发者

Disable button until text fields have been entered?

I have several uitextfields within a view and I would like to disable the uibutton until all the fields have something entered into them. What's the best way of doing this? Ideally, I'd like to do some basic validation (make sure all entries are numbers) too.


EDIT

Couldn't get the solutions below to quite work. Below is the version that I got working (cobbled together from Brad, Mike, and various other sources)

Use the UITextFieldDelegate

Create textfields in IB, and attach to the relevant IBOutlets - textField1, textField2 etc

Create and hookup the button to its relevant IBOutlet (submitButton) and IBAction (submitAction) in IB. Uncheck enabled in IB.

Create a validate method in the view controller:

-(IBAction)validateTextFields:(id)sender
    {
        // make sure all fields are have something in them
        if ((textField1.text.length  > 0) && (textField2.text.length > 0)  && (textField3.text.length > 0)) {
            self.submitButton.enabled = YES;
        }
        else {
            self.submitButton.enabled = NO;
        }
    }

Hookup each fields 'Editing Changed' event to the validateTextFields method. (Note: The 'Value Changed' event doesn't appear to work)

Use this delegate method to limit characters (in my case to numbers, and up to one full-stop). This bit is from Erica Sadun btw.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSCharacterSet *cs;
    NSString *filtered;
    // Check for period
    if ([开发者_运维技巧textField.text rangeOfString:@"."].location == NSNotFound)
    {
        cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet];
        filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
        return [string isEqualToString:filtered];
    }
    // Period is in use
    cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
    filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
    return [string isEqualToString:filtered];
}

Voila.


You will want to implement the UITextFieldDelegate Delegate on all of your textfields in a view cOntroller managing your view like so, making sure to validate your textfields after loading your view:

-(void) viewDidLoad {
  textField1.delegate = self;  //Note if these were created in a xib, you can do this in IB
  textField2.delegate = self;
  [self validateTextFields];
}

And Implement the textField:shouldChangeCharatersInRage: method to due the validation everytime the textfileds change:

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
  [self validateTextFields];
  return YES;
}

Finally, do the actual validation and enable or disable your button as needed:

-(void) validateTextFields {
  if ((textField1.text.length > 0) && textField2.text.length > 0)) {
    myUIButton.enabled = YES;
  }
  else {
    myUIButton.enabled = NO;
  }
}


Set yourself to be the delegate of the textfields and handle the textFieldDidEndEditing: method. In this method you can do your validation:

- (void)textFieldDidEndEditing:(UITextField *)textField {
     myButton.enabled = (myTextField1.text.length && myTextField2.length);
}


I did not like Brad's answer, as you are always one character behind. The last text field you enter text into must have at least two characters because of the way shouldChangeCharactersInRange works. Here is a solution I found to be much more helpful:

Swift:

//This line goes in viewDidLoad
field.addTarget(self, action: #selector(self.validateTextFields), forControlEvents: UIControlEvents.EditingChanged)

func validateTextFields() {

        if field.text != "" {
            registerButton.enabled = true

        } else {

            registerButton.enabled = false
        }
}

Objective-C:

//This line goes in viewDidLoad
[myTextField addTarget:self 
                action:@selector(textFieldDidChange)
      forControlEvents:UIControlEventEditingChanged];

- (void)textFieldDidChange
{
    if ([self.myTextField.text isEqualToString:@""]) {
        [self.button setEnabled:NO];
    }
    else {
        [self.button setEnabled:YES];
    }
}

The solution also does not require you to resign the most recent field as first responder, which I find to be useful as the button's state will change whenever your text field's text changes from an empty string to text.


A Swift 3 variant based on Jacob's example.

//
//  ViewController.swift
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var txtTextField: UITextField!
    @IBOutlet weak var btnButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // Ensure that only valid changes to txtTextField enable btnButton
        txtTextField.addTarget(self, action: #selector(self.validateTextField), for: UIControlEvents.editingChanged)
    }

    func validateTextField() {
        let validValue = txtTextField.text!.trimmingCharacters(in: CharacterSet.whitespaces)

        btnButton.isEnabled = validValue == "" ? false : true
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜