วิธีการลด margin / padding ใน UITextView


486

ฉันมีUITextViewแอพพลิเคชั่น iOS ของฉันซึ่งแสดงข้อความจำนวนมาก

แล้วฉันกำลังเพจข้อความนี้โดยใช้พารามิเตอร์ขอบ offset UITextViewของ

ปัญหาของฉันคือการ padding ของการUITextViewคำนวณของฉันสับสนเนื่องจากดูเหมือนว่าจะแตกต่างกันขึ้นอยู่กับขนาดตัวอักษรและแบบอักษรที่ฉันใช้

ดังนั้นฉันถามคำถาม: มันเป็นไปได้ที่จะลบช่องว่างภายในโดยรอบเนื้อหาของUITextView?

หวังว่าจะได้ยินคำตอบของคุณ!


9
โปรดทราบว่า QA นี้มีอายุเกือบสิบปี! ด้วยมุมมองที่ 100,000 ตั้งแต่หนึ่งในนั้นปัญหาโง่ใน iOS เพียงแค่ FTR ที่ฉันใส่ในปี 2017 โซลูชันที่เรียบง่าย / ปกติ / เป็นที่ยอมรับด้านล่างนี้เป็นคำตอบ
Fattie

1
ฉันยังคงได้รับการอัปเดตเกี่ยวกับเรื่องนี้มีการเขียนวิธีแก้ปัญหาฮาร์ดโค้ดในปี 2009 เมื่อ IOS 3.0 เพิ่งเปิดตัว ฉันเพิ่งแก้ไขคำตอบเพื่อระบุอย่างชัดเจนว่าเป็นปีที่ล้าสมัยและไม่สนใจสถานะที่ยอมรับได้
ไมเคิล

คำตอบ:


383

ทันสมัยสำหรับปี 2562

มันเป็นหนึ่งในข้อบกพร่องที่ร้ายแรงที่สุดใน iOS

คลาสที่ให้ที่นี่UITextViewFixedเป็นวิธีการแก้ปัญหาที่เหมาะสมที่สุดโดยรวม

นี่คือคลาส:

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

อย่าลืมปิด scrollEnabled ใน Inspector!

  1. วิธีการแก้ปัญหาทำงานอย่างถูกต้องในกระดานเรื่องราว

  2. วิธีการแก้ปัญหาทำงานอย่างถูกต้องที่รันไทม์

เสร็จแล้ว

โดยทั่วไปที่ควรจะเป็นสิ่งที่คุณต้องการในกรณีส่วนใหญ่

แม้ว่าคุณจะมีการเปลี่ยนแปลงความสูงของมุมมองข้อความที่เกี่ยวกับการบิน , UITextViewFixedมักจะไม่สิ่งที่คุณต้องการ

(ตัวอย่างทั่วไปของการเปลี่ยนความสูงได้ทันทีคือเปลี่ยนเป็นประเภทผู้ใช้)

นี่คือ UITextView ที่หักจาก Apple ...

สกรีนช็อตของ IB พร้อม UITextView

นี่คือUITextViewFixed:

สกรีนช็อตของ IB พร้อม UITextViewFixed

ทราบว่าแน่นอนคุณต้อง

ปิด scrollEnabled ในตัวตรวจสอบ!

อย่าลืมปิด scrollEnabled! :)


บางประเด็นเพิ่มเติม

(1) ในบางกรณีที่ผิดปกติ - ตัวอย่างเช่นบางกรณีของตารางที่มีความยืดหยุ่นของเซลล์ที่เปลี่ยนแปลงสูงแบบไดนามิก - Apple ทำสิ่งที่แปลกประหลาด: พวกเขาเพิ่มพื้นที่พิเศษที่ด้านล่างพวกเขาเพิ่มพื้นที่พิเศษที่ด้านล่างไม่มีจริงๆ! สิ่งนี้จะต้องเป็นหนึ่งในสิ่งที่ทำให้โกรธที่สุดใน 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 mess-up อื่นที่บอบบางคุณต้องเพิ่มสิ่งนี้:

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

(3) เราควรจะเพิ่ม:

contentInset = UIEdgeInsets.zero

หลังจากที่ใน.lineFragmentPadding = 0UITextViewFixed

