UITextField의 커서를 숨 깁니다.


137

내가 사용하고 UITextFieldUIPickerView의에 대한 inputView그래서 사용자가 텍스트 필드를 탭하면 선택기 그들을 위해 소환되는 것을에서 옵션을 선택합니다.

거의 모든 것이 작동하지만 한 가지 문제가 있습니다. 사용자가 필드에 입력 할 것으로 예상되지 않고 키보드가 표시되지 않기 때문에 커서가 여전히 활성화되어있을 때 커서가 여전히 텍스트 필드에서 깜박입니다. 텍스트 필드에서 설정 editing하고 NO터치를 추적하거나 사용자 정의 스타일 버튼으로 바꾸고 코드를 통해 선택기를 소환하여 해킹 할 수 있다는 것을 알고 있습니다. 그러나 UITextFieldDelegate텍스트 필드의 모든 이벤트 처리에 메소드 를 사용 하고 텍스트 필드를 버튼으로 바꾸는 것과 같은 해킹은이 접근법을 허용하지 않습니다.

UITextField대신 커서를 어떻게 숨길 수 있습니까?

답변:


277

UITextField를 서브 클래 싱하고 caretRectForPosition을 재정의하기 만하면됩니다.

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

2
아름다운! 나를 위해 매력처럼 작동합니다.
Joe Strout

1
@Joseph Chiu 잘 작동합니다. 그러나 iOS 4.3에서는 그렇지 않습니다. 이것 좀 도와 주실 래요?
Dinesh Raja

이중 upvote에 가치가 가장 깨끗하고 가장 짧은 방법 =)
케르 Baltaci

1
그냥 참고하십시오. 내 하위 클래스에서 부울 hideCaret을 추가 한 다음이 재정의에서 true-> CGRectZero를 반환하면 super의 결과를 반환합니다.
WCByrne

6
외부 키보드를 사용하는 사용자는 커서가 숨겨져 있고 선택기보기를 사용하더라도 텍스트 필드의 값을 변경할 수 있습니다.
Mark

156

iOS 7부터는 tintColor = [UIColor clearColor]textField를 설정 하면 캐럿이 사라집니다.


1
이것은 현재 작동하지만 향후 변경 될 수 있으므로 사용하지 않는 것이 좋습니다. 대신 caretRectForPosition:재정의 솔루션을 선택하십시오 .
lipka

@lipka 사실, 아마도 더 좋은 방법 일 것입니다.
jamone

2
지금은 충분합니다. 때로는 빠른 해결책이 필요할 때가 있습니다.
GoldenJoe

이것은 가장 쉬운 해결책입니다!
Jay Q.

1
이 답변은 7 + iOS 용 승인을 받아야한다
트립

95

텍스트 필드의 색조를 지울 수 있습니다.

self.textField.tintColor = [UIColor clearColor];

스위프트 3.0

self.textField.tintColor = .clear

여기에 이미지 설명을 입력하십시오


가장 쉬운 답변.
Nik Kov

2
위에서 언급했듯이 색조 색상을 지우더라도 외부 키보드 (iPad Pro)를 사용하는 사용자가 텍스트를 변경하는 것을 막을 수는 없습니다.
Michael Long

@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

캐럿 숨기기 해제

캐럿 숨기기를 해제하는 두 가지 방법이 있습니다.

  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 2018 년

그렇다면 iOS 문서에서 다음과 같이 말하기 때문에 bugreport.apple.com에 버그를 신고 해야합니다 . "텍스트 범위에 길이가 있으면 현재 선택된 텍스트를 나타냅니다. 길이가 0이면 캐럿 (삽입)을 나타냅니다 텍스트 범위 개체가 nil이면 현재 선택이 없음을 나타냅니다. "
ma11hew28

4
보고서를 제출할만큼 신경 쓰지 않습니다. 다른 사람들이 귀하의 "솔루션"을 사용하고 작동하지 않는 경우 그들이 혼자가 아니라는 것을 알고 싶어했습니다.
Art Geigel 2018 년

