Подтвердить что ты не робот

Как прокручивать просмотр, когда появляется клавиатура?

Я знаю, что этот вопрос задавали снова и снова, но, похоже, для меня ничего не работает. Большинство решений вокруг довольно устарели, а остальные - невероятно огромные блоки кода, которые в десять раз больше, чем собственно кодирование проектов. У меня есть несколько UITextFields, выстроенных вертикально, но когда клавиатура запускает для редактирования, она закрывает текстовое поле. Мне было интересно, есть ли простой новичок, чтобы прокрутить представление вверх, а затем отступить, когда начинается и заканчивается редактирование?

Спасибо.

4b9b3361

Ответ 1

Я разработал решения, которые работают со списком прокрутки и без прокрутки с помощью уведомления клавиатуры и обнаружения текущего первого ответчика, но иногда я использую это тривиальное решение: простой способ - обнаружить открытую клавиатуру через текстовое поле делегата textViewDidBeginEditing: и переместить весь вид вверх. Самый простой способ сделать это - это что-то вроде изменения self.view.bounds.origin.y -100 (или что-то еще). Используйте соответствующий метод textViewShouldEndEditing:, чтобы установить его на противоположное, что в этом случае равно 100. Изменение bounds является относительной процедурой. После его изменения кадр перемещается, но начало координат по-прежнему равно нулю.

Ответ 2

Поскольку я нашел его, я использую TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.

Он отлично работает и очень прост в настройке:

  • Добавить UIScrollView в ваш контроллер просмотра xib
  • Установите класс представления прокрутки в TPKeyboardAvoidingScrollView (все еще в xib, через инспектор идентификации)
  • Поместите все элементы управления в это представление прокрутки

Вы также можете создать его программно, если хотите.


Существует класс для той же потребности внутри UITableViewController; это необходимо только в том случае, если вы поддерживаете версию iOS ниже 4.3.

Ответ 3

@BenLu и другие пользователи, которые сталкиваются с проблемой функции, никогда не получают вызов по следующей причине: Поскольку функция делегата inbuild bydefaults возвращает void вместо BOOL, это должно выглядеть следующим образом:

 -(void)textFieldDidBeginEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.35f];
    CGRect frame = self.view.frame;
    frame.origin.y = -100;
    [self.view setFrame:frame];
    [UIView commitAnimations];
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.35f];
    CGRect frame = self.view.frame;
    frame.origin.y = 100;
    [self.view setFrame:frame];
    [UIView commitAnimations];
}

Ответ 4

Я потратил некоторое время на эту проблему и собрал код для создания одного окончательного решения. Моя проблема связана с прокруткой UITableView и открытием/закрытием клавиатуры.

В вашем классе ячейки вам понадобятся два частичных метода:

    void EditingBegin(UITextField sender)
    {
        // Height of tallest cell, you can ignore this!
        float tableMargin = 70.0f;
        float tableHeight = _tableView.Frame.Size.Height;
        float keyBoardHeight = KeyboardHeight();

        NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows;
        RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section);
        RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section);
        float lastCellY = rectLast.Y - rectFirst.Y;
        if (lastCellY > tableHeight - keyBoardHeight)
        {
            float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight);
            this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
        }

        float cellPosition = this._tableView.RectForSection(this._section).Y;
        if (cellPosition > tableHeight - keyBoardHeight)
        {
            if (this._tableView.ContentInset.Bottom == 0.0f)
            {
                float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight);
                this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
            }
            else
            {
                this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true);
            }
        }
    }

    partial void EditingEnd(UITextField sender)
    {
        UIView.BeginAnimations(null);
        UIView.SetAnimationDuration(0.3f);
        this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f);
        UIView.CommitAnimations();
    }

а затем в вашем классе контроллера контроллера:

    public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
    {
        base.WillAnimateRotation(toInterfaceOrientation, duration);

        float bottom = this.TableView.ContentInset.Bottom;
        if (bottom > 0.0f)
        {
            if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown)
            {
                bottom = bottom * UIScreen.MainScreen.Bounds.Width / UIScreen.MainScreen.Bounds.Height;
            }
            else
            {
                bottom = bottom * UIScreen.MainScreen.Bounds.Height / UIScreen.MainScreen.Bounds.Width;
            }

            UIEdgeInsets insets = this.TableView.ContentInset;
            this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f);
        }
    }  

