iOS 8中具有动态高度的自定义inputView

时间:2014-07-15 10:37:25

标签: ios ios8

我在UITextFields的自定义inputView上遇到了一些问题。根据用户需要在UITextField中输入的文本,inputView仅显示所需的字母。这意味着对于短文本,只有一行字母的inputView就足够了,较长的文本可能需要2行甚至3行,因此inputView的高度是变量。

由于我期望性能更好,因此每个textField只使用一个inputView实例。这样创建必须只发生一次,这使得有时需要直接访问inputView更容易。 inputView在- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField中设置,设置其所需的高度并将显示。

效果很好,但不适用于iOS8。有一些包含inputView的系统视图在更改时不会更新其框架以匹配inputView的边界(第一次工作)。

我知道可以通过每个textField使用我的inputView的一个实例来修复。但是我问是否有推荐/更好的方法来调整框架或将其更改报告给包含视图。也许这是一个iOS8错误,可以在发布之前修复?

以下是重现问题的示例代码:

CustomInputView

@implementation CustomInputView

+ (CustomInputView*)sharedInputView{
    static CustomInputView *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[CustomInputView alloc] init];
    });
    return sharedInstance;
}

- (id)init
{
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor greenColor];
    }
    return self;
}

- (void)setupForTextField:(UITextField*)textField{
    CGFloat height;

    if(textField.tag == 1){
        height = 100;
    }else height = 50;

    self.frame = CGRectMake(0, 0, 320, height);
}
@end

TestViewController代码

- (void)viewDidLoad
{
    [super viewDidLoad];

    UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(15, 50, 290, 30)];
    tf.text = @"bigKeyboard";
    tf.inputView = [CustomInputView sharedInputView];
    tf.layer.borderWidth = 1;
    tf.layer.borderColor = [UIColor lightGrayColor].CGColor;
    tf.delegate = self;
    tf.tag = 1;
    [self.view addSubview:tf];

    tf = [[UITextField alloc] initWithFrame:CGRectMake(15, 100, 290, 30)];
    tf.text = @"smallKeyboard";
    tf.inputView = [CustomInputView sharedInputView];
    tf.layer.borderWidth = 1;
    tf.layer.borderColor = [UIColor lightGrayColor].CGColor;
    tf.delegate = self;
    tf.tag = 2;
    [self.view addSubview:tf];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"dismissKeyboard" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(endEditing) forControlEvents:UIControlEventTouchUpInside];
    button.frame = CGRectMake(15, 150, 290, 30);
    [self.view addSubview:button];
}

- (void)endEditing{
    [self.view endEditing:YES];
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    [[CustomInputView sharedInputView] setupForTextField:textField];
    return YES;
}

2 个答案:

答案 0 :(得分:17)

我在将自定义键盘从iOS 8调整到iOS 10时遇到了类似的问题。我认为正确的解决方案是让输入视图提供正确的intrinsicContentSize并在需要时更改(和无效!)该值改变视图的高度。示例代码:

class CustomInputView: UIInputView {
    var intrinsicHeight: CGFloat = 200 {
        didSet {
            self.invalidateIntrinsicContentSize()
        }
    }

    init() {
        super.init(frame: CGRect(), inputViewStyle: .keyboard)
        self.translatesAutoresizingMaskIntoConstraints = false
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.translatesAutoresizingMaskIntoConstraints = false
    }

    override var intrinsicContentSize: CGSize {
        return CGSize(width: UIViewNoIntrinsicMetric, height: self.intrinsicHeight)
    }
}

class ViewController: UIViewController {
    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.becomeFirstResponder()

        let inputView = CustomInputView()
        // To make the view's size more clear.
        inputView.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0.5, alpha: 1)
        textView.inputView = inputView

        // To demonstrate a change to the view's intrinsic height.
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(2)) {
            inputView.intrinsicHeight = 400
        }
    }
}

另见https://stackoverflow.com/a/40359382/153354

答案 1 :(得分:0)

我发现对于调整iOS 9及更高版本上的inputView大小至关重要的另一件事是将allowSelfSizing设置为true:

if #available(iOS 9.0, *) {
    self.inputView?.allowsSelfSizing = true
}