UITextView ที่ขยายเป็นข้อความโดยใช้เค้าโครงอัตโนมัติ


163

ฉันมีมุมมองที่จัดวางอย่างสมบูรณ์โดยใช้การจัดวางอัตโนมัติโดยทางโปรแกรม ฉันมี UITextView ตรงกลางของมุมมองพร้อมรายการด้านบนและด้านล่าง ทุกอย่างทำงานได้ดี แต่ฉันต้องการขยาย UITextView เมื่อเพิ่มข้อความ สิ่งนี้ควรผลักทุกอย่างลงไปด้านล่างขณะที่ขยาย

ฉันรู้วิธีการทำสิ่งนี้ด้วยวิธี "สปริงและเสา" แต่มีวิธีเลย์เอาต์อัตโนมัติในการทำสิ่งนี้หรือไม่? วิธีเดียวที่ฉันคิดได้คือการลบและเพิ่มข้อ จำกัด ใหม่ทุกครั้งที่ต้องการเติบโต


5
คุณสามารถสร้าง IBOutlet ให้เป็นข้อจำกัดความสูงสำหรับมุมมองข้อความและเพียงแค่ปรับเปลี่ยนค่าคงที่เมื่อคุณต้องการที่จะเติบโตไม่จำเป็นต้องลบและเพิ่ม
rdelmar

4
2017 เคล็ดลับที่มักจะทำให้คุณ หงุดหงิด: มันทำงานได้ถ้าคุณตั้งค่าหลังจาก VIEWDID> ปรากฏขึ้น <มันน่าผิดหวังมากถ้าคุณตั้งค่าข้อความที่ ViewDidLoad - มันจะไม่ทำงาน!
Fattie

2
เคล็ดลับ No2: ถ้าคุณเรียกใช้ [someView.superView layoutIfNeeded] จากนั้นอาจใช้งานได้ใน viewWillAppear ();)
Yaro

คำตอบ:


30

มุมมองที่มี UITextView จะถูกกำหนดขนาดด้วยsetBoundsAutoLayout ดังนั้นนี่คือสิ่งที่ฉันทำ ในตอนแรกผู้บังคับบัญชาได้ตั้งค่าข้อ จำกัด อื่น ๆ ทั้งหมดตามที่ควรจะเป็นและท้ายที่สุดฉันวางข้อ จำกัด พิเศษหนึ่งข้อสำหรับความสูงของ UITextView และฉันบันทึกไว้ในตัวแปรอินสแตนซ์

_descriptionHeightConstraint = [NSLayoutConstraint constraintWithItem:_descriptionTextView
                                 attribute:NSLayoutAttributeHeight 
                                 relatedBy:NSLayoutRelationEqual 
                                    toItem:nil 
                                 attribute:NSLayoutAttributeNotAnAttribute 
                                multiplier:0.f 
                                 constant:100];

[self addConstraint:_descriptionHeightConstraint];

ในsetBoundsวิธีการนั้นฉันเปลี่ยนค่าคงที่

-(void) setBounds:(CGRect)bounds
{
    [super setBounds:bounds];

    _descriptionTextView.frame = bounds;
    CGSize descriptionSize = _descriptionTextView.contentSize;

    [_descriptionHeightConstraint setConstant:descriptionSize.height];

    [self layoutIfNeeded];
}

4
คุณสามารถอัปเดตข้อ จำกัด ใน 'textViewDidChange:' ของ UITextViewDelegate
LK__

2
ทางออกที่ดี โปรดทราบว่าคุณสามารถสร้างข้อ จำกัด ในตัวสร้างส่วนต่อประสานและเชื่อมต่อโดยใช้เต้าเสียบ ร่วมกับการใช้textViewDidChangeนี้ควรบันทึกความยุ่งยากบาง subclassing และการเขียนรหัส ...
บ๊อบ Vork

3
โปรดทราบว่าtextViewDidChange:จะไม่ถูกเรียกเมื่อเพิ่มข้อความไปยัง UITextView โดยทางโปรแกรม
wanderlust

@BobVork ข้อเสนอแนะทำงานได้ดี XCODE 11 / iOS13 ตั้งค่าข้อ จำกัด คงที่เมื่อตั้งค่ามุมมองข้อความใน viewWillAppear และอัปเดตใน textViewDidChange
ptc

