문제

나는있다 UITextView 내 IOS 응용 프로그램에서 많은 양의 텍스트를 표시합니다.

그런 다음 오프셋 마진 매개 변수를 사용 하여이 텍스트를 페이징합니다. UITextView.

내 문제는 UITextView 내가 사용하는 글꼴 크기와 서체에 따라 다른 것처럼 보이므로 계산을 혼동하고 있습니다.

그러므로 나는 질문을 제기한다 : UITextView?

귀하의 답변을 듣기를 기대합니다!

도움이 되었습니까?

해결책

2019 년 최신

iOS에서 가장 칙칙한 버그 중 하나입니다.

아래 수업, UITextViewFixed 일반적으로 합리적인 솔루션입니다.

수업은 다음과 같습니다.

@IBDesignable class UITextViewFixed: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    func setup() {
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0
    }
}

검사관에서 스크롤레인을 끄는 것을 잊지 마십시오!

  1. 솔루션은 스토리 보드에서 제대로 작동합니다

  2. 솔루션은 런타임에 올바르게 작동합니다

그게 다야, 끝났어.

일반적으로 그것은 대부분의 경우 필요한 전부입니다.

텍스트보기의 높이를 즉시 변경하더라도 일반적으로 필요한 모든 기능을 수행합니다.

(즉석에서 높이를 바꾸는 일반적인 예는 사용자 유형으로 변경하는 것입니다.)

Apple의 깨진 UitextView는 다음과 같습니다.

screenshot of IB with UITextView

여기에 있습니다 UITextViewFixed:

screenshot of IB with UITextViewFixed

물론 당신은해야합니다

검사관에서 스크러버링을 끄십시오!

Scrollenabled를 끄는 것을 잊지 마십시오! :)


몇 가지 추가 문제

(1) 일부 비정상적인 경우 - 예를 들어, 동적으로 변화하는 높이가있는 유연한 셀 높이 테이블 뷰의 경우 - 애플은 기괴한 일을한다. 그들은 바닥에 추가 공간을 추가합니다. 아니, 정말! 이것은 iOS에서 가장 분노한 것 중 하나 여야합니다.

다음은 추가 할 "빠른 수정"이 있으며, 이는 일반적으로 그 광기에 도움이됩니다.

...
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0

        // this is not ideal, but you can sometimes use this
        // to fix the "extra space at the bottom" insanity
        var b = bounds
        let h = sizeThatFits(CGSize(
           width: bounds.size.width,
           height: CGFloat.greatestFiniteMagnitude)
       ).height
       b.size.height = h
       bounds = b
 ...

(2) 때때로, 또 다른 미묘한 Apple 엉망을 해결하려면 다음을 추가해야합니다.

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
    super.setContentOffset(contentOffset, animated: false)
}

(3) 논란의 여지가 있습니다 ~해야 한다 추가 중 :

contentInset = UIEdgeInsets.zero

직후 .lineFragmentPadding = 0 안에 UITextViewFixed .

그러나 ... 믿거 나 말거나 ... 그냥 작동하지 않습니다 현재 iOS에서! (2019 년에 확인되었습니다.) 향후 그 라인을 추가해야 할 수도 있습니다.

사실 그 UITextView iOS에서 깨졌습니다. 모든 모바일 컴퓨팅에서 가장 이상한 것 중 하나입니다. 이 질문의 10 주년을 기념하고 여전히 고정되어 있지 않습니다!

마지막으로, 여기에 텍스트와 다소 비슷한 팁이 있습니다.필드: https://stackoverflow.com/a/43099816/294884

다른 팁

iOS 7.0의 경우 ContentInset 트릭이 더 이상 작동하지 않는다는 것을 알았습니다. 이것은 iOS 7에서 마진/패딩을 제거하는 데 사용한 코드입니다.

텍스트의 왼쪽 가장자리를 컨테이너의 왼쪽 가장자리에 가져옵니다.

textView.textContainer.lineFragmentPadding = 0

이로 인해 텍스트 상단이 컨테이너 상단과 일치하게됩니다.

textView.textContainerInset = .zero

마진/패딩을 완전히 제거하려면 두 줄 모두 필요합니다.

이 해결 방법은 iOS 3.0이 출시 된 2009 년에 작성되었습니다. 더 이상 적용되지 않습니다.

나는 똑같은 문제에 부딪쳤다. 결국 나는 사용해야했다.

nameField.contentInset = UIEdgeInsetsMake(-4,-8,0,0);

여기서 Namefield는 a UITextView. 내가 사용했던 글꼴은 Helvetica 16 포인트였습니다. 내가 그리는 특정 필드 크기에 대한 맞춤형 솔루션입니다. 이렇게하면 왼쪽 오프셋이 왼쪽과 함께 플러시되고 상단 오프셋이 상자를 드는 곳에 위치합니다.

또한 이것은 적용되는 것 같습니다 UITextViews 기본 Aligment를 사용하는 곳 (즉).

nameField.textAlignment = NSTextAlignmentLeft;