อย่างไรก็ตาม ... เชื่อหรือไม่ ... มันใช้ไม่ได้กับ iOS ปัจจุบัน! (ตรวจสอบในปี 2562) อาจจำเป็นต้องเพิ่มบรรทัดนั้นอีกในอนาคต

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

สุดท้ายนี่คือเคล็ดลับที่คล้ายกันสำหรับ Text Field : https://stackoverflow.com/a/43099816/294884

เคล็ดลับแบบสุ่มสมบูรณ์: วิธีเพิ่ม "... " ในตอนท้าย

บ่อยครั้งที่คุณใช้ UITextView "like UILabel" คุณต้องการตัดทอนข้อความโดยใช้เครื่องหมายจุดไข่ปลา "... "

ถ้าเป็นเช่นนั้นเพิ่มรหัสบรรทัดที่สามใน "ตั้งค่า":

 textContainer.lineBreakMode = .byTruncatingTail

เคล็ดลับที่มีประโยชน์ถ้าคุณต้องการความสูงเป็นศูนย์เมื่อไม่มีข้อความเลย

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

เยี่ยมมาก แต่ถ้าไม่มีข้อความเลยน่าเสียดายที่คุณมีความสูงเท่ากับข้อความหนึ่งบรรทัด !! มุมมองข้อความไม่เคย "หายไป"

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

หากคุณต้องการให้ "หายไป" เพียงเพิ่มสิ่งนี้

override var intrinsicContentSize: CGSize {
    var i = super.intrinsicContentSize
    print("for \(text) size will be \(i)")
    if text == "" { i.height = 1.0 }
    print("   but we changed it to \(i)")
    return i
}

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

(ฉันทำให้มันเป็น '1' ดังนั้นจึงเป็นที่ชัดเจนว่าเกิดอะไรขึ้น '0' ไม่เป็นไร)

แล้ว UILabel ล่ะ

เมื่อแสดงข้อความ UILabel มีข้อดีกว่า UITextView มากมาย UILabel ไม่ประสบปัญหาที่อธิบายไว้ในหน้า QA นี้ เหตุผลที่เรามักจะ "ยอมแพ้" และเพียงแค่ใช้ UITextView ก็คือ UILabel นั้นยากที่จะทำงานด้วย โดยเฉพาะอย่างยิ่งมันเป็นเรื่องยากที่จะเพิ่มการเติมpaddingอย่างถูกต้องลงใน UILabel ในความเป็นจริงที่นี่คือการสนทนาเต็มรูปแบบเกี่ยวกับวิธี "ในที่สุด" อย่างถูกต้องเพิ่มการขยายไปยัง UILabel อย่างถูกต้อง: https://stackoverflow.com/a/58876988/294884 ในบางกรณีถ้าคุณทำเค้าโครงยากด้วยเซลล์ความสูงแบบไดนามิกบางครั้งก็เป็น ดีกว่าที่จะทำมันอย่างหนักกับ UILabel


1
ฉันself.textView.isScrollEnabled = falseเข้าไปข้างในviewDidLayoutSubviews()และนั่นก็ใช้ได้เช่นกัน แอปเปิ้ลเพียงแค่ชอบที่จะทำให้เรากระโดดผ่านห่วง :)
AnBisw

1
ทางออกที่ดีที่สุดในการแก้ไขข้อบกพร่องอัตโนมัติ UITextView ของฉันทั้งหมดใน UITableView Cells Header และ Footer ด้วยความสูงแบบไดนามิก (UITableViewAutomaticDimension) ที่ดี!
Peter Kreinz

1
ผมเคยโพสต์คำตอบของการปรับปรุงเพื่อให้คำตอบ @ Fattie translatesAutoresizingMaskIntoConstraintsซึ่งช่วยให้ผมจริงๆกำจัดขุ่นทั้งหมดโดยใช้เคล็ดลับพิเศษของการเปิด ด้วยคำตอบนี้เพียงอย่างเดียวฉันไม่สามารถลบระยะขอบทั้งหมด (ขอบล่างบางอันแปลก ๆ ที่ต่อต้านหายไป) ในลำดับชั้นการดูโดยใช้เลย์เอาต์อัตโนมัติ นอกจากนี้ยังเกี่ยวข้องกับการคำนวณขนาดการดูที่ใช้systemLayoutSizeFittingซึ่งก่อนหน้านี้ส่งคืนขนาดที่ไม่ถูกต้องเนื่องจาก buggyUITextView
Fab1n