549

สรุป: ปิดการเลื่อนมุมมองข้อความของคุณและไม่จำกัดความสูงของมัน

เมื่อต้องการทำสิ่งนี้โดยทางโปรแกรมให้ใส่รหัสต่อไปนี้ในviewDidLoad:

let textView = UITextView(frame: .zero, textContainer: nil)
textView.backgroundColor = .yellow // visual debugging
textView.isScrollEnabled = false   // causes expanding height
view.addSubview(textView)

// Auto Layout
textView.translatesAutoresizingMaskIntoConstraints = false
let safeArea = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
    textView.topAnchor.constraint(equalTo: safeArea.topAnchor),
    textView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
    textView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor)
])

ในการสร้างอินเทอร์เฟซให้เลือกมุมมองข้อความยกเลิกการเลือกการเลื่อนเปิดใช้งานในตัวตรวจสอบแอตทริบิวต์และเพิ่มข้อ จำกัด ด้วยตนเอง

หมายเหตุ: หากคุณมีมุมมองอื่น / สูงกว่า / ต่ำกว่ามุมมองข้อความของคุณให้พิจารณาใช้UIStackViewเพื่อจัดเรียงทั้งหมด


12
ใช้งานได้สำหรับฉัน (iOS 7 @ xcode 5) ข้อแม้คือการยกเลิกการเลือกเพียง "เปิดใช้งานการเลื่อน" ใน IB จะไม่ช่วย คุณต้องทำโดยทางโปรแกรม
Kenneth Jiang

10
ฉันจะตั้งค่าความสูงสูงสุดในมุมมองข้อความได้อย่างไรจากนั้นให้มุมมองข้อความเลื่อนหลังจากเนื้อหานั้นเกินความสูงของมุมมองข้อความ
ma11hew28

3
@iOSGeek เพียงแค่สร้าง subclass UITextView และเขียนทับเช่นนี้intrinsicContentSize - (CGSize)intrinsicContentSize { CGSize size = [super intrinsicContentSize]; if (self.text.length == 0) { size.height = UIViewNoIntrinsicMetric; } return size; }บอกฉันว่ามันใช้ได้ผลสำหรับคุณหรือไม่ ไม่ได้ทดสอบด้วยตัวเอง
manuelwaldner

1
ตั้งค่าคุณสมบัตินี้และวาง UITextView ใน UIStackView Voilla - ปรับขนาดข้อความด้วยตนเองดู!)
Nik Kov

3
คำตอบนี้คือทองคำ ด้วย Xcode 9 จะใช้งานได้หากคุณปิดใช้งานช่องทำเครื่องหมายใน IB
bio

48

นี่คือวิธีการแก้ปัญหาสำหรับผู้ที่ต้องการทำทั้งหมดโดยการจัดวางอัตโนมัติ:

ในการตรวจสอบขนาด:

  1. ตั้งค่าลำดับความสำคัญของความต้านทานการบีบอัดเนื้อหาในแนวตั้งเป็น 1,000

  2. ลดลำดับความสำคัญของความสูงของข้อ จำกัด ลงโดยคลิก "แก้ไข" ในข้อ จำกัด เพียงแค่ทำให้มันน้อยกว่า 1,000

ป้อนคำอธิบายรูปภาพที่นี่

ในตัวตรวจสอบคุณสมบัติ:

  1. ยกเลิกการทำเครื่องหมาย "เปิดใช้งานการเลื่อน"

มันทำงานได้อย่างสมบูรณ์แบบ ฉันไม่ได้ตั้งความสูง การเพิ่มระดับความสำคัญของความต้านทานแรงกดตามแนวตั้งของ UItextview เป็น 1,000 จำเป็นต้องใช้เท่านั้น UItextView มีสิ่งที่แทรกอยู่บางส่วนนั่นคือสาเหตุที่ autolayout ให้ข้อผิดพลาดเนื่องจาก UItextview จะต้องมีความสูงอย่างน้อย 32 ความสูงแม้ว่าจะไม่มีเนื้อหาอยู่ในนั้นเมื่อปิดการใช้งานการเลื่อน
nr5

อัปเดต: จำเป็นต้องมีการจำกัดความสูงหากคุณต้องการให้ความสูงไม่ต่ำกว่า 20 หรืออย่างอื่น อื่น ๆ ที่ฉลาด 32 จะถือว่าเป็นความสูงขั้นต่ำ
nr5