예를 들어 오른쪽에 정렬됩니다 UIEdgeInsetsMake 오른쪽 가장자리에 전혀 영향을 미치지 않는 것 같습니다.

최소한 .Contentinset 속성을 사용하면 필드를 "올바른"위치에 배치하고 귀하의 필드를 상쇄하지 않고 편차를 수용 할 수 있습니다. UITextViews.

이미 주어진 좋은 답변 중 일부를 구축하면 여기에 사용자 정의 런타임 속성을 사용하고 iOS 7.0+에서 작동하는 순수한 인터페이스 빌더 기반 솔루션이 있습니다.

enter image description here

iOS 5 UIEdgeInsetsMake(-8,-8,-8,-8); 잘 작동하는 것 같습니다.

실제 마진이 사용자 글꼴 크기 설정 등으로 변경 될 수 있으므로 하드 코딩 된 값과 관련된 답변을 확실히 피할 수 있습니다.

다음은 @user1687195의 답변입니다. textContainer.lineFragmentPadding (때문에 문서 상태 이것은 의도 된 사용법이 아닙니다).

이것은 iOS 7 이후에 적합합니다.

self.textView.textContainerInset = UIEdgeInsetsMake(
                                      0, 
                                      -self.textView.textContainer.lineFragmentPadding, 
                                      0, 
                                      -self.textView.textContainer.lineFragmentPadding);

이것은 효과적으로 동일한 결과이며, 라인 프레이트 패딩 속성을 오용하지 않는다는 점에서 약간 더 깨끗합니다.

사용자 정의 런타임 속성을 사용하여 스토리 보드 또는 인터페이스 빌더 솔루션.업데이트. ContentInset = {{-10, -5}, {0, 0}}을 가진 iOS7.1 & iOS6.1 스크린 샷이 추가되었습니다.enter image description here enter image description here

이 모든 답변은 제목 질문을 다루지 만 OP의 질문 본문에 제시된 문제에 대한 몇 가지 솔루션을 제안하고 싶었습니다.

텍스트 내용의 크기

내부의 텍스트 크기를 계산하는 빠른 방법 UITextView 사용하는 것입니다 NSLayoutManager:

UITextView *textView;
CGSize textSize = [textView usedRectForTextContainer:textView.textContainer].size;

이것은 총 스크롤 가능한 컨텐츠를 제공하며, 이는 UITextView의 프레임. 나는 이것이 훨씬 더 정확하다는 것을 알았다 textView.contentSize 실제로 텍스트가 얼마나 많은 공간을 차지하는지 계산하기 때문입니다. 예를 들어, 빈 공간이 주어집니다 UITextView:

textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)

라인 높이

UIFont 주어진 글꼴의 라인 높이를 빠르게 얻을 수있는 속성이 있습니다. 그래서 당신은 당신의 텍스트의 선 높이를 빠르게 찾을 수 있습니다. UITextView 와 함께:

UITextView *textView;
CGFloat lineHeight = textView.font.lineHeight;

가시 텍스트 크기 계산

실제로 보이는 텍스트의 양을 결정하는 것은 "페이징"효과를 처리하는 데 중요합니다. UITextView 호텔이 있습니다 textContainerInset 실제로 실제 사이의 마진입니다 UITextView.frame 그리고 텍스트 자체. 가시 프레임의 실제 높이를 계산하려면 다음 계산을 수행 할 수 있습니다.

UITextView *textView;
CGFloat textViewHeight = textView.frame.size.height;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textHeight = textViewHeight - textInsets.top - textInsets.bottom;

페이징 크기 결정

마지막으로, 눈에 보이는 텍스트 크기와 컨텐츠가 있으므로, 차수를 빼면 오프셋이 무엇인지 빠르게 결정할 수 있습니다. textHeight ~로부터 textSize:

// where n is the page number you want
CGFloat pageOffsetY = textSize - textHeight * (n - 1);
textView.contentOffset = CGPointMake(textView.contentOffset.x, pageOffsetY);

// examples
CGFloat page1Offset = 0;
CGFloat page2Offset = textSize - textHeight
CGFloat page3Offset = textSize - textHeight * 2

이 모든 방법을 사용하여 삽입되지 않았으며 Caret 또는 내가 원하는 텍스트의 어디에서나 갈 수있었습니다.

당신이 사용할 수있는 textContainerInset 의 자산 UITextView:

TextView.textContainerInset = uiedgeinsetsmake (10, 10, 10, 10);

(위 왼쪽 아래 오른쪽)

iOS 10의 경우 다음 줄은 상단 및 하단 패딩 제거에 대해 작동합니다.

captionTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)

다음은 Fattie의 매우 유용한 답변의 업데이트 버전입니다. iOS 10과 11에서 완벽한 레이아웃을 얻는 데 도움이되는 2 개의 매우 중요한 라인을 추가합니다 (아마도 낮은 것도).

@IBDesignable class UITextViewFixed: UITextView {
    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }
    func setup() {
        translatesAutoresizingMaskIntoConstraints = true
        textContainerInset = UIEdgeInsets.zero
        textContainer.lineFragmentPadding = 0
        translatesAutoresizingMaskIntoConstraints = false
    }
}

