Создание прокрутки UITableView при выделении текстового поля - PullRequest
245 голосов
/ 27 февраля 2009

После долгих проб и ошибок я сдаюсь и задаю вопрос. Я видел много людей с похожими проблемами, но не мог правильно ответить на все ответы.

У меня есть UITableView, который состоит из пользовательских ячеек. Ячейки состоят из 5 текстовых полей, расположенных рядом друг с другом (вроде сетки).

Когда я пытаюсь прокрутить и отредактировать ячейки внизу UITableView, мне не удается правильно расположить свои ячейки над клавиатурой.

Я видел много ответов, говорящих об изменении размеров вида и т. Д., Но ни один из них до сих пор не работал должным образом.

Может ли кто-нибудь уточнить «правильный» способ сделать это на конкретном примере кода?

Ответы [ 45 ]

1 голос
/ 31 декабря 2013

Простое и быстрое решение.

Я просто прокручиваю в нужную ячейку всякий раз, когда происходит прокрутка

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView 

Если я знаю, что таблица сейчас находится в этом режиме "_keepMyCellOnTop" & Я знаю выбранную ячейку "_selectedCellIndex" или выделите выделенную ячейку

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{

    if (_keepMyCellOnTop)
    {
        [self.tableView scrollToRowAtIndexPath:_selectedCellIndex atScrollPosition:UITableViewScrollPositionTop animated:NO];
    }
}

Это предотвратит прокрутку.

Размещение кода в -(void) scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView приведет к прокрутке вверх и вниз

1 голос
/ 20 марта 2011

UITableViewController делает прокрутку автоматически, действительно. Разница по сравнению с использованием UIViewController заключается в том, что вы должны создавать элементы Navbar-Buttonitems программно, используя NavigationController, при использовании TableViewController.

1 голос
/ 23 ноября 2011

Другой простой метод (работает только с одним разделом)

//cellForRowAtIndexPath
UItextField *tf;
[cell addSubview:tf];
tf.tag = indexPath.row;
tf.delegate = self;

//textFieldDidBeginEditing:(UITextField *)text
[[self.tableView scrollToRowsAtIndexPath:[NSIndexPath indexPathForRow:text.tag in section:SECTIONINTEGER] animated:YES];
1 голос
/ 05 марта 2012

Если ваш UITableView управляется подклассом UITableViewController, а не UITableView, а делегатом текстового поля является UITableViewController, он должен управлять всей прокруткой автоматически - все эти другие комментарии очень трудно реализовать на практике.

Хороший пример см. В примере проекта кода Apple: TaggedLocations.

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

1 голос
/ 08 октября 2018

Небольшая вариация с Swift 4.2 ...

В моем UITableView у меня было много разделов, но мне пришлось избегать эффекта плавающего заголовка , поэтому я использовал подход " dummyViewHeight ", как было где-то здесь, в Переполнении стека ... Так что это мое решение для этой проблемы (оно работает также для клавиатуры + панель инструментов + предложения):

Объявите его как константу класса:

let dummyViewHeight: CGFloat = 40.0

Тогда

override func viewDidLoad() {
    super.viewDidLoad()
    //... some stuff here, not needed for this example

    // Create non floating header
    tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: dummyViewHeight))
    tableView.contentInset = UIEdgeInsets(top: -dummyViewHeight, left: 0, bottom: 0, right: 0)

    addObservers()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    removeObservers()
}

А здесь вся магия ...

@objc func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let keyboardHeight = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue.size.height
        tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight))
        tableView.contentInset = UIEdgeInsets(top: -dummyViewHeight, left: 0, bottom: keyboardHeight, right: 0)
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.25) {
        self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: self.dummyViewHeight))
        self.tableView.contentInset = UIEdgeInsets(top: -self.dummyViewHeight, left: 0, bottom: 0, right: 0)
    }
}
1 голос
/ 26 июля 2012

Вот как я сделал эту работу, которая представляет собой смесь ответов Сэма Хо и Марселя В. и некоторых моих собственных исправлений ошибок, внесенных в мой дерьмовый код. Я использовал UITableViewController. Размер таблицы теперь корректно изменяется при отображении клавиатуры.

