Отключите прокрутку UIScrollView, когда UITextField становится первым респондентом - PullRequest
60 голосов
/ 03 января 2011

Когда UITextField, встроенный в UIScrollView, становится первым респондентом, скажем, если пользователь вводит какой-то символ, UIScrollView автоматически прокручивает это поле, есть ли способ отключить это?

Дубликат rdar: // 16538222 более

Ответы [ 11 ]

61 голосов
/ 28 сентября 2012

Опираясь на ответ Моше ...

Подкласс UIScrollView и переопределите следующий метод:

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated

Оставьте его пустым.Работа выполнена!

56 голосов
/ 15 апреля 2011

Я боролся с той же проблемой, и, наконец, я нашел решение.

Я исследовал, как выполняется автопрокрутка путем отслеживания трассировки вызовов, и обнаружил, чтовнутренний [UIFieldEditor scrollSelectionToVisible] вызывается, когда буква набирается в UITextField.Этот метод, кажется, действует на UIScrollView ближайшего предка UITextField.

Так, на textFieldDidBeginEditing, оборачивая UITextField новым UIScrollView с таким же размеромэто (то есть, вставка представления между UITextField и его суперпредставлением), это заблокирует автопрокрутку.Наконец удалите эту оболочку на textFieldDidEndEditing.

Код выглядит так:

- (void)textFieldDidBeginEditing:(UITextField*)textField {  
    UIScrollView *wrap = [[[UIScrollView alloc] initWithFrame:textField.frame] autorelease];  
    [textField.superview addSubview:wrap];  
    [textField setFrame:CGRectMake(0, 0, textField.frame.size.width, textField.frame.size.height)]; 
    [wrap addSubview: textField];  
}  

- (void)textFieldDidEndEditing:(UITextField*)textField {  
  UIScrollView *wrap = (UIScrollView *)textField.superview;  
  [textField setFrame:CGRectMake(wrap.frame.origin.x, wrap.frame.origin.y, wrap.frame.size.width, textField.frame.size.height)];
  [wrap.superview addSubview:textField];  
  [wrap removeFromSuperview];  
}  

надеюсь, это поможет!

8 голосов
/ 31 августа 2015

У меня была такая же проблема с отключением автопрокрутки для UITextView, являющегося ячейкой UITableView.Я смог решить ее, используя следующий подход:

@interface MyTableViewController : UITableViewController<UITextViewDelegate>

@implementation MyTableViewController {
    BOOL preventScrolling;
    // ...
}

// ... set self as the delegate of the text view

- (void)textViewDidBeginEditing:(UITextView *)textView {
    preventScrolling = YES;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (preventScrolling) {
        [self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:NO];
    }
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    preventScrolling = NO;
}

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

6 голосов
/ 20 января 2012

Как упоминалось в Taketo, когда UITextField становится первым респондентом, его первое родительское представление типа UIScrollView (если оно существует) прокручивается, чтобы сделать UITextField видимым. Самый простой способ - просто обернуть каждый UITextField в UIScrollView (или, в идеале, обернуть все их в один макет UIScrollView). Это очень похоже на решение Taketo, но оно должно дать вам немного лучшую производительность, и оно, на мой взгляд, сделает ваш код (или ваш интерфейс в Интерфейсном Разработчике) намного чище.

3 голосов
/ 11 октября 2017

Опираясь на ответ Люка, чтобы решить проблему, заключающуюся в том, что его решение полностью отключает автопрокрутку, вы можете выборочно отключить ее следующим образом:

//  TextFieldScrollView
#import <UIKit/UIKit.h>

@interface TextFieldScrollView : UIScrollView

@property (assign, nonatomic) IBInspectable BOOL preventAutoScroll;

@end

@implementation TextFieldScrollView

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
    if (self.preventAutoScroll == NO) {
        [super scrollRectToVisible:rect animated:animated];
    }
}

@end

Таким образом, вы можете полностью настроить его в Интерфейсном Разработчике, чтобы отключить автопрокрутку, но в любой момент иметь полный контроль для его повторного включения (хотя почему вы хотите, чтобы это было за мной).

2 голосов
/ 19 ноября 2014

Похоже на UIScrollview, который содержит поле UIText, автоматически корректирует смещение содержимого;когда текстовое поле станет первым респондентом.Эту проблему можно решить, сначала добавив текстовое поле в виде прокрутки того же размера, а затем добавив его в основной вид прокрутки.вместо непосредственного добавления в основное представление прокрутки

    // Swift

    let rect = CGRect(x: 0, y: 0, width: 200, height: 50)

    let txtfld = UITextField()
    txtfld.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)

    let txtFieldContainerScrollView = UIScrollView()
    txtFieldContainerScrollView.frame = rect
    txtFieldContainerScrollView.addSubview(txtfld)
    // Now add this txtFieldContainerScrollView in desired UITableViewCell, UISCrollView.. etc
    self.mainScrollView.addSubview(txtFieldContainerScrollView)

    // Am33T