@ ไม่มีความยินดีที่ได้ยินมันช่วย
Michael Revlis

@MichaelRevlis มันใช้งานได้ดี แต่เมื่อมีข้อความขนาดใหญ่ข้อความจะไม่แสดง คุณสามารถเลือกข้อความทำการประมวลผลอื่น ๆ แต่ไม่สามารถมองเห็นได้ คุณช่วยฉันด้วยได้ไหม ? มันเกิดขึ้นเมื่อฉันยกเลิกการเลือกตัวเลือกการเปิดใช้งานการเลื่อน เมื่อฉันเปิดใช้งานการเลื่อนมุมมองข้อความมันจะแสดงได้อย่างสมบูรณ์ แต่ฉันต้องการให้มุมมองข้อความไม่ให้เลื่อน
Bhautik Ziniya

@BhautikZiniya คุณลองสร้างแอปของคุณบนอุปกรณ์จริงหรือไม่? ฉันคิดว่ามันอาจเป็นเครื่องจำลองที่แสดงข้อผิดพลาด ฉันมี UITextView พร้อมตัวอักษรขนาด 100 มันแสดงผลได้ดีบนอุปกรณ์จริง แต่ข้อความจะไม่ปรากฏในเครื่องจำลอง
Michael Revlis

38

UITextView ไม่ได้จัดให้มี intrinsicContentSize ดังนั้นคุณต้อง subclass มันและให้หนึ่ง ในการทำให้มันโตขึ้นโดยอัตโนมัติให้โมฆะ intrinsicContentSize ใน layoutSubviews หากคุณใช้สิ่งอื่นนอกเหนือจาก contentInset ที่เป็นค่าเริ่มต้น (ซึ่งฉันไม่แนะนำ) คุณอาจต้องปรับการคำนวณ intrinsicContentSize

@interface AutoTextView : UITextView

@end

#import "AutoTextView.h"

@implementation AutoTextView

- (void) layoutSubviews
{
    [super layoutSubviews];

    if (!CGSizeEqualToSize(self.bounds.size, [self intrinsicContentSize])) {
        [self invalidateIntrinsicContentSize];
    }
}

- (CGSize)intrinsicContentSize
{
    CGSize intrinsicContentSize = self.contentSize;

    // iOS 7.0+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {
        intrinsicContentSize.width += (self.textContainerInset.left + self.textContainerInset.right ) / 2.0f;
        intrinsicContentSize.height += (self.textContainerInset.top + self.textContainerInset.bottom) / 2.0f;
    }

    return intrinsicContentSize;
}

@end

1
นี้ทำงานได้ดีสำหรับฉัน. นอกจากนี้ฉันจะตั้งค่า 'scrollEnabled' เป็น NO ใน Interface Builder สำหรับมุมมองข้อความนี้เนื่องจากมันจะแสดงเนื้อหาทั้งหมดโดยไม่ต้องเลื่อน ที่สำคัญกว่านั้นถ้าอยู่ในมุมมองเลื่อนที่แท้จริงคุณสามารถพบเคอร์เซอร์ที่กระโดดใกล้กับด้านล่างของมุมมองข้อความหากคุณไม่ปิดใช้งานการเลื่อนบนมุมมองข้อความ
idStar

มันใช้งานได้ดี ที่น่าสนใจเมื่อเอาชนะsetScrollEnabled:การตั้งค่าให้NOคุณจะได้รับการวนซ้ำไม่สิ้นสุดสำหรับขนาดเนื้อหาที่แท้จริงที่เพิ่มขึ้นเรื่อย ๆ
Pascal

ใน iOS 7.0 ฉันต้องโทร[textView sizeToFit]ในการtextViewDidChange:โทรกลับของผู้มอบหมายสำหรับ Auto Layout เพื่อขยายหรือลดขนาดของมุมมองข้อความ (และคำนวณข้อ จำกัด ใด ๆ ที่ขึ้นอยู่กับ) หลังจากการกดแป้นแต่ละครั้ง
followben

