ProgramingTip

UITextview의 줄 수 제한

bestdevel 2020. 11. 12. 19:27
반응형

UITextview의 줄 수 제한


UITextField를 편집 할 때 사용자가 입력 할 수있는 LINES (다른 질문에서 필요한 문자가 아님)의 양을 제한하는 방법이 궁금합니다.

이상적으로는 입력을 최대로 제한하고 싶습니다. 10 줄.

어디서부터 시작해야합니까? 방법 으로이 작업을 수행합니까?

 - (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView

당신은 올바른 생각을 가지고 잘못된 방법을 가지고 있습니다. textView:shouldChangeTextInRange:replacementText:텍스트가 변경 될 때마다 호출됩니다. text속성을 사용하여 텍스트보기의 현재 콘텐츠에 액세스 할 수있는 전달 된 범위에서 새 콘텐츠를 구성하고 [textView.text stringByReplacingCharactersInRange:range withString:replacementText]. 그런 다음 줄 수를 세고 YES를 반환하여 변경을 허용하거나 NO를 반환하여 거부 할 수 있습니다.


Maciek Czarnik 답변은 저에게 효과가 없었지만 어떻게 해야할지를 얻었습니다.

iOS 7 이상

빠른

textView.textContainer.maximumNumberOfLines = 10
textView.textContainer.lineBreakMode = .byTruncatingTail

ObjC

textView.textContainer.maximumNumberOfLines = 10;
textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;

도움이 될 수 있습니다 (iOS 7 이상) :

textView.textContainer.maximumNumberOfLines = 10;
[textView.layoutManager textContainerChangedGeometry:textView.textContainer];

첫 번째 줄조차도 내가 생각하는 것입니다 ... 아마도 SDK의 버그 일 수 있습니다.


Maciek Czarnik의 대답은 iOS7에서 작동하지 않는 것입니다. 그것은 나에게 이상한 행동을했는지, 이유를 모르겠습니다.

UITextView에서 줄 수를 제한하기 위해 수행하는 작업은 간단합니다.

(iOS7에서만 테스트 됨) 다음 UITextViewDelegate 메서드에서 :

- (void)textViewDidChange:(UITextView *)textView
{
    NSUInteger maxNumberOfLines = 5;
    NSUInteger numLines = textView.contentSize.height/textView.font.lineHeight;
    if (numLines > maxNumberOfLines)
    {
        textView.text = [textView.text substringToIndex:textView.text.length - 1];
    }
}

Swift 3.0버전 :

self.textView.textContainer.maximumNumberOfLines = self.textViewNumberOflines
self.textView.textContainer.lineBreakMode = .byTruncatingTail

Swift 4.2 / Swift 5

에서 Numereyes 답변의 개선 된 버전이 있습니다.

코드를 추가 할 수 약간의 확장을했습니다. While-Loop을 사용하고 있습니다. 이 사용자가 한 번에 많은 텍스트를 넣을 때도 작동합니다.

extension UITextView {        
    var numberOfCurrentlyDisplayedLines: Int {
        let size = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        //for Swift <=4.0, replace with next line:
        //let size = systemLayoutSizeFitting(UILayoutFittingCompressedSize)

        return Int(((size.height - layoutMargins.top - layoutMargins.bottom) / font!.lineHeight))
    }

    /// Removes last characters until the given max. number of lines is reached
    func removeTextUntilSatisfying(maxNumberOfLines: Int) {
        while numberOfCurrentlyDisplayedLines > (maxNumberOfLines) {
            text = String(text.dropLast())
            layoutIfNeeded()
        }
    }
}

// Use it in UITextView's delegate method:
func textViewDidChange(_ textView: UITextView) {        
    textView.removeTextUntilSatisfying(maxNumberOfLines: 10)
}        

주어진 다른 솔루션은 마지막에 생성되는 마지막 줄 (질문의 경우 11 번째 줄)과 관련된 문제를 해결하지 않습니다.

다음은 Swift 4.0& Xcode 9.0 베타 에서 작동하는 솔루션입니다 ( 이 블로그 게시물 에서 찾았 습니다 ).

   class ViewController: UIViewController, UITextViewDelegate {

      @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        textView.textContainer.maximumNumberOfLines = 10
        textView.textContainer.lineBreakMode = .byWordWrapping
      }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

        let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
        let newLines = text.components(separatedBy: CharacterSet.newlines)
        let linesAfterChange = existingLines.count + newLines.count - 1

        return linesAfterChange <= textView.textContainer.maximumNumberOfLines
    }

참고 : 이 솔루션은 마지막 줄이 표시하기에 너무 긴 시나리오를 처리하지 않습니다 (텍스트가 UITextView의 맨 오른쪽에 숨겨 짐).


다른 답변과 비슷하지만 Storyboard에서 직접 사용할 수 있으며 하위 클래스를 만들지 않습니다.

extension UITextView {
    @IBInspectable var maxNumberOfLines: NSInteger {
        set {
            textContainer.maximumNumberOfLines = maxNumberOfLines
        }
        get {
            return textContainer.maximumNumberOfLines
        }
    }
    @IBInspectable var lineBreakByTruncatingTail: Bool {
        set {
            if lineBreakByTruncatingTail {
                textContainer.lineBreakMode = .byTruncatingTail
            }
        }
        get {
            return textContainer.lineBreakMode == .byTruncatingTail
        }
    }
}

신속한 4의 경우 이것은 버그없이 작동했습니다.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
    let newLines = text.components(separatedBy: CharacterSet.newlines)
    let linesAfterChange = existingLines.count + newLines.count - 1
    return linesAfterChange <= textView.textContainer.maximumNumberOfLines
}

문자를 제한하려는 경우 :

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        let existingLines = textView.text.components(separatedBy: CharacterSet.newlines)
        let newLines = text.components(separatedBy: CharacterSet.newlines)
        let linesAfterChange = existingLines.count + newLines.count - 1
        if(text == "\n") {
            return linesAfterChange <= textView.textContainer.maximumNumberOfLines
        }

        let newText = (textView.text as NSString).replacingCharacters(in: range, with: text)
        let numberOfChars = newText.count
        return numberOfChars <= 30 // 30 characters limit
    }
}

제한을 설정할 줄 수를 추가하는 것을 잊지 마십시오 viewDidLoad.

txtView.textContainer.maximumNumberOfLines = 2

참고 URL : https://stackoverflow.com/questions/5225763/limit-the-number-of-lines-for-uitextview

반응형