중요한 선은 두 가지입니다 translatesAutoresizingMaskIntoConstraints = <true/false> 진술!

놀랍게도 모든 마진을 제거합니다 내 모든 상황에서!

동안 textView 첫 번째 응답자가 아닙니다. sizeThatFits 허용 된 답변에 언급 된 방법.
TextView를 탭핑 할 때 갑자기 이상한 바닥 여백이 사라지고 모든 것이 그렇게 보였지만 TextView가 얻은 즉시 firstResponder.

그래서 나는 읽었다 여기에 그것을 가능하게하고 비활성화합니다 translatesAutoresizingMaskIntoConstraints 통화 사이에 프레임/바운드를 수동으로 설정할 때 도움이됩니다.

다행히도 이것은 프레임 설정뿐만 아니라 2 줄에서 작동합니다. setup() 둘 사이에 샌드위치 translatesAutoresizingMaskIntoConstraints 전화!

이것은 예를 들어입니다 매우 도움이됩니다 보기 프레임을 계산할 때 사용 systemLayoutSizeFitting a UIView. 올바른 크기를 돌려줍니다 (이전에는하지 않은)!

언급 된 원래 답변에서와 같이 :
검사관에서 스크롤레인을 끄는 것을 잊지 마십시오!
이 솔루션은 런타임뿐만 아니라 스토리 보드에서 제대로 작동합니다.

그게 다야 진짜 완료!

최신 스위프트 :

self.textView.textContainerInset = .init(top: -2, left: 0, bottom: 0, right: 0)
self.textView.textContainer.lineFragmentPadding = 0

Swift 4의 경우 Xcode 9

다음 함수를 사용하면 uitextView에서 텍스트의 마진/패딩을 변경할 수 있습니다.

Public Func Uiedgeinsetsmake (_ Top : CGFloat, _ Left : CGFLOAT, _ 하단 : CGFLOAT, _ 오른쪽 : CGFLOAT) -> uiedgeinsets

이 경우에

 self.textView?.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)

삽입 된 솔루션을 수행하면 여전히 오른쪽과 바닥에 패딩이있었습니다. 또한 텍스트 정렬이 문제를 일으켰습니다. 내가 찾은 유일한 파이어 방식은 텍스트보기를 다른 뷰 안에 바운드에 잘게하는 것이 었습니다.

다음은 앱의 모든 텍스트보기에서 Apple의 기본 마진을 제거하는 쉬운 작은 확장 기능입니다.

참고 : 인터페이스 빌더는 여전히 이전 마진을 표시하지만 앱은 예상대로 작동합니다.

extension UITextView {

   open override func awakeFromNib() {
      super.awakeFromNib();
      removeMargins();
   }

   /** Removes the Apple textview margins. */
   public func removeMargins() {
      self.contentInset = UIEdgeInsetsMake(
         0, -textContainer.lineFragmentPadding,
         0, -textContainer.lineFragmentPadding);
   }
}

나를 위해 (iOS 11 & Xcode 9.4.1) 마술처럼 일한 것은 TextView.font 속성을 설정하는 것이 었습니다. UIFont.preferred(forTextStyle:UIFontTextStyle) @fattie가 언급 한 스타일과 첫 번째 답변. 그러나 @fattie 답변은 TextView.Font 속성을 설정할 때까지 작동하지 않았습니다. 그렇지 않으면 uitextView는 계속 행동합니다.

최신 스위프트 버전을 찾는 사람이라면 아래 코드가 잘 작동합니다. Xcode 10.2 그리고 스위프트 4.2

yourTextView.textContainerInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

UitextView의 서브 뷰에서 텍스트로보기를 얻고 서브 클래스의 레이아웃 서브 뷰 메소드로 설정하는 방법이 하나 더 발견되었습니다.

- (void)layoutSubviews {
    [super layoutSubviews];

    const int textViewIndex = 1;
    UIView *textView = [self.subviews objectAtIndex:textViewIndex];
    textView.frame = CGRectMake(
                                 kStatusViewContentOffset,
                                 0.0f,
                                 self.bounds.size.width - (2.0f * kStatusViewContentOffset),
                                 self.bounds.size.height - kStatusViewContentOffset);
}

TextView 스크롤은 또한 텍스트의 위치에 영향을 미치고 수직 중심이 아닌 것처럼 보이게합니다. 스크롤을 비활성화하고 상단 삽입물을 0으로 설정하여보기의 텍스트 중앙을 중심으로했습니다.

    textView.scrollEnabled = NO;
    textView.textContainerInset = UIEdgeInsetsMake(0, textView.textContainerInset.left, textView.textContainerInset.bottom, textView.textContainerInset.right);

어떤 이유로 든 아직 알아 내지 못했습니다. 유형이 시작되기 전에 커서가 여전히 중앙에 있지 않지만 타이핑을 시작할 때 즉시 텍스트 중심이 중심입니다.

[firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top