Imbottitura a UILabel
, soluzione completa. Aggiornato per il 2020.
Si scopre che ci sono tre cose da fare.
1. Deve chiamare textRect # forBounds con la nuova dimensione più piccola
2. Deve sovrascrivere drawText con la nuova dimensione più piccola
3. Se una cella di dimensioni dinamiche, deve regolare intrinsicContentSize
Nell'esempio tipico di seguito, l'unità di testo è in una vista tabella, vista pila o costruzione simile, che le conferisce una larghezza fissa . Nell'esempio vogliamo un'imbottitura di 60,20,20,24.
Quindi, prendiamo intrinsicContentSize "esistente" e in realtà aggiungiamo 80 all'altezza .
Ripetere ...
Devi letteralmente "ottenere" l'altezza calcolata "finora" dal motore, e cambiare quel valore.
Trovo che questo processo sia confuso, ma è così che funziona. Per me, Apple dovrebbe esporre una chiamata chiamata "Calcolo preliminare dell'altezza".
In secondo luogo, dobbiamo effettivamente utilizzare la chiamata textRect # forBounds con le nostre nuove dimensioni più piccole .
Quindi in textRect # forBounds prima riduciamo le dimensioni e poi chiamiamo super.
Mettere in guardia! È necessario chiamare Super dopo , non prima!
Se indaghi attentamente su tutti i tentativi e le discussioni in questa pagina, questo è il problema esatto. Si noti che alcune soluzioni "sembrano quasi funzionare", ma qualcuno segnalerà che in determinate situazioni non funzionerà. Questo è davvero il motivo esatto: confusamente devi "chiamare super dopo", non prima.
Quindi, se lo chiami super "nell'ordine sbagliato", di solito funziona, ma non per determinate lunghezze di testo specifiche .
Ecco un esempio visivo esatto di "erroneamente fare il primo super":
Si noti che i margini 60,20,20,24 sono corretti MA il calcolo delle dimensioni è in realtà errato, poiché è stato eseguito con il modello "super first" in textRect # forBounds.
Fisso:
Si noti che solo ora il motore textRect # forBounds sa come eseguire correttamente il calcolo :
Finalmente!
Ancora una volta, in questo esempio UILabel viene utilizzato nella situazione tipica in cui la larghezza è fissa. Quindi in intrinsicContentSize dobbiamo "aggiungere" l'altezza extra complessiva che desideriamo. (Non è necessario "aggiungere" in alcun modo alla larghezza, sarebbe privo di significato in quanto è stato risolto.)
Quindi in textRect # forBounds si ottengono i limiti "suggeriti finora" mediante autolayout, si sottraggono i margini e solo successivamente si richiama nuovamente al motore textRect # forBounds, vale a dire in super, il che ti darà un risultato.
Finalmente e semplicemente in drawText, ovviamente, si disegna nella stessa casella più piccola.
Accidenti!
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
}
Di nuovo. Si noti che le risposte su questo e altri QA "quasi" corretti presentano il problema nella prima immagine sopra: il "super è nel posto sbagliato" . È necessario forzare la dimensione più grande in intrinsicContentSize e quindi in textRect # forBounds è necessario prima ridurre i limiti del primo suggerimento e quindi chiamare super.
Riepilogo: è necessario "chiamare super last " in textRect # forBounds
Questo è il segreto
Si noti che non è necessario e non è necessario chiamare inoltre invalidate, sizeThatFits, needsLayout o qualsiasi altra chiamata forzata. Una soluzione corretta dovrebbe funzionare correttamente nel normale ciclo di estrazione del layout automatico.
Mancia:
Se stai lavorando con caratteri monospace, ecco un ottimo consiglio: https://stackoverflow.com/a/59813420/294884