ios - descargar - iphone 5s
Cambiar el tamaño de un UILabel para acomodar inserciones (7)
Añadiendo a @Pataphysicien la respuesta anterior para los formularios de Xamarin, así es como usa UIEdgeableLabel:
[assembly: ExportRenderer(typeof(PaddedLabel), typeof(PaddedLabelRenderer))]
namespace MyProj.iOS.Renderers
{
public class PaddedLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
if (Control == null)
{
var label = new UIEdgeableLabel();
label.EdgeInsets = new UIEdgeInsets(2, 2, 2, 2); //padding
SetNativeControl(label);
}
base.OnElementChanged(e);
}
}
}
Estoy construyendo una pantalla para escanear códigos de barras, y tengo que colocar una pantalla translúcida detrás de algunos UILabels
para mejorar la visibilidad contra fondos claros.
Así es como se ve la pantalla ahora:
Estoy configurando el color de fondo en UILabel
para obtener los cuadros translúcidos. También creé una subclase de UILabel
personalizada para permitirme establecer algo de relleno entre el borde de UILabel
y el texto usando este enfoque .
Como puede ver en la pantalla de arriba, UILabel
no UILabel
tamaño correctamente para tener en cuenta el relleno. El "relleno" simplemente cambia el texto sin cambiar el ancho de la etiqueta, lo que hace que el texto se trunque.
Ambas etiquetas contendrán texto de longitudes arbitrarias, y realmente necesito que UILabel
tamaño dinámicamente.
¿ UILabel
método de UILabel
puedo anular para aumentar el ancho de la etiqueta y tener en cuenta el relleno?
Además de la respuesta de Nikolai Ruhe , debe invalidar el tamaño de contenido intrínseco para el autodiseño para recalcular correctamente los cambios de tamaño. Notarás este problema si cambias edgeInsets durante el ciclo de vida de la aplicación:
class NRLabel: UILabel {
var edgeInsets = UIEdgeInsetsZero {
didSet {
self.invalidateIntrinsicContentSize()
}
}
...
}
Aquí está la versión C # (útil para Xamarin) basada en el código de Nikolai:
public class UIEdgeableLabel : UILabel
{
public UIEdgeableLabel() : base() { }
public UIEdgeableLabel(NSCoder coder) : base(coder) { }
public UIEdgeableLabel(CGRect frame) : base(frame) { }
protected UIEdgeableLabel(NSObjectFlag t) : base(t) { }
private UIEdgeInsets _edgeInset = UIEdgeInsets.Zero;
public UIEdgeInsets EdgeInsets
{
get { return _edgeInset; }
set
{
_edgeInset = value;
this.InvalidateIntrinsicContentSize();
}
}
public override CGRect TextRectForBounds(CGRect bounds, nint numberOfLines)
{
var rect = base.TextRectForBounds(EdgeInsets.InsetRect(bounds), numberOfLines);
return new CGRect(x: rect.X - EdgeInsets.Left,
y: rect.Y - EdgeInsets.Top,
width: rect.Width + EdgeInsets.Left + EdgeInsets.Right,
height: rect.Height + EdgeInsets.Top + EdgeInsets.Bottom);
}
public override void DrawText(CGRect rect)
{
base.DrawText(this.EdgeInsets.InsetRect(rect));
}
}
Aquí hay un ejemplo de lo que utilicé para un acolchado simple de 10 unidades a la izquierda y derecha de la etiqueta con esquinas redondeadas. Simplemente configura el texto de la etiqueta para centrarlo y haz que sea de la clase IndentedLabel y el resto se ocupa de sí mismo. Para modificar el relleno simplemente escala hacia arriba o hacia abajo rect.size.width + = (x)
class IndentedLabel: UILabel {
var edgeInsets:UIEdgeInsets = UIEdgeInsetsZero
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
var rect = super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, edgeInsets), limitedToNumberOfLines: numberOfLines)
rect.size.width += 20;
return rect
}
override func drawTextInRect(rect: CGRect) {
self.clipsToBounds = true
self.layer.cornerRadius = 3
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, edgeInsets))
}
}
Aquí hay una clase de etiqueta que calcula los tamaños correctamente. El código publicado está en Swift 3, pero también puede descargar las versiones de Swift 2 u Objective-C .
¿Como funciona?
Al calcular el texto correcto, se repare que todo el sizeToFit
y el diseño automático funcionan como se esperaba. El truco consiste en restar primero las inserciones, luego calcular los límites de las etiquetas originales y finalmente agregar las inserciones nuevamente.
Código
class NRLabel : UILabel {
var textInsets = UIEdgeInsets.zero {
didSet { invalidateIntrinsicContentSize() }
}
override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
let insetRect = UIEdgeInsetsInsetRect(bounds, textInsets)
let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines)
let invertedInsets = UIEdgeInsets(top: -textInsets.top,
left: -textInsets.left,
bottom: -textInsets.bottom,
right: -textInsets.right)
return UIEdgeInsetsInsetRect(textRect, invertedInsets)
}
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, textInsets))
}
}
Opcional: compatibilidad con Interface Builder
Si desea configurar texto en los guiones gráficos, puede usar la siguiente extensión para habilitar el soporte de Interface Builder:
@IBDesignable
extension NRLabel {
// currently UIEdgeInsets is no supported IBDesignable type,
// so we have to fan it out here:
@IBInspectable
var leftTextInset: CGFloat {
set { textInsets.left = newValue }
get { return textInsets.left }
}
// Same for the right, top and bottom edges.
}
Ahora puede configurar convenientemente sus inserciones en IB y luego simplemente presionar ⌘ = para ajustar el tamaño de la etiqueta para que encaje.
Renuncia:
Todo el código es de dominio público. Haz lo que quieras.
Aquí hay una forma rápida y traviesa de hacerlo que puedes entender más rápido. No es tan robusto como el de Nikolai, pero hace el trabajo bien. Hice esto cuando intenté ajustar mi texto en mi UILabel dentro de una UITableViewCell:
- Establecer una restricción de ancho para el UILabel
- Conecte la restricción mediante IBOutlet a su código, ya sea VC (clase de celda personalizada si está haciendo una celda de vista de tabla en expansión)
- Cree una variable para el tamaño real del texto, luego agregue las inserciones + el tamaño del ancho a la restricción y actualice la vista:
let messageTextSize: CGSize = (messageText as NSString).sizeWithAttributes([ NSFontAttributeName: UIFont.systemFontOfSize(14.0)]) cell.widthConstraint.constant = messageTextSize.width + myInsetsOrWhatever
Aún no lo he probado exhaustivamente, es posible que deba jugar con los valores exactos de CGFloat que agrega. Descubrí que el tamaño correcto no es exactamente el ancho más las inserciones; es un poco más grande que eso. Esto asegura que el ancho de UILabel siempre será al menos del tamaño del texto o más grande.
Aquí hay una versión Swift de una subclase UILabel (igual que la respuesta de @ Nikolai) que crea un relleno adicional alrededor del texto de un UILabel:
class EdgeInsetLabel : UILabel {
var edgeInsets:UIEdgeInsets = UIEdgeInsetsZero
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
var rect = super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, edgeInsets), limitedToNumberOfLines: numberOfLines)
rect.origin.x -= edgeInsets.left
rect.origin.y -= edgeInsets.top
rect.size.width += (edgeInsets.left + edgeInsets.right);
rect.size.height += (edgeInsets.top + edgeInsets.bottom);
return rect
}
override func drawTextInRect(rect: CGRect) {
super.drawTextInRect(UIEdgeInsetsInsetRect(rect, edgeInsets))
}
}