6
สิ่งนี้ดูเหมือนจะไม่จำเป็นในiOS 7.1อีกต่อไปในการแก้ไขและให้ความเข้ากันได้ย้อนหลังห่อเงื่อนไข-(void)layoutSubviewsและห่อรหัสทั้งหมด-(CGSize)intrinsicContentSizeด้วยversion >= 7.0f && version < 7.1f+else return [super intrinsicContentSize];
David James

1
@DavidJames ยังมีความจำเป็นใน iOS 7.1.2 ฉันไม่ทราบว่าคุณกำลังทดสอบอยู่ที่ไหน
Softlion

28

คุณสามารถทำได้ผ่านกระดานเรื่องราวเพียงแค่ปิดการใช้งาน "Scrolling Enabled" :)

สตอรี่บอร์ด


2
คำตอบที่ดีที่สุดสำหรับคำถามนี้
Ivan Byelko

นี่เป็นทางออกที่ดีที่สุดเมื่อคุณทำงานกับเค้าโครงอัตโนมัติ
JanApotheker

1
การตั้งค่าเลย์เอาต์อัตโนมัติ (นำหน้า, ต่อท้าย, บน, ล่าง, ไม่สูง / กว้าง ) + ปิดการใช้งานการเลื่อน และคุณไป ขอบคุณ!
Farhan Arshad

15

ฉันพบว่าไม่ใช่เรื่องผิดปกติอย่างสิ้นเชิงในสถานการณ์ที่คุณอาจต้องตั้งค่า isScrollEnabled เป็น true เพื่ออนุญาตการโต้ตอบ UI ที่เหมาะสม กรณีที่ง่ายสำหรับกรณีนี้คือเมื่อคุณต้องการอนุญาตให้มีการขยายมุมมองข้อความอัตโนมัติ แต่ยังคงจำกัดความสูงของสิ่งที่สมเหตุสมผลใน UITableView

นี่คือ subclass ของ UITextView ที่ฉันสร้างขึ้นมาซึ่งอนุญาตให้ขยายอัตโนมัติด้วยเลย์เอาต์อัตโนมัติ แต่คุณยังสามารถจำกัดความสูงได้สูงสุดและจะจัดการว่ามุมมองนั้นเลื่อนได้หรือไม่ขึ้นอยู่กับความสูง ตามค่าเริ่มต้นมุมมองจะขยายอย่างไม่มีกำหนดหากคุณมีข้อ จำกัด ในการตั้งค่าแบบนั้น

import UIKit

