UITextFieldのカーソルを非表示にする


137

私はにa UITextFieldを使用していますUIPickerView。そのinputViewため、ユーザーがテキストフィールドをタップすると、ユーザーがオプションを選択するためのピッカーが呼び出されます。

ほぼすべてが機能しますが、私は1つの問題を抱えています。ユーザーがフィールドに入力することは想定されておらず、キーボードも表示されないため、アクティブなときにカーソルがテキストフィールドで点滅します。テキストフィールドeditingNOに設定してタッチを追跡するか、カスタムスタイルのボタンに置​​き換えて、コードを介してピッカーを呼び出すことで、これを巧みに解決できることはわかっています。ただし、UITextFieldDelegateテキストフィールドでのすべてのイベント処理のメソッドを使用したいと考えています。テキストフィールドをボタンに置​​き換えるなどのハックでは、このアプローチは許可されていません。

UITextField代わりにカーソルを非表示にするにはどうすればよいですか?

回答:


277

単にUITextFieldをサブクラス化し、caretRectForPositionをオーバーライドします

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    return CGRectZero;
}

2
綺麗な!私にとっては魅力のように機能します。
Joe Strout 2013年

1
@ジョセフチウそれは素晴らしい作品。しかし、iOS 4.3ではできません。これを手伝ってくれませんか?
Dinesh Raja

二重の
賛成投票に

1
ただのメモ。私のサブクラスで、bool hideCaretを追加し、次にこのオーバーライドでtrueの場合-> CGRectZeroを返し、それ以外の場合はsuperの結果を返します。
WCByrne 2014

6
外部キーボードを使用しているユーザーは、カーソルが非表示になっていてピッカービューを使用している場合でも、テキストフィールドの値を変更できることに注意してください。
マーク

156

iOS 7以降tintColor = [UIColor clearColor]では、textFieldにを設定するだけでキャレットが消えます。


1
これは現時点では機能しますが、将来変更される可能性があるため、使用しないことをお勧めします。むしろを選ぶcaretRectForPosition:オーバーライドソリューション。
lipka 14

@lipka確かに、それはおそらくより良い方法です。
jamone 2014

2
今のところ十分です。場合によっては、簡単な解決策が必要なこともあります。
GoldenJoe 2015

これは、これまでで最も簡単なソリューションです。
Jay Q.

1
この回答はiOS 7以降で承認される必要があります
tryp

95

あなただけのテキストフィールドのtintColorをクリアすることができます

self.textField.tintColor = [UIColor clearColor];

Swift 3.0

self.textField.tintColor = .clear

ここに画像の説明を入力してください


最も簡単な答え。
Nik Kov

2
上記のように、ティントカラーをクリアしても、外部キーボード(iPad Pro)を使用しているユーザーはテキストを変更できます。
マイケルロング

@MichaelLongこれは、ユーザーがテキストを変更できないようにすることではなく、単なるスタイルの選択です。
JRam13

21

また、ユーザーがテキストを選択、コピー、または貼り付けないようにして、テキスト入力のみがピッカービューから行われるようにすることもできます。

- (CGRect) caretRectForPosition:(UITextPosition*) position
{
    return CGRectZero;
}

- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
    return nil;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(copy:) || action == @selector(selectAll:) || action == @selector(paste:))
    {
        returnNO;
    }

    return [super canPerformAction:action withSender:sender];
}

http://b2cloud.com.au/tutorial/disabling-the-caret-and-text-entry-in-uitextfields/


15

チェックアウト財産 selectedTextRangeプロトコル UITextInputクラス UITextField準拠して。少ない!これが、オブジェクト指向プログラミングのレッスンです。

キャレットを非表示

キャレットを非表示にするには、テキストフィールドの選択したテキスト範囲を削除します。

textField.selectedTextRange = nil; // hides caret

キャレットを再表示

キャレットを再表示するには2つの方法があります。

  1. テキストフィールドの選択されたテキスト範囲をドキュメントの最後に設定します。

    UITextPosition *end = textField.endOfDocument;
    textField.selectedTextRange = [textField textRangeFromPosition:end
                                                        toPosition:end];
  2. キャレットを同じ場所に保持するには、まず、テキストフィールドの選択したテキスト範囲をインスタンス変数に格納します。

    _textFieldSelectedTextRange = textField.selectedTextRange;
    textField.selectedTextRange = nil; // hides caret

    次に、キャレットを再表示する場合は、テキストフィールドの選択されたテキスト範囲を元のテキスト範囲に戻すだけです。

    textField.selectedTextRange     = _textFieldSelectedTextRange;
    _textFieldLastSelectedTextRange = nil;

3
この特定のソリューションは、私の実装では機能しませんでした。カーソルはまだ点滅します。
Art Geigel 2013年

