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

Posted

技术标签:

【中文标题】iOS 8中具有动态高度的自定义inputView【英文标题】:Custom inputView with dynamic height in iOS 8 【发布时间】:2014-07-15 10:37:24 【问题描述】:

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

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

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

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

这里有一些重现问题的示例代码:

自定义输入视图

@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;

【问题讨论】:

你有没有找到调整 inputView 大小的解决方案?我需要 iPad 的固定 inputView 高度。 如果您需要固定高度,它应该可以工作 - inputView 将保持在您创建时指定的高度。如果您以后需要更改高度,我仍然不知道解决方案。我采取了为每个 textField 创建一个 inputView 的解决方法,这对我的情况来说没问题... 【参考方案1】:

我在将自定义键盘从 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://***.com/a/40359382/153354。

【讨论】:

【参考方案2】:

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

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

【讨论】:

这对我有用。不要忘记您的视图必须是UIInputView 的子类。

以上是关于iOS 8中具有动态高度的自定义inputView的主要内容,如果未能解决你的问题,请参考以下文章

具有自动布局的自定义单元格的动态高度

UISearchBar 的自定义 InputView 在 iOS7 中不起作用

iOS 8 具有可变高度的自调整单元格

在具有动态高度的 IB uitableviewcell 中使用带有 XIB 的自定义视图

具有多行 UILabel 的自定义 Tableview 单元格需要动态高度

ios添加自定义inputView