class FlexibleTextView: UITextView {
    // limit the height of expansion per intrinsicContentSize
    var maxHeight: CGFloat = 0.0
    private let placeholderTextView: UITextView = {
        let tv = UITextView()

        tv.translatesAutoresizingMaskIntoConstraints = false
        tv.backgroundColor = .clear
        tv.isScrollEnabled = false
        tv.textColor = .disabledTextColor
        tv.isUserInteractionEnabled = false
        return tv
    }()
    var placeholder: String? {
        get {
            return placeholderTextView.text
        }
        set {
            placeholderTextView.text = newValue
        }
    }

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        isScrollEnabled = false
        autoresizingMask = [.flexibleWidth, .flexibleHeight]
        NotificationCenter.default.addObserver(self, selector: #selector(UITextInputDelegate.textDidChange(_:)), name: Notification.Name.UITextViewTextDidChange, object: self)
        placeholderTextView.font = font
        addSubview(placeholderTextView)

        NSLayoutConstraint.activate([
            placeholderTextView.leadingAnchor.constraint(equalTo: leadingAnchor),
            placeholderTextView.trailingAnchor.constraint(equalTo: trailingAnchor),
            placeholderTextView.topAnchor.constraint(equalTo: topAnchor),
            placeholderTextView.bottomAnchor.constraint(equalTo: bottomAnchor),
        ])
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var text: String! {
        didSet {
            invalidateIntrinsicContentSize()
            placeholderTextView.isHidden = !text.isEmpty
        }
    }

    override var font: UIFont? {
        didSet {
            placeholderTextView.font = font
            invalidateIntrinsicContentSize()
        }
    }

    override var contentInset: UIEdgeInsets {
        didSet {
            placeholderTextView.contentInset = contentInset
        }
    }

    override var intrinsicContentSize: CGSize {
        var size = super.intrinsicContentSize

        if size.height == UIViewNoIntrinsicMetric {
            // force layout
            layoutManager.glyphRange(for: textContainer)
            size.height = layoutManager.usedRect(for: textContainer).height + textContainerInset.top + textContainerInset.bottom
        }

        if maxHeight > 0.0 && size.height > maxHeight {
            size.height = maxHeight

            if !isScrollEnabled {
                isScrollEnabled = true
            }
        } else if isScrollEnabled {
            isScrollEnabled = false
        }

        return size
    }

    @objc private func textDidChange(_ note: Notification) {
        // needed incase isScrollEnabled is set to true which stops automatically calling invalidateIntrinsicContentSize()
        invalidateIntrinsicContentSize()
        placeholderTextView.isHidden = !text.isEmpty
    }
}

เป็นโบนัสมีการสนับสนุนสำหรับการรวมข้อความตัวแทนที่คล้ายกับ UILabel


7

นอกจากนี้คุณยังสามารถทำได้โดยไม่ UITextViewsubclassing ดูที่คำตอบของฉันฉันจะปรับขนาด UITextView ให้เป็นเนื้อหาใน iOS 7 ได้อย่างไร

ใช้ค่าของนิพจน์นี้:

[textView sizeThatFits:CGSizeMake(textView.frame.size.width, CGFLOAT_MAX)].height

การปรับปรุงconstantของความสูงของtextViewUILayoutConstraint


3
คุณกำลังทำสิ่งนี้อยู่และคุณกำลังทำสิ่งอื่นเพื่อให้แน่ใจว่า UITextView ได้รับการตั้งค่าทั้งหมดหรือไม่ ฉันกำลังทำสิ่งนี้และมุมมองข้อความจะปรับขนาดเอง แต่ข้อความจะถูกตัดออกไปครึ่งทางตามความสูงของ UITextView ข้อความถูกตั้งค่าโดยทางโปรแกรมก่อนที่จะทำสิ่งต่าง ๆ ข้างต้น
chadbag

ฉันพบสิ่งนี้โดยทั่วไปมีประโยชน์มากกว่าคำสั่ง scrollEnabled = NO หากคุณต้องการตั้งค่าความกว้างด้วยตนเอง
jchnxu

3

สิ่งสำคัญที่ควรทราบ:

เนื่องจาก UITextView เป็น subclass ของ UIScrollView มันขึ้นอยู่กับคุณสมบัติ automaticAdjustsScrollViewInsets ของ UIViewController

หากคุณกำลังตั้งค่าเค้าโครงและ TextView เป็นมุมมองย่อยแรกในลำดับชั้นของ UIViewControllers มันจะมีการปรับเปลี่ยน contentInsets ถ้า AutomaticAdjustsScrollViewInsets เป็นจริงบางครั้งทำให้เกิดพฤติกรรมที่ไม่คาดคิดในโครงร่างอัตโนมัติ

ดังนั้นหากคุณมีปัญหาเกี่ยวกับเลย์เอาต์อัตโนมัติและมุมมองข้อความให้ลองตั้งค่าautomaticallyAdjustsScrollViewInsets = falseบนตัวควบคุมมุมมองหรือเลื่อน textView ไปข้างหน้าในลำดับชั้น


2

นี่เป็นความคิดเห็นที่สำคัญมาก

กุญแจสำคัญในการทำความเข้าใจว่าทำไมคำตอบของวิตามินวอเทอร์จึงมีสามสิ่ง:

  1. รู้ว่า UITextView เป็น subclass ของคลาส UIScrollView
  2. ทำความเข้าใจวิธีการทำงานของ ScrollView และวิธีคำนวณขนาดเนื้อหา สำหรับข้อมูลเพิ่มเติมดู ที่นี่คำตอบและโซลูชั่นและความคิดเห็นต่างๆ
  3. ทำความเข้าใจว่า contentSize คืออะไรและคำนวณอย่างไร ดูที่นี่และที่นี่ นอกจากนี้ยังอาจช่วยให้การตั้งค่าcontentOffsetนั้นน่าจะเป็นอะไร แต่:

func setContentOffset(offset: CGPoint)
{
    CGRect bounds = self.bounds
    bounds.origin = offset
    self.bounds = bounds
}

ดูเพิ่มเติมobjc scrollviewและเข้าใจ scrollview


การรวมสามอย่างเข้าด้วยกันคุณจะเข้าใจได้อย่างง่ายดายว่าคุณต้องการอนุญาตให้ contentView ขนาดแท้จริงของ textView ทำงานตามข้อ จำกัด AutoLayout ของ textView เพื่อขับเคลื่อนตรรกะ มันเกือบจะเหมือนกับว่าคุณ textView ทำงานเหมือน UILabel

ในการทำให้เกิดขึ้นคุณต้องปิดใช้งานการเลื่อนซึ่งโดยทั่วไปหมายถึงขนาดของ scrollView ขนาดของ contentSize และในกรณีที่เพิ่ม containerView จากนั้นขนาดของ containerView จะเท่ากัน เมื่อพวกเขาเหมือนกันคุณจะไม่มีการเลื่อน และคุณจะต้อง มีหมายความว่าคุณไม่ได้เลื่อนลง ไม่แม้แต่ 1 จุดลง! ดังนั้น textView จะขยายออกทั้งหมด0 contentOffset0 contentOffSet

นอกจากนี้ยังไม่มีค่าอะไรที่ หมายความว่าขอบเขตและกรอบของ scrollView เหมือนกัน หากคุณเลื่อนลง 5 คะแนนเนื้อหาของคุณจะเป็น Offset ในขณะที่คุณจะเท่ากับ0 contentOffset5scrollView.bounds.origin.y - scrollView.frame.origin.y5


1

โซลูชั่นแบบพลักแอนด์เพลย์ - Xcode 9

autolayoutเช่นเดียวUILabelกับการตรวจสอบการเชื่อมโยง , การเลือกข้อความ , การแก้ไขและเลื่อนUITextViewของ

จัดการโดยอัตโนมัติ