@ArtGeigel의 의견에도 불구하고 이것은 완벽하게 작동합니다. 그러나 재정의와 관련된 솔루션을 선호합니다 caretRectForPosition. 그것은 무엇을하고 있는지보다 명확하며 인용 한 문서는 현재 선택이 없을 때 캐럿의 동작이 무엇인지 명확하지 않습니다. 이것이 작동하지 않는다고 @ArtGeigel의 주장이 정확하다면 (적어도 내가 알 수있는 한은 아닙니다) 그것이 버그인지 명확하지 않을 것입니다.
Mark Amery

나에게도 효과가 없었습니다. 캐럿이 여전히 있고 깜박입니다.
CW0007007

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

2
@BreadicalMD 내가 볼 수있는 가장 큰 문제는 UITextFieldDelegate시작 및 종료 편집 이벤트를 처리하기 위해 with를 사용할 수 없다는 것 입니다. 대신-내가 알지 못하는 이벤트를 처리 할 수있는 방법이 없다면 버튼 서브 클래스 를 재정의 becomeFirstResponder하고 resignFirstResponder자신의 델리게이트 프로토콜을 만들고 delegate속성을 추가 한 다음 위에서 언급 한 것에서 델리게이트를 호출해야합니다. 행동 양식. 이것은 서브 클래스 caretRectForPosition에서 재정의 하는 것보다 훨씬 많은 작업 UITextField입니다.
Mark Amery

1
@BreadicalMD 즉, Joseph Chiu의 대답이 실제적인 관점에서 우수 함에도 불구하고, 나는 이것이 여전히 섹시하다는 것에 여전히 동의합니다. 나는 UIResponder이전에 클래스 참조를 주의 깊게 보지 않았으며 , 이와 같은 트릭이 가능하다는 것을 전혀 몰랐습니다.
Mark Amery 22.19에

파티에 늦었지만 이것이 매우 좋은 해결책이라고 생각 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. Fdez

3

tintColor를 Clear Color로 설정하십시오

textfield.tintColor = [UIColor clearColor];

인터페이스 빌더에서 설정할 수도 있습니다


2
방금 2 년 전에 답변을 복사했습니다.
Ashley Mills

1
친구 미안하지만 아무 것도 복사하지 않았습니다.
Ahmad Al-Attal

4
재미 있어요, "나의 친구" 귀하의 답변은 15 년 5 월 1 일의 @oldman의 답변과 거의 비슷해 보입니다. 당신이 어떻게 다른지 말해 주실 수 있습니까?
Ashley Mills

1
위에서 언급했듯이 색조 색상을 지우더라도 외부 키보드 (iPad Pro)를 사용하는 사용자가 텍스트를 변경하는 것을 막을 수는 없습니다.
Michael Long

프로 사용자는 자신이 원하는 것을 할 수 있습니다. 그들은 전문가입니다 : 그들은 그들이하고있는 일을 알고 있습니다; ^)
Anton Tropashko

2

커서를 숨기려면 쉽게 사용할 수 있습니다! 그것은 나를 위해 일했다 ..

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

3
내가 아는 한 이것은 문서화되어 있지 않습니다. 앱 스토어에 제출하면 개인 API 호출에 대해 앱을 거부 할 수 있지만,이 방법을 사용하여 그 추론을 테스트하는 제출 내용은 알 수 없습니다. 서브 클래스 화 없이이 문제를 해결할 수 있기 때문에 유감입니다.이 답변을 통해 가능합니다.
Mark Amery

1

OP에서 제공 한 답변으로, 질문 본문에서 복사하여 답변이없는 질문의 끝을 정리하는 데 도움이됩니다.

나는 올바른 해결책을 가지고 있다고 생각하지만 개선 될 수 있다면 환영받을 것입니다 :) 글쎄, UITextField의 하위 클래스를 만들고 경계에 대한 CGRect를 반환하는 메서드를 재정의했습니다.

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

