การเติมUILabel
เต็มวิธีการแก้ปัญหา อัปเดตในปี 2020
ปรากฎว่ามีสามสิ่งที่ต้องทำ
1. ต้องเรียกใช้ textRect # forBounds ด้วยขนาดที่เล็กกว่าใหม่
2. ต้องแทนที่ drawText ด้วยขนาดที่เล็กกว่าใหม่
3. หากเซลล์ที่มีขนาดแบบไดนามิกต้องปรับเปลี่ยน intrinsicContentSize
ในตัวอย่างด้านล่างหน่วยข้อความที่อยู่ในมุมมองตารางมุมมองสแต็คหรือการก่อสร้างที่คล้ายกันซึ่งจะทำให้มันกว้างคง ในตัวอย่างเราต้องการการเติมเต็ม 60,20,20,24
ดังนั้นเราจึงใช้ "ที่มีอยู่" intrinsicContentSize และจริงเพิ่ม 80 ความสูง
ทำซ้ำ ...
คุณต้อง "รับ" ความสูงที่คำนวณได้ "จนถึงตอนนี้" โดยเครื่องยนต์และเปลี่ยนค่านั้น
ฉันพบว่ากระบวนการนั้นทำให้เกิดความสับสน แต่นั่นเป็นวิธีการทำงาน สำหรับฉัน Apple ควรเปิดเผยการโทรที่มีชื่อว่า "การคำนวณความสูงเบื้องต้น"
ประการที่สองเราจะต้องใช้งานจริง textRect อันดับ forBounds โทรด้วยขนาดที่เล็กกว่าของเราใหม่
ดังนั้นใน textRect # forBounds เราครั้งแรกทำให้มีขนาดเล็กลงและจากนั้นเรียกซุปเปอร์
แจ้งเตือน! คุณต้องโทรหาซุปเปอร์หลังจากไม่ใช่ก่อน!
หากคุณตรวจสอบความพยายามและการอภิปรายทั้งหมดในหน้านี้อย่างรอบคอบนั่นเป็นปัญหาที่แน่นอน สังเกตวิธีแก้ปัญหาบางอย่าง "ดูเหมือนจะเกือบจะทำงานได้" แต่บางคนก็จะรายงานว่าในบางสถานการณ์มันจะไม่ทำงาน นี่คือเหตุผลที่แท้จริง - คุณต้อง "โทรหาซูเปอร์ภายหลัง" อย่างสับสนไม่ได้มาก่อน
ดังนั้นหากคุณเรียกมันว่า "ผิดลำดับ" มากเกินไปมันก็ใช้งานได้แต่ไม่ได้มีความยาวข้อความที่แน่นอน
นี่คือตัวอย่างที่เห็นได้ชัดของ "การทำซุปเปอร์มาอย่างไม่ถูกต้อง":
ขอให้สังเกตว่าระยะขอบ 60,20,20,24 นั้นถูกต้อง แต่การคำนวณขนาดนั้นผิดจริงเพราะทำด้วยรูปแบบ "ขั้นแรกสุด" ใน textRect # forBounds
แก้ไขแล้ว:
โปรดสังเกตว่าตอนนี้ textRect # forBounds เอ็นจิ้นรู้วิธีการคำนวณอย่างถูกต้องเท่านั้น :
ที่สุด!
อีกครั้งในตัวอย่างนี้ UILabel กำลังถูกใช้ในสถานการณ์ทั่วไปที่มีการแก้ไขความกว้าง ดังนั้นใน intrinsicContentSize เราต้อง "เพิ่ม" ความสูงพิเศษโดยรวมที่เราต้องการ (คุณไม่จำเป็นต้อง "เพิ่ม" ในความกว้างไม่ว่าจะเป็นความหมายตามที่ได้รับการแก้ไข)
จากนั้นใน textRect # forBounds คุณจะได้รับขอบเขต "ที่แนะนำ" โดย autolayout คุณจะลบระยะขอบของคุณและจากนั้นโทรไปที่เครื่องมือ textRect # forBounds อีกครั้งนั่นคือการพูดในระดับสูงซึ่งจะทำให้คุณได้ผลลัพธ์
ในที่สุดและเพียงแค่ในการดึงคุณแน่นอนวาดในกล่องขนาดเล็กที่เดียวกัน
วุ้ย
let UIEI = UIEdgeInsets(top: 60, left: 20, bottom: 20, right: 24) // as desired
override var intrinsicContentSize:CGSize {
numberOfLines = 0 // don't forget!
var s = super.intrinsicContentSize
s.height = s.height + UIEI.top + UIEI.bottom
s.width = s.width + UIEI.left + UIEI.right
return s
}
override func drawText(in rect:CGRect) {
let r = rect.inset(by: UIEI)
super.drawText(in: r)
}
override func textRect(forBounds bounds:CGRect,
limitedToNumberOfLines n:Int) -> CGRect {
let b = bounds
let tr = b.inset(by: UIEI)
let ctr = super.textRect(forBounds: tr, limitedToNumberOfLines: 0)
// that line of code MUST be LAST in this function, NOT first
return ctr
}
อีกครั้ง หมายเหตุว่าคำตอบเกี่ยวกับเรื่องนี้และควบคุมคุณภาพอื่น ๆ ที่เป็น "เกือบ" ที่ถูกต้องประสบปัญหาในภาพแรกข้างต้น - The "ซูเปอร์อยู่ในสถานที่ที่ไม่ถูกต้อง" คุณต้องบังคับให้ขนาดใหญ่ขึ้นใน intrinsicContentSize แล้วใน textRect # forBounds คุณต้องหดขอบเขตคำแนะนำแรกก่อนแล้วจึงเรียก super
สรุป: คุณต้อง "การเรียกร้องซุปเปอร์สุดท้าย " ใน textRect # forBounds
นั่นเป็นความลับ
โปรดทราบว่าคุณไม่จำเป็นต้องและไม่จำเป็นต้องโทรหาการใช้งานที่ไม่ถูกต้อง, sizeThatFits, needsLayout หรือการบังคับให้โทรอื่น ๆ โซลูชันที่ถูกต้องควรทำงานอย่างถูกต้องในรอบการวาดอัตโนมัติแบบปกติ
เคล็ดลับ:
หากคุณกำลังทำงานกับแบบอักษร monospace ต่อไปนี้เป็นเคล็ดลับที่ยอดเยี่ยม: https://stackoverflow.com/a/59813420/294884