1
1up สำหรับ IBDesignable ฉันต้องการ
อัปเด

1
ฉันมี textviews ในตารางคนที่มีบรรทัดเดียวของข้อความไม่ได้คำนวณความสูงได้อย่างถูกต้อง (autolayout) ในการแก้ไขฉันต้องแทนที่ didMoveToSuperview และตั้งค่าการโทรที่นั่นด้วย
El Horrible

791

สำหรับ iOS 7.0 ฉันพบว่าการหลอกลวง contentInset ใช้งานไม่ได้อีกต่อไป นี่คือรหัสที่ฉันใช้เพื่อกำจัดระยะขอบ / ช่องว่างภายในใน iOS 7

วิธีนี้จะนำขอบซ้ายของข้อความไปที่ขอบด้านซ้ายของคอนเทนเนอร์:

textView.textContainer.lineFragmentPadding = 0

ซึ่งทำให้ด้านบนของข้อความเพื่อจัดตำแหน่งกับด้านบนของคอนเทนเนอร์

textView.textContainerInset = .zero

จำเป็นต้องใช้ทั้งสองเส้นเพื่อลบระยะขอบ / ช่องว่างภายใน


2
สิ่งนี้ใช้ได้สำหรับฉันสองบรรทัด แต่เมื่อถึง 5 บรรทัดข้อความจะถูกตัดออก
livings124

7
โปรดทราบว่าบรรทัดที่สองสามารถเขียนเป็น: self.descriptionTextView.textContainerInset = UIEdgeInsetsZero;
jessepinho

19
การตั้งค่าlineFragmentPaddingเป็น 0 คือความมหัศจรรย์ที่ฉันกำลังมองหา ฉันไม่รู้ว่าทำไม Apple ทำให้เป็นเรื่องยากที่จะจัดเรียงเนื้อหา UITextView กับตัวควบคุมอื่น ๆ
phatmann

3
นี่คือคำตอบที่ถูกต้อง การเลื่อนในแนวนอนจะไม่เกิดขึ้นกับโซลูชันนี้
Michael

2
lineFragmentPaddingไม่ได้มีวัตถุประสงค์เพื่อปรับระยะขอบ จากdocs การ เติมเต็มส่วนบรรทัดไม่ได้ออกแบบมาเพื่อแสดงระยะขอบข้อความ แต่คุณควรใช้ส่วนแทรกในมุมมองข้อความของคุณปรับเปลี่ยนคุณลักษณะระยะขอบย่อหน้าหรือเปลี่ยนตำแหน่งของมุมมองข้อความภายในมุมมองกำกับ
Martin Berger

256

วิธีแก้ปัญหานี้ถูกเขียนในปี 2009 เมื่อเปิดตัว IOS 3.0 มันใช้ไม่ได้อีกต่อไป

ฉันวิ่งเข้าไปในปัญหาเดียวกันที่แน่นอนในที่สุดฉันก็ต้องใช้

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

ที่ nameField UITextViewเป็น แบบอักษรที่ฉันใช้คือ Helvetica 16 point เป็นเพียงโซลูชันที่กำหนดเองสำหรับขนาดฟิลด์เฉพาะที่ฉันวาด สิ่งนี้ทำให้ออฟเซ็ตซ้ายกับด้านซ้ายและออฟเซ็ตด้านบนที่ฉันต้องการสำหรับกล่องที่วาด

นอกจากนี้ดูเหมือนว่าจะใช้กับUITextViewsตำแหน่งที่คุณใช้การตั้งค่าเริ่มต้นเท่านั้น

nameField.textAlignment = NSTextAlignmentLeft;

จัดแนวไปทางขวาตัวอย่างเช่นUIEdgeInsetsMakeดูเหมือนว่าจะไม่มีผลกระทบกับขอบขวาเลย