1) В viewDidLoad я добавил:

self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

2) Я забыл назвать super эквиваленты в viewWillAppear и awakeFromNib. Я добавил их обратно.

1 голос
/ 12 февраля 2016

в viewdidload

-(void)viewdidload{

[super viewdidload];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
}

    -(void)keyboardWillChange:(NSNotification*)sender{

        NSLog(@"keyboardwillchange sender %@",sender);

float margin=0  // set your own topmargin


        CGFloat originY = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;


        if (originY >= self.view.frame.size.height){

            NSLog(@"keyboardclose");



            [tb_ setFrame:CGRectMake(0, margin, self.view.frame.size.width, self.view.frame.size.height-margin)];

        }else{

            NSLog(@"keyobard on");

            float adjustedHeight = self.view.frame.size.height - margin - (self.view.frame.size.height-originY);

            [tb_ setFrame:CGRectMake(0, margin, self.view.frame.size.width, adjustedHeight)];
        }







    }
0 голосов
/ 10 июня 2018

Решение для Swift 3-4 с анимацией и сменой кадра клавиатуры:

Сначала создайте Bool:

// MARK: - Private Properties
private var isKeyboardShowing = false

Во-вторых, добавьте наблюдателей в уведомления клавиатуры системы:

// MARK: - Overriding ViewController Life Cycle Methods
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: .UIKeyboardWillHide, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame), name: .UIKeyboardWillChangeFrame, object: nil)
}

В-третьих, подготовьте функцию анимации:

func adjustTableViewInsets(keyboardHeight: CGFloat, duration: NSNumber, curve: NSNumber){
    var extraHeight: CGFloat = 0
    if keyboardHeight > 0 {
        extraHeight = 20
        isKeyboardShowing = true
    } else {
        isKeyboardShowing = false
    }

    let contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight + extraHeight, right: 0)
    func animateFunc() {
        //refresh constraints
        //self.view.layoutSubviews()
        tableView.contentInset = contentInset
    }

    UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: [UIViewAnimationOptions(rawValue: UInt(curve))], animations: animateFunc, completion: nil)
}

Затем добавьте методы цели / действия (вызываемые наблюдателями):

// MARK: - Target/Selector Actions
func keyboardWillShow(notification: NSNotification) {
    if !isKeyboardShowing {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight = keyboardSize.height

            let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
            let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber

            adjustTableViewInsets(keyboardHeight: keyboardHeight, duration: duration, curve: curve)
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
    let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
    adjustTableViewInsets(keyboardHeight: 0, duration: duration, curve: curve)
}

func keyboardWillChangeFrame(notification: NSNotification) {
    if isKeyboardShowing {
        let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
        let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber

        if let newKeyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight = newKeyboardSize.height
            adjustTableViewInsets(keyboardHeight: keyboardHeight, duration: duration, curve: curve)
        }
    }
}

Наконец, не забудьте удалить наблюдателей в deinit или в view. WillDisappear:

deinit {
    NotificationCenter.default.removeObserver(self)
}
0 голосов
/ 22 февраля 2018

Не нужно никаких расчетов, используйте код ниже, это будет работать: Этот код, который я использовал в моей пользовательской UITableviewcell, работает:

override func viewDidLoad() {
super.viewDidLoad()

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)}


func keyboardWillShow(_ notification:Notification) {

if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
    tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
}}


func keyboardWillHide(_ notification:Notification) {

if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
    tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
}}
0 голосов
/ 26 октября 2011

Я просто снова посмотрел ссылку на библиотеку iOS 5.0 и обнаружил этот раздел под названием «Перемещение содержимого, расположенного под клавиатурой»: TextAndWebiPhoneOS KeyboardManagement

Это новое с iOS 5, возможно? Я еще не читал об этом, потому что нахожусь в центре чего-то другого, но, возможно, другие знают больше и могут просветить меня и других здесь.

Заменяет ли документ Apple то, что обсуждалось здесь, или эта информация все еще полезна для пользователей iOS 5 SDK?

...