如果键盘阻止了文本视图,则移动 UIView

Posted

技术标签:

【中文标题】如果键盘阻止了文本视图,则移动 UIView【英文标题】:Move UIView if keyboard is blocking a textview 【发布时间】:2017-05-10 16:19:39 【问题描述】:

您好,我有一个 UIView,它显示为模式。该视图包含一些 UITextView 字段。问题是当我编辑一些较低的视图时,键盘会弹出隐藏它的字段。

我需要一种方法来使视图内容可滚动,或者如果键盘挡住它,则将视图内容向上移动。视图是以编程方式创建的。我尝试移动视图,但无法获得活动的 textview(从未调用过 textViewDidBeginEditing 方法)。这是我的代码..

EditController.m

- (void)editNavPressedEdit:(MapElement *)mapElement 

    [self dismissViewControllerAnimated:YES completion:^

        EditAnnotationController *annotationController = [[EditAnnotationController alloc] init];
        annotationController.mapElement = mapElement;
        annotationController.delegate = self;

        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:annotationController];
        navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
        navigationController.preferredContentSize = CGSizeMake(500, 500);
        navigationController.navigationBar.translucent = NO;
        navigationController.navigationBar.barTintColor = [UIColor blackColor];
        navigationController.view.backgroundColor = [UIColor blackColor];

        [self presentViewController:navigationController animated:YES completion:nil];
    ];

EditDetailController.h

@class MapElement;

@protocol EditAnnotationDelegate

- (void)editAnnotationSaved:(MapElement *)element;

- (void)editAnnotationCancelled;

@end

@interface EditAnnotationController : UIViewController <NavigationPickerDelegate, EditOverlayDelegate, UITextViewDelegate>

@property(nonatomic, strong) MapElement *mapElement;
@property(nonatomic, weak) id <EditAnnotationDelegate> delegate;

@end

EditDetailController.m

@implementation EditAnnotationController 
    UIView *_detailView;

    NSLayoutConstraint *_detailWidth;
    NSArray *_detailHoriz;

    NSMutableDictionary *_bindings;
    NSMutableArray *_detailObjects;

    NSDateFormatter *_dateFormatter;

    UIButton *_dateButton;

    UISegmentedControl *_segmentedControl;
    NSArray *_segments;
    NSString *_segmentsBinding;

    UITextField *_radiusField;
    UITextView *_activeField;


@synthesize mapElement = _mapElement;
@synthesize delegate = _delegate;

- (void)viewDidLoad 
    [super viewDidLoad];

    _detailObjects = [NSMutableArray array];
    _bindings = [NSMutableDictionary dictionary];

    _dateFormatter = [NSDateFormatter new];
    _dateFormatter.dateFormat = @"MM/dd/yyyy hh:mm:ss a";

    [self setUpDetailView];

    if (_mapElement) 
        [self setUpMapElement];
    

    UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(save)];
    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel)];

    self.navigationItem.rightBarButtonItem = saveButton;
    self.navigationItem.leftBarButtonItem = cancelButton;


- (void)viewWillAppear:(BOOL)animated 
    [super viewWillAppear:animated];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];


- (void)viewWillDisappear:(BOOL)animated 
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];


- (void)setUpDetailView 
    _detailView = [UIView new];
    _detailView.backgroundColor = [UIColor blackColor];
    _detailView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:_detailView];

    NSArray *vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:@@"view": _detailView];
    _detailHoriz = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@@"view": _detailView];

    [self.view addConstraints:vertical];
    [self.view addConstraints:_detailHoriz];



- (void)keyboardWillShow:(NSNotification *)notification 

    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;


    [UIView animateWithDuration:0.3 animations:^
        CGRect f = self.view.frame;
        f.origin.y = -keyboardSize.height + 250;
        self.view.frame = f;
    ];


- (void)textViewDidBeginEditing:(UITextView *)textView 
    _activeField = textView;


- (void)textViewDidEndEditing:(UITextView *)textView 
    _activeField = nil;


- (void)keyboardWillHide:(NSNotification *)notification 

    [UIView animateWithDuration:0.3 animations:^
        CGRect f = self.view.frame;
        f.origin.y = 44;
        self.view.frame = f;
    ];



- (void)setUpMapElement 
    [self setViewWidth:320];

    [self addImage:_mapElement.iconImage size:CGSizeMake(30, 30)];

    switch ([_mapElement.layerID intValue]) 
        case 1:
            [self configureHydrant];
            break;
    

    [self addConstraints];



- (void)configureHydrant 
    [self addTitleLabel:@"Hydrant"];

    [self addHeaderLabel:@"Name:"];
    _bindings[propertyKeyPathLastComponent(_mapElement.subType)] = [self addTextField:_mapElement.subType];

    [self addHeaderLabel:@"Cap Color:"];

    _segments = @[@"Red", @"Blue", @"Green", @"Orange"];
    _segmentsBinding = propertyKeyPathLastComponent(_mapElement.steamerCapColor);
    [self addSegments:_segments selected:_mapElement.steamerCapColor];

    [self addHeaderLabel:@"Water line size:"];
    _bindings[propertyKeyPathLastComponent(_mapElement.waterLineSize)] = [self addTextField:_mapElement.waterLineSize.stringValue];

    [self addHeaderLabel:@"Flow rate:"];
    _bindings[propertyKeyPathLastComponent(_mapElement.flowRate)] = [self addTextField:_mapElement.flowRate.stringValue];

    [self addHeaderLabel:@"PSI:"];
    _bindings[propertyKeyPathLastComponent(_mapElement.psi)] = [self addTextField:_mapElement.psi.stringValue];

    [self addHeaderLabel:@"Notes:"];
    _bindings[propertyKeyPathLastComponent(_mapElement.description)] = [self addTextView:_mapElement.description];

【问题讨论】:

【参考方案1】:

每当您创建相关的 TextView 时,请将您的 ViewController 设置为它们的委托:

UITextField *myTextField = [UITextField alloc] init];
myTextField.delegate = self;

在此之后 textViewDidBeginEditing 应该按预期调用。

【讨论】:

【参考方案2】:

首先注册“UIKeyboardWillShowNotification”和“UIKeyboardWillHideNotification”通知,如下所示,

[[NSNotificationCenter defaultCenter] addObserver:self                                           selector:@selector(keyboardWillShown:)
                                             name:UIKeyboardWillShowNotification object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillBeHidden:)
                                             name:UIKeyboardWillHideNotification object:nil]

然后实现方法,'keyboardWillShown:' 和 'keyboardWillBeHidden:',如下所示,

- (void)keyboardWillShown:(NSNotification*)aNotification
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

 if(selectedTextField.origin.y > self.view.size - kbSize.height)
     //shift view upwards
   
 

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
       //set origin of view to (0,0)
 

【讨论】:

我的问题是我无法触发 textViewDidBeginEditing 方法。我无法获得活动的文本视图,可能是因为它是以编程方式创建的? @nikBhosale

以上是关于如果键盘阻止了文本视图,则移动 UIView的主要内容,如果未能解决你的问题,请参考以下文章

React Native:键盘在调整其视图高度时阻止多行文本输入

手势识别器阻止触摸已结束

UICollectionView:补充视图阻止项目选择

在 iOS Swift 中使用键盘平移手势处理文本输入视图移动

阻止 UIView 离开屏幕

不希望模态视图在键盘显示上向上移动