Ответ 5

Если у вас есть UITableView или UIScrollView, лучше изменить значения для contentOffset вместо внесения изменений в frame.

Работа над Peter Answer, добавление этого метода в ваш класс прекрасно работает:

- (void)textViewDidBeginEditing:(UITextField *)textField {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.35f];
    CGPoint offset = self.tableView.contentOffset;
    offset.y += 200; // You can change this, but 200 doesn't create any problems
    [self.tableView setContentOffset:offset];
    [UIView commitAnimations];
}

Для этого не нужно добавлять метод textViewDidEndEditing.


Мне не нужно это говорить, но для этого вам нужно26 > или UITextView быть делегатом вашего контроллера.

Ответ 6

Начиная с ответа Питера, я разработал следующий подход в Swift 3.0 под iOS 10.1. Я делаю это для textView, поэтому я реализовал функции UITextViewDelegate textViewDidBeginEditing и textViewDidEndEditing, где я настраиваю границы представления. Как вы можете видеть, я устанавливаю значение начала Y для небольшого положительного числа для прокрутки вверх, а затем обратно в 0, чтобы вернуться в исходное положение.

Вот соответствующий код моего ViewController. Вам не нужно анимировать, но это добавляет приятный штрих.

func textViewDidBeginEditing(_ textView: UITextView)
{
    if UIScreen.main.bounds.height < 568 { 
        UIView.animate(withDuration: 0.75, animations: {
            self.view.bounds.origin.y = 60
        })
    }
}

func textViewDidEndEditing(_ textView: UITextView)
{
    if UIScreen.main.bounds.height < 568 {
        UIView.animate(withDuration: 0.75, animations: {
            self.view.bounds.origin.y = 0
        })
    }
}

Ответ 7

У меня есть scrollview и 3 текстовых поля. У меня есть простой код из моего собственного приложения:

.h файл:

#import <UIKit/UIKit.h>

@interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate>

@property (nonatomic, retain) NSDictionary *dict_contactDetail;

@property (nonatomic, retain) IBOutlet UILabel *lbl_name;
@property (nonatomic, retain) IBOutlet UITextField *txtField_tel;
@property (nonatomic, retain) IBOutlet UITextField *txtField_address;
@property (nonatomic, retain) IBOutlet UITextField *txtField_email;

@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;

@end

.m file:

#import "AddContactViewController.h"

@interface AddContactViewController ()

@end

@implementation AddContactViewController

@synthesize dict_contactDetail;

@synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil       
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

   // NSLog(@"dict_contactDetail : %@", dict_contactDetail);

    UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonSystemItemDone target:self action:@selector(addEmergencyContact:)];
    self.navigationItem.rightBarButtonItem = rightButton;


    lbl_name.text = [NSString stringWithFormat:@"%@ %@", [dict_contactDetail  valueForKey:@"fname"], [dict_contactDetail  valueForKey:@"lname"]];

    txtField_tel.returnKeyType = UIReturnKeyDone;
    txtField_email.returnKeyType = UIReturnKeyDone;
    txtField_address.returnKeyType = UIReturnKeyDone;

}



-(void)addEmergencyContact:(id)sender
{
    scrollView.frame = CGRectMake(0, 0, 320, 460);
}

#pragma mark - text field delegates
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if([textField isEqual:txtField_tel])
    {
        [scrollView setContentOffset:CGPointMake(0, 70)];
        scrollView.frame = CGRectMake(0, 0, 320, 210);
    }
    if([textField isEqual:txtField_address])
    {
        [scrollView setContentOffset:CGPointMake(0, 140)];
        scrollView.frame = CGRectMake(0, 0, 320, 210);
    }
    if([textField isEqual:txtField_email])
    {
        [scrollView setContentOffset:CGPointMake(0, 210)];
        scrollView.frame = CGRectMake(0, 0, 320, 210);
    }
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    scrollView.frame = CGRectMake(0, 0, 320, 460);
    [textField resignFirstResponder];
    return YES;
}



@end