ที่อย่างน้อยที่สุดโดยใช้ .contentInset คุณสมบัติช่วยให้คุณวางเขตข้อมูลของคุณกับ "ถูกต้อง" UITextViewsตำแหน่งและรองรับการเบี่ยงเบนโดยไม่มีการหักล้างของคุณ


1
ใช่มันทำงานได้ใน iOS 7 ตรวจสอบให้แน่ใจว่า UIEdgeInset ถูกตั้งค่าเป็นค่าที่เหมาะสม มันอาจแตกต่างจาก UIEdgeInsetsMake (-4, -8,0,0)
app_

15
ใน IOS 7 ฉันพบ UIEdgeInsetsMake (0, -4,0, -4) ทำงานได้ดีที่สุด
Racura

2
ใช่นั่นคือตัวเลขตัวอย่าง ฉันระบุว่า "เป็นเพียงโซลูชันที่กำหนดเองสำหรับขนาดฟิลด์เฉพาะที่ฉันวาด" ส่วนใหญ่ฉันพยายามแสดงให้เห็นว่าคุณต้องเล่นกับตัวเลขสำหรับสถานการณ์รูปแบบที่ไม่ซ้ำกันของคุณ
Michael

3
UITextAlignmentLeft เลิกใช้แล้วใน iOS 7 ใช้ NSTextAlignmentLeft
Jordi Kroon

7
ฉันไม่เข้าใจว่าทำไมคนถึงตอบคำตอบที่ใช้ประโยชน์จากค่าตายตัว มันมีโอกาสมากที่จะแตก iOS เวอร์ชันถัดไปและเป็นเพียงความคิดที่ไม่ดี
ldoogy

77

สร้างคำตอบที่ดีบางข้อที่ได้รับแล้วนี่เป็นโซลูชันที่ใช้สตอรี่บอร์ด / อินเทอร์เฟซผู้สร้างที่ใช้งานได้กับ iOS 7.0+

ตั้งค่าแอททริบิวต์รันไทม์ที่ผู้ใช้กำหนดของ UITextView สำหรับคีย์ต่อไปนี้:

textContainer.lineFragmentPadding
textContainerInset

เครื่องมือสร้างส่วนต่อประสาน


4
นี้ชัดเจนคำตอบที่ดีที่สุดโดยเฉพาะอย่างยิ่งถ้าคุณต้องแก้ปัญหา XIB เท่านั้น
Yano

16
คัดลอก / วาง: textContainer.lineFragmentPadding | textContainerInset
Luca De Angelis

3
นี่คือสิ่งที่ทำให้คำตอบที่สวยงาม - ง่ายและทำงานได้ดีแม้หลังจาก 3 ปี :)
Shai Mishali


41

ฉันจะหลีกเลี่ยงคำตอบใด ๆ ที่เกี่ยวข้องกับค่าตายตัวเนื่องจากระยะขอบที่แท้จริงอาจเปลี่ยนไปตามการตั้งค่าขนาดตัวอักษรของผู้ใช้เป็นต้น

นี่คือคำตอบของ @ user1687195 เขียนโดยไม่มีการแก้ไขtextContainer.lineFragmentPadding(เนื่องจากเอกสารระบุว่านี่ไม่ใช่การใช้งานที่ตั้งใจ)

ใช้งานได้ดีกับ iOS 7 และใหม่กว่า

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

นี่เป็นผลลัพธ์ที่เหมือนกันอย่างมีประสิทธิภาพเพียงเล็กน้อยที่สะอาดกว่าซึ่งไม่ได้ใช้คุณสมบัติ lineFragmentPadding ในทางที่ผิด


ฉันลองวิธีอื่นตามคำตอบนี้และใช้งานได้ดี การแก้ปัญหาคือ:self.textView.textContainer.lineFragmentPadding = 0;
Bakyt Abdrasulov

1
@ BakytAbdrasulov โปรดอ่านคำตอบของฉัน ในขณะที่โซลูชันของคุณใช้งานได้ไม่เป็นไปตามเอกสาร (ดูลิงก์ในคำตอบของฉัน) lineFragmentPaddingไม่ได้หมายถึงการควบคุมระยะขอบ textContainerInsetนั่นเป็นเหตุผลที่คุณควรจะใช้
ldoogy