문제? rect가 0이므로 텍스트가 표시되지 않습니다. 그러나 컨트롤의 하위보기로 UILabel을 추가하고 setText 메소드를 재정의했습니다. 그래서 평소와 같이 텍스트를 입력 할 때 텍스트 필드 텍스트는 nil이며 텍스트를 표시하는 레이블입니다

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

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

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

이것으로 예상대로 작동합니다. 그것을 향상시킬 방법을 알고 있습니까?


이 대답은 Joseph Chiu의 대체 접근법이 매우 유사하지만 훨씬 간단하다는 점을 감안할 때 기본적으로 가치가 없습니다. 그냥 삭제하는 것이 좋습니다?
Mark Amery 22.39에

1

커서와 메뉴를 비활성화하려면 다음 두 가지 방법으로 하위 클래스를 사용하십시오.

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

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

    return NO;
}

0

나는 단순히 서브 클래스 UITextField를 만들고 layoutSubviews다음과 같이 재정의 합니다.

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

그런 다음 메소드 스위 즐링을 사용하여 및를 사용하여 기본값 caretRectForPosition:을 전환하는 메소드 로 스위 즐하십시오 .CGRectZerocursorless

이는 드롭 인 범주를 통한 간단한 인터페이스로 이어집니다. 이것은 다음 파일에서 설명됩니다.

간단히 삽입하여이 간단한 인터페이스의 이점을 누리십시오.

UITextField카테고리 : https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless.h https://github.com/rexmas/RexDK/blob/master/RexDK/UI/UITextField%2BRXCursorless .미디엄

스위블 방식 : https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject%2BRXRuntimeAdditions.h https://github.com/rexmas/RexDK/blob/master/RexDK/Foundation/NSObject% 2BRXRuntimeAdditions.m


너무 많은 수준에서 나쁜 해결책! 우선 : 범주의 메소드를 대체하지 마십시오. 당신이 정말로 필요로하지 않는 한, 메소드 Swizziling을 피하십시오 (다른 사람들은이 질문에 대한 좋은 해결책을 제시했습니다). 코드를 훨씬 더 복잡하게 만듭니다.
EsbenB

실제로 코드를 살펴보면 범주에서 메소드를 재정의하지 않고 메소드 스위 즐링이 올바르게 구현되었음을 알 수 있습니다. 필자는 수년 동안이 구현을 사용해 왔습니다.
Awesome-o

또한 지속적으로 반복되는 문제를 영구적으로 해결하기 위해 ~ 150 줄의 분리 된 코드베이스를 추가하는 것이 복잡한 점을 설명하십시오. 이것은 코드베이스를 복잡하게 할뿐만 아니라 가장 간단한 인터페이스를 제공합니다. 기능을 지시하는 단일 부울
Awesome-o

특히 스위블에 관한 방법 스위 즐링 stackoverflow.com/questions/5339276 / ... 에 대한이 훌륭한 토론을 살펴보십시오 . 메소드 스위 즐링은 놀라운 기능이지만 IMHO는 필요할 때만 사용해야합니다. 이 문제는 여기에 제공된 제안 중 하나를 사용하여 쉽게 해결할 수 있으며 다른 프로그래머가 쉽게 유지 관리하고 읽을 수있는 코드를 제공합니다.
EsbenB

나는 그것을 읽었으며 정확성에 대한 구현의 모든 개요 지침을 따랐습니다. 아마도 이것은 방법 스위 즐링이 승리했을 때의 확실한 예입니다. 기본 라이브러리가 간단한 방법으로 플랫폼에서 광범위하게 필요한 기능을 구현하지 못하는 격리 된, 일반적인 사례입니다. 제안 된 다른 예제는 커서없는 텍스트 필드를 의미 적으로 정의하지 않으며 커서의 프레임 또는 색상을 난독 화하여 만 수행합니다. 새로운 프로그래머에게는이 인터페이스가 가장 읽기 쉽고 예상 한대로 작동합니다.
Awesome-o
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.