さて、その後、おそらくあなたがでバグを報告しなければならないbugreport.apple.com iOSのドキュメントが言うので:「テキスト範囲の長さを持っている場合、それは現在選択されているテキストを示し、それはゼロの長さを持っている場合、それはキャレット(挿入を示しています。ポイント)。テキスト範囲オブジェクトがnilの場合、現在選択されていないことを示します。
ma11hew28 2013年

4
私は報告を提出するほど気にしていない。他の人があなたの「解決策」を使用していて、それが機能していない場合、私は彼らが一人ではないことを彼らに知らせたかったのです。
Art Geigel 2013年

@ArtGeigelのコメントにもかかわらず、これは私にとって完全に機能します。ただし、私はオーバーライドを含むソリューションを好むcaretRectForPosition。それはそれが何をしているのかより明確であり、あなたが引用したドキュメントは「現在選択されていない」ときのキャレットの振る舞いがどうあるべきかを明確にしていません。これが機能しないという@ArtGeigelの主張が正しかった場合(少なくとも私が知る限り、正しくありません)、それがバグであったことは明らかではありません。
Mark Amery 2013

私もうまくいきませんでした。キャレットはまだそこにあり、点滅しています。
CW0007007 2013

11

OPによって提供される回答。質問本体からコピーされ、増え続ける未回答の質問の尾をきれいにするのに役立ちます。

私は別の解決策を見つけました:UIButtonこれらのメソッドをサブクラス化してオーバーライドします

- (UIView *)inputView {
    return inputView_;
}

- (void)setInputView:(UIView *)anInputView {
    if (inputView_ != anInputView) {
        [inputView_ release];
        inputView_ = [anInputView retain];
    }
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

ボタンUIResponderは、と同じように動作UITextFieldし、実装は非常に簡単です。


5
これは本当に素晴らしい解決策ではありません。以下、この答えをチェックアウト:stackoverflow.com/a/13660503/1103584
DiscDev

2
なぜこれが優れたソリューションではないのですか?それは意図した効果を達成し、以前はそれを持っていなかったクラスに機能を提供します。また、ハックではありません。本当にかっこいいと思います。それで何が問題になっていますか?
BreadicalMD 2013

2
@BreadicalMD私が見ることができる最大の問題はUITextFieldDelegate、これを使用して編集イベントの開始と終了を処理できないことです。代わりに-私が知らないこれらのイベントを処理する方法がない限り、ボタンサブクラスでオーバーライドbecomeFirstResponderresignFirstResponderて、独自のデリゲートプロトコルを作成し、delegateプロパティを追加して、前述のデリゲートを呼び出す必要があります。メソッド。これはcaretRectForPositionUITextFieldサブクラスで単にオーバーライドするよりもはるかに多くの作業です。
Mark Amery 2013年

1
@BreadicalMDとはいえ、Joseph Chiuの答えは実用的な観点からは優れているものの、これはかなりセクシーだと私はまだ同意します。これUIResponderまでクラス参照を注意深く見たことがなく、このようなトリックが可能であるとは思いもしませんでした。
Mark Amery 2013年

パーティーには遅れますが、これは非常に良い解決策だと思いUITextFieldます。カーソルを非表示にしたり、カーソルを非表示にしたりするよりもはるかに適切であり、ハックが少ないと感じます。の機能を使用していませんUITextField
Rupert

7

Netの投稿のSwift 5バージョン

  override func caretRect(for position: UITextPosition) -> CGRect {
    return .zero
  }
  
  override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] {
    return []
  }
  
  override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return false
  }

私の場合、それはうまくいきました。Swift 4を使用してこれらのメソッドを持つUITextFieldのサブクラスを追加しました。ありがとうございます。
J.フェズ

3

tintColorをClear Colorに設定します

textfield.tintColor = [UIColor clearColor];

インターフェースビルダーからも設定できます


2
2年以上前の回答をコピーしました。
Ashley Mills

1
申し訳ありませんが、私は何もコピーしませんでした。
Ahmad Al-Attal 2017年

4
おもしろい「友だち」。あなたの答えは、15年5月1日の@oldmanの答えにかなり似ています。あなたの違いは何ですか?
Ashley Mills

1
上記のように、ティントカラーをクリアしても、外部キーボード(iPad Pro)を使用しているユーザーはテキストを変更できます。
マイケルロング

プロユーザーは好きなことをすることができます。彼らはプロです:彼らは自分のやっていることを知っています; ^)
Anton Tropashko

2

カーソルを非表示にしたい場合は、簡単に使用できます。それは私のために働いた。

[[textField valueForKey:@"textInputTraits"] setValue:[UIColor clearColor] forKey:@"insertionPointColor"]

