66

UITextField埋め込まれたUIScrollViewが最初の応答者になると (たとえば、ユーザーが文字を入力することによって)、 はUIScrollViewそのフィールドに自動的にスクロールします。それを無効にする方法はありますか?

重複する rdar://16538222

4

11 に答える 11

64

Mosheの答えに基づいて...次のメソッドをサブクラスUIScrollView化してオーバーライドします。

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

空のままにします。仕事は終わりました!


Swiftの場合:

class CustomScrollView: UIScrollView {
    override func scrollRectToVisible(_ rect: CGRect, animated: Bool) { }
}
于 2012-09-28T13:19:27.987 に答える
59

私は同じ問題に苦労してきましたが、ついに解決策を見つけました。

呼び出しトレースを追跡して自動スクロールがどのように行われるかを調査したところ[UIFieldEditor scrollSelectionToVisible]UITextField. UIScrollViewこのメソッドは、 の最も近い祖先の に作用するようUITextFieldです。

したがって、 で を同じサイズのnewでtextFieldDidBeginEditingラップする(つまり、とそのスーパービューの間にビューを挿入する) と、自動スクロールがブロックされます。最後に、上のこのラッパーを削除します。UITextFieldUIScrollViewUITextFieldtextFieldDidEndEditing

コードは次のようになります。

- (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];  
}  

お役に立てれば!

于 2011-04-15T06:13:23.737 に答える
8

Taketo が述べたように、 aUITextFieldがファーストレスポンダーになると、そのタイプの最初の親ビューUIScrollView(存在する場合) がスクロールされてUITextField表示されます。最も簡単なハックは、各 UITextField を単純にラップすることですUIScrollView(または、理想的には、それらすべてを単一のダミーでラップしますUIScrollView)。これは Taketo のソリューションと非常によく似ていますが、私の意見では、パフォーマンスがわずかに向上し、コード (または Interface Builder のインターフェイス) がず​​っときれいになります。

于 2012-01-20T00:27:16.550 に答える
3

ルークの答えに基づいて、彼のソリューションが自動スクロールを完全に無効にする問題を処理するために、次のように選択的に無効にすることができます。

//  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

このようにして、自動スクロールを無効にするようにInterface Builderで完全に設定できますが、いつでも完全に制御して再度有効にすることができます(ただし、なぜそうしたいのかは私にはわかりません).

于 2017-10-11T13:52:24.780 に答える
2

UITextfieldを含むUIScrollviewのように見え、そのコンテンツオフセットを自動調整します。テキストフィールドがファーストレスポンダになるとき。これは、最初に同じサイズのスクロール ビューに textfield を追加してから、メイン スクロール ビューに追加することで解決できます。メインスクロールビューに直接追加する代わりに

    // 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
于 2014-11-19T08:55:18.907 に答える
1

これは私がそれを行う方法です:

非常に簡単です。任意の scrollRectToVisible に対して独自の contentOffset を返すことができます。

このようにして、通常の動作や物事の流れを損なうことはありません。独自の改善を加えて、同じチャネルで同じ機能を提供するだけです。

#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
于 2013-01-23T08:24:32.940 に答える
0

@TaketoSanoの答えを試しましたが、うまくいかないようです..私の場合は、スクロールビューがなく、いくつかのテキストフィールドを持つビューだけです。

そして最後に、私は回避策を得ました。必要なキーボードのデフォルトの通知名は 2 つあります。

  • 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}}が表示されたときのビューのフレームです。

ところで、ビューのフレーム変更は自動的にアニメーションに適用されます。これは本当に完璧です!

于 2013-05-26T14:04:45.673 に答える
0

一番上にテキスト フィールドがあり、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];
    }
}
于 2013-12-09T19:27:16.187 に答える
0

それを可能にするプロパティを知りませんUIScrollView。それを無効にできるのは、ユーザーエクスペリエンスが悪いでしょう、IMHO。

UIScrollViewとはいえ、メソッドの一部をサブクラス化およびオーバーライドして、UITextfieldスクロールする前に がファーストレスポンダーではないことを確認することは可能かもしれません。

于 2011-01-03T16:25:42.010 に答える