  • พื้นที่ปลอดภัย
  • เนื้อหาที่ใส่เข้าไป
  • การขยายส่วนของเส้น
  • ที่เก็บข้อความ
  • ข้อ จำกัด
  • มุมมองสแต็ก
  • สตริงที่ประกอบขึ้น
  • อะไรก็ตาม

คำตอบเหล่านี้จำนวนมากทำให้ฉันมี 90% แต่ไม่มีใครพิสูจน์ได้

ดร็อปUITextViewคลาสย่อยนี้และคุณทำได้ดี


#pragma mark - Init

- (instancetype)initWithFrame:(CGRect)frame textContainer:(nullable NSTextContainer *)textContainer
{
    self = [super initWithFrame:frame textContainer:textContainer];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (void)commonInit
{
    // Try to use max width, like UILabel
    [self setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    
    // Optional -- Enable / disable scroll & edit ability
    self.editable = YES;
    self.scrollEnabled = YES;
    
    // Optional -- match padding of UILabel
    self.textContainer.lineFragmentPadding = 0.0;
    self.textContainerInset = UIEdgeInsetsZero;
    
    // Optional -- for selecting text and links
    self.selectable = YES;
    self.dataDetectorTypes = UIDataDetectorTypeLink | UIDataDetectorTypePhoneNumber | UIDataDetectorTypeAddress;
}

#pragma mark - Layout

- (CGFloat)widthPadding
{
    CGFloat extraWidth = self.textContainer.lineFragmentPadding * 2.0;
    extraWidth +=  self.textContainerInset.left + self.textContainerInset.right;
    if (@available(iOS 11.0, *)) {
        extraWidth += self.adjustedContentInset.left + self.adjustedContentInset.right;
    } else {
        extraWidth += self.contentInset.left + self.contentInset.right;
    }
    return extraWidth;
}

- (CGFloat)heightPadding
{
    CGFloat extraHeight = self.textContainerInset.top + self.textContainerInset.bottom;
    if (@available(iOS 11.0, *)) {
        extraHeight += self.adjustedContentInset.top + self.adjustedContentInset.bottom;
    } else {
        extraHeight += self.contentInset.top + self.contentInset.bottom;
    }
    return extraHeight;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    // Prevents flashing of frame change
    if (CGSizeEqualToSize(self.bounds.size, self.intrinsicContentSize) == NO) {
        [self invalidateIntrinsicContentSize];
    }
    
    // Fix offset error from insets & safe area
    
    CGFloat textWidth = self.bounds.size.width - [self widthPadding];
    CGFloat textHeight = self.bounds.size.height - [self heightPadding];
    if (self.contentSize.width <= textWidth && self.contentSize.height <= textHeight) {
        
        CGPoint offset = CGPointMake(-self.contentInset.left, -self.contentInset.top);
        if (@available(iOS 11.0, *)) {
            offset = CGPointMake(-self.adjustedContentInset.left, -self.adjustedContentInset.top);
        }
        if (CGPointEqualToPoint(self.contentOffset, offset) == NO) {
            self.contentOffset = offset;
        }
    }
}

- (CGSize)intrinsicContentSize
{
    if (self.attributedText.length == 0) {
        return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
    }
    
    CGRect rect = [self.attributedText boundingRectWithSize:CGSizeMake(self.bounds.size.width - [self widthPadding], CGFLOAT_MAX)
                                                    options:NSStringDrawingUsesLineFragmentOrigin
                                                    context:nil];
    
    return CGSizeMake(ceil(rect.size.width + [self widthPadding]),
                      ceil(rect.size.height + [self heightPadding]));
}

0

คำตอบของ vitaminwater นั้นใช้ได้ผลสำหรับฉัน

หากข้อความ TextView ของคุณจะใหญ่ขึ้นและลงในระหว่างการแก้ไขหลังจากการตั้งค่าชุด[textView setScrollEnabled:NO];Size Inspector > Scroll View > Content Insets > Never

หวังว่ามันจะช่วย


0

วาง UILabel ที่ซ่อนอยู่ใต้มุมมองข้อความของคุณ Label Lines = 0 กำหนดข้อ จำกัด ของ UITextView ให้เท่ากับ UILabel (centerX, centerY, width, height) ทำงานได้แม้ว่าคุณจะออกจากพฤติกรรมการเลื่อนของ textView


-1

BTW ฉันสร้าง UITextView ที่ขยายขึ้นโดยใช้คลาสย่อยและแทนที่ขนาดเนื้อหาที่แท้จริง ฉันค้นพบข้อบกพร่องใน UITextView ที่คุณอาจต้องการตรวจสอบในการใช้งานของคุณเอง นี่คือปัญหา:

มุมมองข้อความที่ขยายจะโตลงเพื่อรองรับข้อความที่กำลังเติบโตหากคุณพิมพ์ตัวอักษรทีละตัว แต่ถ้าคุณวางข้อความเป็นมัด ๆ มันจะไม่โตขึ้น แต่ข้อความจะเลื่อนขึ้นและข้อความที่อยู่ด้านบนก็ไม่ได้ถูกมอง

การแก้ปัญหา: แทนที่ setBounds: ในคลาสย่อยของคุณ ด้วยเหตุผลที่ไม่ทราบสาเหตุการวางทำให้ขอบเขตค่าต้นกำเนิดของฉันเป็น non-zee (33 ในทุกกรณีที่ฉันเห็น) ดังนั้นฉันจึงข้าม setBounds: เพื่อตั้งขอบเขตเสมอหรือกำเนิดเป็นศูนย์ แก้ไขปัญหา


-1

นี่เป็นวิธีแก้ปัญหาอย่างรวดเร็ว:

ปัญหานี้อาจเกิดขึ้นหากคุณตั้งค่าคุณสมบัติ clipsToBounds เป็น false ของมุมมองข้อความของคุณ หากคุณเพียงแค่ลบมันปัญหาจะหายไป

myTextView.clipsToBounds = false //delete this line

-3
Obj C:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic) UITextView *textView;
@end



#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize textView;

- (void)viewDidLoad{
    [super viewDidLoad];
    [self.view setBackgroundColor:[UIColor grayColor]];
    self.textView = [[UITextView alloc] initWithFrame:CGRectMake(30,10,250,20)];
    self.textView.delegate = self;
    [self.view addSubview:self.textView];
}

- (void)didReceiveMemoryWarning{
    [super didReceiveMemoryWarning];
}

- (void)textViewDidChange:(UITextView *)txtView{
    float height = txtView.contentSize.height;
    [UITextView beginAnimations:nil context:nil];
    [UITextView setAnimationDuration:0.5];

    CGRect frame = txtView.frame;
    frame.size.height = height + 10.0; //Give it some padding
    txtView.frame = frame;
    [UITextView commitAnimations];
}

@end
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.