3
私の知る限り、これは文書化されていません。これを使用してアプリストアに送信すると、プライベートAPIの呼び出しでアプリが拒否される可能性がありますが、これを使用して何らかの方法で推測をテストすることはできません。サブクラス化せずにこの問題を解決できると便利なので、残念です。この回答でそれが可能になります。
Mark Amery 2013年

1

OPによって提供される回答。質問本体からコピーされ、増え続ける未回答の質問の尾をきれいにするのに役立ちます。

私は正しい解決策を持っていると思いますが、改善できる場合は歓迎されます:)まあ、私はUITextFieldのサブクラスを作成し、境界のCGRectを返すメソッドをオーバーライドしました

-(CGRect)textRectForBounds:(CGRect)bounds {
    return CGRectZero;
}

問題?rectがゼロであるため、テキストは表示されません。しかし、UILabelをコントロールのサブビューとして追加し、setTextメソッドをオーバーライドしたので、通常どおりテキストを入力すると、テキストフィールドのテキストはnilになり、テキストを表示するラベルになります

- (void)setText:(NSString *)aText {
    [super setText:nil];

    if (aText == nil) {
        textLabel_.text = nil;
    }

    if (![aText isEqualToString:@""]) {
        textLabel_.text = aText;
    }
}

これで物事は期待どおりに動作します。それを改善する方法を知っていますか?


ジョセフチウの代替アプローチは非常に似ていますが、はるかに単純であるため、この答えは基本的に価値がありません。削除することをお勧めしますか?
Mark Amery

1

カーソルとメニューの両方を無効にするには、次の2つのメソッドでサブクラスを使用します。

- (CGRect)caretRectForPosition:(UITextPosition *)position {
    return CGRectZero;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    [UIMenuController sharedMenuController].menuVisible = NO;
    self.selectedTextRange = nil;

    return NO;
}

0

私は単にサブクラス化しUITextFieldlayoutSubviews次のようにオーバーライドします。

- (void)layoutSubviews
{
    [super layoutSubviews];
    for (UIView *v in self.subviews)
    {
        if ([[[v class] description] rangeOfString:@"UITextSelectionView"].location != NSNotFound)
        {
            v.hidden = YES;
        }
    }
}

これは汚いハックであり、将来は失敗する可能性があります(その時点でカーソルは再び表示されます-アプリはクラッシュしません)が、機能します。


-1

関連するオブジェクトを介して、カテゴリにBOOL cursorlessプロパティを追加できUITextFieldます。

@interface UITextField (Cursorless)

@property (nonatomic, assign) BOOL cursorless;

@end

次に、メソッドswizzlingを使用して、を使用してとデフォルト値をcaretRectForPosition:切り替えるメソッドでスウィズルしCGRectZeroますcursorless

これにより、ドロップインカテゴリを介したシンプルなインターフェイスが実現します。これは、次のファイルで示されています。

それらをドロップするだけで、このシンプルなインターフェースのメリットを享受できます

UITextFieldカテゴリ:https : //github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless.h https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless .m

メソッドのスウィズリング:https : //github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.h https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject% 2BRXRuntimeAdditions.m


非常に多くのレベルでの悪い解決策!初心者向け:カテゴリ内のメソッドをオーバーライドしないでください。あなたが本当にそれを本当に必要としない限り、メソッドスウィズリングを避けてください(他の人はこの質問に対する良い解決策を考え出しました)。コードが非常に複雑になります。
EsbenB 2014

実際にコードを見ると、カテゴリでメソッドがオーバーライドされておらず、メソッドのスウィズリングが正しく実装されていることがわかります。私は何年もこの実装を確実に使用してきました。
Awesome-o

また、継続的に繰り返される問題を永続的に解決するために、150行以下の独立したコードベースを追加することの複雑さについて説明してください。これはコードベースを複雑にするだけでなく、可能な限りシンプルなインターフェースを提供します。機能を指示する単一のブール値。
Awesome-o

スウィズル方法については、この優れた議論を見てとるstackoverflow.com/questions/5339276/...をデバッグに特にを。メソッドのスウィズリングは素晴らしい機能ですが、IMHOは必要な場合にのみ使用してください。この問題は、ここで提供される提案の1つを使用して簡単に解決でき、他のプログラマーが保守および読み取りしやすいコードを提供します。
EsbenB 2014

私は以前にそれを読んだことがあり、正確さのために私の実装ではすべての概説されたガイドラインに従いました。おそらく、これはメソッドのスウィズリングが勝ったときの確かな例です。これは、基本的なライブラリがプラットフォーム間で広く必要とされている機能を簡単な方法で実装できない、孤立した、しかし一般的なケースです。提案されている他の例は、カーソルのないテキストフィールドを意味的に定義するものではなく、カーソルのフレームまたは色の難読化を通じてのみ実行します。新しいプログラマーにとって、このインターフェースは最も読みやすく、期待されていることを正確に実行します。
Awesome-o
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.