20

สตอรีบอร์ดหรือโซลูชันตัวสร้างส่วนต่อประสานโดยใช้คุณสมบัติรันไทม์ที่ผู้ใช้กำหนดเอง :

ภาพหน้าจอของ iOS 7.1 และ iOS 6.1 contentInset = {{-10, -5}, {0, 0}}ด้วย

คุณสมบัติรันไทม์ที่ผู้ใช้กำหนด

เอาท์พุต


1
ทำงานให้ฉันใน iOS 7
kubilay

เพิ่มขึ้นเฉพาะสำหรับคุณสมบัติที่กำหนดโดยผู้ใช้รันไทม์
hris.to

16

คำตอบทั้งหมดเหล่านี้ตอบคำถามชื่อเรื่อง แต่ฉันต้องการเสนอวิธีแก้ไขปัญหาสำหรับปัญหาที่นำเสนอในเนื้อความของคำถามของ 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

ใช้วิธีการเหล่านี้ทั้งหมดฉันไม่ได้สัมผัสสิ่งที่ใส่เข้าไปและฉันสามารถไปที่เครื่องหมายรูปหมวกหรือที่ใดก็ได้ในข้อความที่ฉันต้องการ


12

คุณสามารถใช้textContainerInsetคุณสมบัติของUITextView:

textView.textContainerInset = UIEdgeInsetsMake (10, 10, 10, 10);

(บน, ซ้าย, ล่าง, ขวา)


1
ฉันสงสัยว่าทำไมสิ่งนี้จึงไม่ได้รับมอบหมายให้เป็นคำตอบที่ดีที่สุดที่นี่ textContainerInset ตอบสนองความต้องการของฉันอย่างแท้จริง
KoreanXcodeWorker

การอัปเดตค่าด้านล่างในtextContainerInsetทรัพย์สินไม่ทำงานสำหรับฉันเมื่อฉันต้องการที่จะเปลี่ยนมันไปอยู่ที่ใหม่ที่มีมูลค่าเห็นstackoverflow.com/questions/19422578/...
Evan R

@MaggiePhillips ไม่ใช่คำตอบที่ดีที่สุดเพราะค่า hardcoded อาจไม่ใช่วิธีที่ถูกต้องในการทำเช่นนี้และรับประกันได้ว่าจะล้มเหลวในบางกรณี คุณต้องคำนึงถึง lineFragmentPadding ด้วย
ldoogy

11

สำหรับ iOS 10 บรรทัดต่อไปนี้ใช้สำหรับการลบส่วนขยายด้านบนและด้านล่าง

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

Xcode 8.2.1 ยังคงเป็นปัญหาเดียวกันตามที่ระบุไว้ในคำตอบนี้ โซลูชันของฉันคือแก้ไขค่าเป็น UIEdgeInsets (top: 0, left: -4.0, bottom: 0, right: -4.0)
Darkwonder

UIEdgeInset.zeroใช้งานได้กับ XCode 8.3 และ iOS 10.3 Simulator
Simon Warta

10

สวิฟท์ล่าสุด:

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

คำตอบที่ดี คำตอบนี้จะลบสิ่งที่ใส่เข้าไปเพิ่มเติมยอดนิยม textView.textContainerInset = UIEdgeInsets.zero ไม่ได้ลบ 2 พิกเซลออกจากสิ่งที่ใส่เข้าไปด้านบน
korgx9

10

นี่เป็นคำตอบที่เป็นประโยชน์ของ Fattie รุ่นปรับปรุง มันเพิ่ม 2 บรรทัดสำคัญที่ช่วยให้ฉันได้รับเลย์เอาต์ที่ทำงานบน iOS 10 และ 11 (และอาจเป็นในกรณีที่ต่ำกว่าเช่นกัน):

@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ได้มี

ดังนั้นฉันอ่านที่นี่เกี่ยวกับ SOที่เปิดใช้งานและปิดใช้งานtranslatesAutoresizingMaskIntoConstraintsจะช่วยเมื่อตั้งค่าเฟรม / ขอบเขตด้วยตนเองในระหว่างการโทร