1 голос
/ 23 января 2013

Вот как я это делаю:

Это очень просто, вы можете вернуть свой собственный contentOffset для любого scrollRectToVisible.

Таким образом, вы не наносите вреда нормальному поведению и потоку вещей - просто предоставляя одинаковые функциональные возможности в том же канале со своими собственными улучшениями.

#import <UIKit/UIKit.h>

@protocol ExtendedScrollViewDelegate <NSObject>

- (CGPoint)scrollView:(UIScrollView*)scrollView offsetForScrollingToVisibleRect:(CGRect)rect;

@end

@interface ExtendedScrollView : UIScrollView

@property (nonatomic, unsafe_unretained) id<ExtendedScrollViewDelegate> scrollToVisibleDelegate;

@end

#import "ExtendedScrollView.h"

@implementation ExtendedScrollView

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
{
    if (_scrollToVisibleDelegate && [_scrollToVisibleDelegate respondsToSelector:@selector(scrollView:offsetForScrollingToVisibleRect:)])
    {
        [self setContentOffset:[_scrollToVisibleDelegate scrollView:self offsetForScrollingToVisibleRect:rect] animated:animated];
    }
    else
    {
        [super scrollRectToVisible:rect animated:animated];
    }
}

@end
0 голосов
/ 05 февраля 2014

Более простой способ остановить прокрутку прокрутки при выборе textField в вашем viewController :: viewWillAppear () НЕ вызывать [super viewWillAppear];

Затем вы можете управлять прокруткой по своему усмотрению.

0 голосов
/ 09 декабря 2013

У меня есть представление коллекции с текстовым полем в самом верху, имитирующим UITableView.tableHeaderView.Это текстовое поле расположено в области отрицательного смещения содержимого, поэтому оно не мешает остальной части представления коллекции.Я в основном обнаруживаю, выполняет ли пользователь прокрутку в представлении прокрутки и является ли текстовое поле первым респондентом, и прокручивается ли представление прокрутки за верхнюю часть вставки содержимого представления прокрутки.Этот точный код не обязательно поможет никому, но они могли бы манипулировать им, чтобы соответствовать их случаю.

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

    // This is solving the issue where making the text field first responder
    // automatically scrolls the scrollview down by the height of the search bar.
    if (!scrollView.isDragging && !scrollView.isDecelerating &&
        self.searchField.isFirstResponder &&
        (scrollView.contentOffset.y < -scrollView.contentInset.top)) {

        [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top) animated:NO];
    }
}
0 голосов
/ 26 мая 2013

Я попробовал ответ @ TaketoSano, но, похоже, не работает .. В моем случае у меня нет прокрутки, только вид с несколькими текстовыми полями.

И, наконец, я нашел обходной путь,Мне нужны два названия уведомлений по умолчанию для клавиатуры:

  • UIKeyboardDidShowNotification, когда клавиатура все-таки показывалась;
  • UIKeyboardWillHideNotification когда клавиатура будет скрыта.

Вот пример кода, который я использовал:

- (void)viewDidLoad {
  [super viewDidLoad];

  ...

  NSNotificationCenter * notificationCetner = [NSNotificationCenter defaultCenter];
  [notificationCetner addObserver:self
                         selector:@selector(_keyboardWasShown:)
                             name:UIKeyboardDidShowNotification
                           object:nil];
  [notificationCetner addObserver:self
                         selector:@selector(_keyboardWillHide:)
                             name:UIKeyboardWillHideNotification
                           object:nil];
}

- (void)_keyboardWasShown:(NSNotification *)note {
  [self.view setFrame:(CGRect){{272.f, 55.f}, {480.f, 315.f}}];
}

- (void)_keyboardWillHide:(NSNotification *)note {
  [self.view setFrame:(CGRect){{272.f, 226.5f}, {480.f, 315.f}}];
}

Здесь (CGRect){{272.f, 226.5f}, {480.f, 315.f}} - это рамка по умолчанию для видакогда клавиатура скрыта.И (CGRect){{272.f, 55.f}, {480.f, 315.f}} - это кадр вида, когда клавиатура показывала.

Кстати, при смене кадра вида автоматически применяется анимация, это действительно прекрасно!

...