โชคดีที่มันไม่เพียงทำงานได้กับการตั้งค่าเฟรมเท่านั้น แต่ยังมีsetup()แซนด์วิช2 เส้นคั่นระหว่างสองtranslatesAutoresizingMaskIntoConstraintsโทรสาย!

ตัวอย่างนี้มีประโยชน์มากเมื่อคำนวณกรอบของมุมมองโดยใช้systemLayoutSizeFittingบนUIViewในให้ขนาดที่ถูกต้อง (ซึ่งก่อนหน้านี้มันไม่ได้)!

ดังที่ได้กล่าวไว้ในคำตอบเดิม:
อย่าลืมปิด scrollEnabled ใน Inspector!
วิธีการแก้ปัญหานั้นทำงานอย่างถูกต้องในกระดานเรื่องราวเช่นเดียวกับในขณะทำงาน

เพียงเท่านี้คุณก็ทำได้จริงๆ !


5

สำหรับ swift 4, Xcode 9

ใช้ฟังก์ชั่นต่อไปนี้สามารถเปลี่ยนระยะขอบ / ช่องว่างภายในของข้อความใน UITextView

ฟังก์ชั่นที่สาธารณะ UIEdgeInsetsMake (_ top: CGFloat, _ ซ้าย: CGFloat, _ bottom: CGFloat, _ ขวา: CGFloat) -> UIEdgeInsets

ดังนั้นในกรณีนี้คือ

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

3

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


3

นี่เป็นส่วนเสริมเล็ก ๆ น้อย ๆ ที่จะลบระยะขอบเริ่มต้นของ 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);
   }
}

1

สำหรับฉัน (iOS 11 & Xcode 9.4.1) สิ่งที่ใช้งานได้ดีคือการตั้งค่าคุณสมบัติ textView.font ให้มีUIFont.preferred(forTextStyle:UIFontTextStyle) สไตล์และยังเป็นคำตอบแรกตามที่ @Fattie พูดถึง แต่คำตอบ @Fattie ไม่ทำงานจนกว่าฉันจะตั้งค่าคุณสมบัติ textView.font เป็นอย่างอื่น UITextView จะทำงานผิดปกติ


1

ในกรณีที่ใครก็ตามที่กำลังมองหา Swift เวอร์ชั่นล่าสุดแล้วโค้ดด้านล่างก็ใช้ได้ดี Xcode 10.2และSwift 4.2

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

0

ฉันพบวิธีการอีกวิธีหนึ่งแล้วรับมุมมองด้วยข้อความจากการดูย่อยของ UITextView และตั้งค่าในวิธี layoutSubview ของคลาสย่อย:

- (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);
}

0

การเลื่อน textView ยังส่งผลต่อตำแหน่งของข้อความและทำให้ดูเหมือนไม่อยู่กึ่งกลางแนวตั้ง ฉันจัดการเพื่อจัดกึ่งกลางข้อความในมุมมองโดยปิดใช้งานการเลื่อนและการตั้งค่าส่วนบนสุดเป็น 0:

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

ด้วยเหตุผลบางอย่างที่ฉันยังไม่พบมันเคอร์เซอร์ยังคงไม่อยู่กึ่งกลางก่อนที่การพิมพ์จะเริ่มขึ้น แต่ข้อความจะอยู่กึ่งกลางทันทีที่ฉันเริ่มพิมพ์


0

ในกรณีที่คุณต้องการตั้งค่าสตริง HTML และหลีกเลี่ยงการเติมด้านล่างโปรดตรวจสอบให้แน่ใจว่าคุณไม่ได้ใช้แท็กบล็อกเช่น div, p

ในกรณีของฉันนี่คือเหตุผล คุณสามารถทดสอบได้อย่างง่ายดายโดยแทนที่การเกิดขึ้นของแท็กบล็อกด้วยเช่นแท็กขยาย


0

สำหรับ SwiftUI

หากคุณสร้าง TextView ของคุณเองโดยใช้UIViewRepresentableและต้องการควบคุมช่องว่างภายในmakeUIViewฟังก์ชันของคุณเพียงทำ:

uiTextView.textContainerInset = UIEdgeInsets(top: 10, left: 18, bottom: 0, right: 18)

หรืออะไรก็ได้ที่คุณต้องการ


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