¿Cómo configurar la alineación superior izquierda para la aplicación UILabel para iOS?


99

He agregado una etiqueta en mi archivo de plumilla, entonces es necesario que tenga una alineación superior izquierda para esa etiqueta. Como estoy proporcionando texto en tiempo de ejecución, no estoy seguro de cuántas líneas hay. Entonces, si el texto contiene solo una línea, entonces aparece alineado verticalmente en el centro. Esa alineación no coincide con mi etiqueta respectiva frente a ella.

Por ejemplo:

ingrese la descripción de la imagen aquí

Que se ve extraño :(

¿Hay alguna forma en la que pueda establecer el texto de la etiqueta adecuado para la alineación superior izquierda?


Respuestas:



64

Es bastante fácil de hacer. Cree un UILabelsubcasco con una verticalAlignmentpropiedad y anule textRectForBounds:limitedToNumberOfLinespara devolver los límites correctos para una alineación vertical superior, media o inferior. Aquí está el código:

SOLabel.h

#import <UIKit/UIKit.h>

typedef enum
{
    VerticalAlignmentTop = 0, // default
    VerticalAlignmentMiddle,
    VerticalAlignmentBottom,
} VerticalAlignment;

@interface SOLabel : UILabel

   @property (nonatomic, readwrite) VerticalAlignment verticalAlignment;

@end

SOLabel.m

@implementation SOLabel

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (!self) return nil;

    // set inital value via IVAR so the setter isn't called
    _verticalAlignment = VerticalAlignmentTop;

    return self;
}

-(VerticalAlignment) verticalAlignment
{
    return _verticalAlignment;
}

-(void) setVerticalAlignment:(VerticalAlignment)value
{
    _verticalAlignment = value;
    [self setNeedsDisplay];
}

// align text block according to vertical alignment settings
-(CGRect)textRectForBounds:(CGRect)bounds 
    limitedToNumberOfLines:(NSInteger)numberOfLines
{
   CGRect rect = [super textRectForBounds:bounds 
                   limitedToNumberOfLines:numberOfLines];
    CGRect result;
    switch (_verticalAlignment)
    {
       case VerticalAlignmentTop:
          result = CGRectMake(bounds.origin.x, bounds.origin.y, 
                              rect.size.width, rect.size.height);
           break;

       case VerticalAlignmentMiddle:
          result = CGRectMake(bounds.origin.x, 
                    bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
                    rect.size.width, rect.size.height);
          break;

       case VerticalAlignmentBottom:
          result = CGRectMake(bounds.origin.x, 
                    bounds.origin.y + (bounds.size.height - rect.size.height),
                    rect.size.width, rect.size.height);
          break;

       default:
          result = bounds;
          break;
    }
    return result;
}

-(void)drawTextInRect:(CGRect)rect
{
    CGRect r = [self textRectForBounds:rect 
                limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:r];
}

@end

3
También probé muchas otras soluciones aquí en SO antes de encontrarme con esta. ¡Funcionó perfectamente! Tenga en cuenta que si está haciendo esto en StoryBoard, asegúrese de establecer el atributo CustomClass en SOLabel (o como decida nombrarlo) en lugar de UILabel (en el Inspector de utilidades).
TMc

Esto es muy útil, gracias. No funciona para texto alineado en el centro o la derecha, pero usarlo en bounds.size.widthlugar de rect.size.widthen textRectForBounds:limitedToNumberOfLines:parece solucionarlo.
Geoff Hackworth

1
Si encontró 'Thread 1: EXC_BAD_ACCESS (Code 2, address = 0x ...)' en iOS 9 Xcode 7, simplemente elimine el setter y getter - (VerticalAlignment) verticalAlignment; y - (void) setVerticalAlignment: funciones de valor (VerticalAlignment), ya que la variable es @property. Está sintetizado y contiene descriptores de acceso.
felixwcf

Tengo que hacer algunas enmiendas aquí en el método: "textRectForBounds" - resultado = CGRectMake (rect.origin.x, limits.origin.y, rect.size.width, rect.size.height); Para hacer mis trabajos para la alineación correcta UILable.
g212gs

50

Encontré una solución usando AutoLayout en StoryBoard.

1) Establezca el número de líneas en 0 y la alineación del texto en la izquierda.

ingrese la descripción de la imagen aquí

2) Establecer restricción de altura.

ingrese la descripción de la imagen aquí

3) La restricción de altura debe estar en relación: menor o igual que

ingrese la descripción de la imagen aquí

4)

   override func viewWillLayoutSubviews() {
        sampleLabel.sizeToFit()
    }

Obtuve el resultado de la siguiente manera:

ingrese la descripción de la imagen aquí


2
Funciona a la perfección, incluso en un UITableViewCell con reutilización.
alex.bour

¿Colocas el viewWillLayoutSubviewsen el controlador o en el archivo de celda? Si es el controlador, ¿cómo accede a la UILabel desde la celda?
Craig.Pearce

¿Dónde pones el paso 4? Como nuevo usuario, estaba emocionado de tener una solución puramente de interfaz de usuario, luego ese código sale de la nada y no se nos dice dónde colocarlo
velkoon

Ya sea en SampleClass.swift o SampleTableViewCell.swift
AG

Esta debería ser la solución. Funciona perfectamente, no se requiere hack o subclasificación.
Curious101

44

El SOLabel funciona para mí.

Swift 3 y 5:

Esta versión se ha actualizado desde el original para permitir la compatibilidad con los idiomas RTL:

public class VerticalAlignLabel: UILabel {
    enum VerticalAlignment {
        case top
        case middle
        case bottom
    }

    var verticalAlignment : VerticalAlignment = .top {
        didSet {
            setNeedsDisplay()
        }
    }

    override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
        let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)

        if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
            switch verticalAlignment {
            case .top:
                return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
            case .middle:
                return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
            case .bottom:
                return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
            }
        } else {
            switch verticalAlignment {
            case .top:
                return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
            case .middle:
                return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
            case .bottom:
                return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
            }
        }
    }

    override public func drawText(in rect: CGRect) {
        let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
        super.drawText(in: r)
    }
}

Rápido 1:

class UIVerticalAlignLabel: UILabel {

enum VerticalAlignment : Int {
    case VerticalAlignmentTop = 0
    case VerticalAlignmentMiddle = 1
    case VerticalAlignmentBottom = 2
}

var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop {
    didSet {
        setNeedsDisplay()
    }
}

required init(coder aDecoder: NSCoder){
    super.init(coder: aDecoder)
}

override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
    let rect = super.textRectForBounds(bounds, limitedToNumberOfLines: limitedToNumberOfLines)

    switch(verticalAlignment) {
        case .VerticalAlignmentTop:
            return CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height)
        case .VerticalAlignmentMiddle:
            return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height)
        case .VerticalAlignmentBottom:
            return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height)
        default:
            return bounds
    }
}

override func drawTextInRect(rect: CGRect) {
    let r = self.textRectForBounds(rect, limitedToNumberOfLines: self.numberOfLines)
    super.drawTextInRect(r)
    }
}

Si trato de crear una etiqueta usando este código: var myLabel = VerticalAlignLabel () obtengo un "Argumento faltante para el parámetro 'codificador' en la llamada". ¿Cómo puedo crear una etiqueta usando esta subclase VerticalAlignLabel?
RanLearns

1
Pruebe la versión 3 de Swift ahora: tenía un init requerido que no es necesario.
hasta el

14

En mi caso, fue un bottom spaceproblema de restricción. Lo había puesto en = 16.

Cuando lo configuré bottom to >= 16, este problema se resolvió.

Además, si tiene alguna restricción de altura en la etiqueta, debe eliminarla.

Aquí está la vista de restricción de mi etiqueta en el inspector de tamaño:

restricción


No tengo opciones de restricción cuando selecciono una etiqueta.
velkoon

La solución más simple: deje que las restricciones y el diseño automático se encarguen de ello. ¡Gracias!
Jason

13

En tu código

label.text = @"some text";
[label sizeToFit];

Tenga en cuenta que si lo usa en celdas de tabla u otras vistas que se reciclan con datos diferentes, deberá almacenar el marco original en algún lugar y restablecerlo antes de llamar a sizeToFit.


Recomiendo dejarlo todo en Autolayout en este punto. Esto ya no es necesario.
n13

9

Encontré otra solución para el mismo problema. Usé en UITextViewlugar de UILabely cambié la editable()función a false.


@geekyaleks ¿Por qué es un truco tonto? Parece una solución decente, ¿hay otros problemas además de no ser una respuesta directa a la pregunta?
Christopher Larsen

No es apropiado, porque no está utilizando el componente de interfaz de usuario adecuado para el trabajo. NO debería ser un compromiso para algo tan simple como la alineación vertical. Necesita utilizar el componente adecuado para el trabajo. Cualquier otra cosa es un truco ...
geekyaleks

7

También estaba teniendo este problema, pero lo que encontré fue que el orden en el que estableces las propiedades y métodos de UILabel es importante.

Si llama [label sizeToFit]antes label.font = [UIFont fontWithName:@"Helvetica" size:14];, el texto no se alinea con la parte superior, pero si lo intercambia, ¡lo hace!

También noté que establecer el texto primero también marca la diferencia.

Espero que esto ayude.


Excelente. sizeToFit () debería llamarse al final.
MK al menos

4

Mientras utiliza el generador de interfaces, establezca las restricciones para su etiqueta (asegúrese de establecer también la altura y el ancho). Luego, en el Inspector de tamaño, verifique la altura de la etiqueta. Allí querrá que lea> = en lugar de =. Luego, en la implementación para ese controlador de vista, establezca el número de líneas en 0 (también se puede hacer en IB) y establezca la etiqueta [label sizeToFit]; ya medida que su texto gane longitud, la etiqueta crecerá en altura y mantendrá su texto en la parte superior izquierda.


4

Si lo que necesita es texto no editable que, de forma predeterminada, comienza en la esquina superior izquierda, simplemente puede usar una Vista de texto en lugar de una etiqueta y luego establecer su estado en no editable, así:

textview.isEditable = false

Mucho más fácil que jugar con las etiquetas ...

¡Salud!


3

La solución con SoLabel funciona, gracias.

A continuación, he agregado la versión monotouch:

    public class UICustomLabel : UILabel
{
    private UITextVerticalAlignment _textVerticalAlignment;

    public UICustomLabel()
    {
        TextVerticalAlignment = UITextVerticalAlignment.Top;
    }

    public UITextVerticalAlignment TextVerticalAlignment
    {
        get
        {
            return _textVerticalAlignment;
        }
        set
        {
            _textVerticalAlignment = value;
            SetNeedsDisplay();
        }
    }

    public override void DrawText(RectangleF rect)
    {
        var bound = TextRectForBounds(rect, Lines);
        base.DrawText(bound);
    }

    public override RectangleF TextRectForBounds(RectangleF bounds, int numberOfLines)
    {
        var rect = base.TextRectForBounds(bounds, numberOfLines);
        RectangleF resultRect;
        switch (TextVerticalAlignment)
        {
            case UITextVerticalAlignment.Top:
                resultRect = new RectangleF(bounds.X, bounds.Y, rect.Size.Width, rect.Size.Height);
                break;
            case UITextVerticalAlignment.Middle:
                resultRect = new RectangleF(bounds.X,
                                            bounds.Y + (bounds.Size.Height - rect.Size.Height)/2,
                                            rect.Size.Width, rect.Size.Height);
                break;
            case UITextVerticalAlignment.Bottom:
                resultRect = new RectangleF(bounds.X,
                                            bounds.Y + (bounds.Size.Height - rect.Size.Height),
                                            rect.Size.Width, rect.Size.Height);
                break;

            default:
                resultRect = bounds;
                break;
        }

        return resultRect;
    }
}

public enum UITextVerticalAlignment
{
    Top = 0, // default
    Middle,
    Bottom
}

3

La forma más sencilla y sencilla es incrustar Label en StackView y configurar el eje de StackView en Horizontal, Alignment to Top en Attribute Inspector desde Storyboard como se muestra aquí .


2

Sobre la base de la increíble respuesta de totiG, he creado una clase IBDesignable que hace que sea extremadamente fácil personalizar la alineación vertical de un UILabel directamente desde el StoryBoard. Solo asegúrese de configurar la clase de UILabel en 'VerticalAlignLabel' desde el inspector de identidad de StoryBoard. Si la alineación vertical no surte efecto, vaya a Editor-> Actualizar todas las vistas, que debería funcionar.

Cómo funciona: una vez que haya configurado correctamente la clase de UILabel, el guión gráfico debería mostrarle un campo de entrada que toma un número entero (código de alineación).

Actualización: he agregado soporte para etiquetas centradas ~ Sev


Ingrese 0 para la alineación superior

Ingrese 1 para alineación media

Ingrese 2 para alineación inferior

    @IBDesignable class VerticalAlignLabel: UILabel {
    
    @IBInspectable var alignmentCode: Int = 0 {
        didSet {
            applyAlignmentCode()
        }
    }
    
    func applyAlignmentCode() {
        switch alignmentCode {
        case 0:
            verticalAlignment = .top
        case 1:
            verticalAlignment = .topcenter
        case 2:
            verticalAlignment = .middle
        case 3:
            verticalAlignment = .bottom
        default:
            break
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        self.applyAlignmentCode()
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        
        self.applyAlignmentCode()
    }
    
    enum VerticalAlignment {
        case top
        case topcenter
        case middle
        case bottom
    }
    
    var verticalAlignment : VerticalAlignment = .top {
        didSet {
            setNeedsDisplay()
        }
    }
    
    override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
        let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
        
        if #available(iOS 9.0, *) {
            if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
                switch verticalAlignment {
                case .top:
                    return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
                case .topcenter:
                    return CGRect(x: self.bounds.size.width - (rect.size.width / 2), y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
                case .middle:
                    return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
                case .bottom:
                    return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
                }
            } else {
                switch verticalAlignment {
                case .top:
                    return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
                case .topcenter:
                    return CGRect(x: (self.bounds.size.width / 2 ) - (rect.size.width / 2), y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
                case .middle:
                    return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
                case .bottom:
                    return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
                }
            }
        } else {
            // Fallback on earlier versions
            return rect
        }
    }
    
    override public func drawText(in rect: CGRect) {
        let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
        super.drawText(in: r)
    }
}


2

también puede cambiar su UILabel a UITextView, porque básicamente hacen lo mismo, excepto que la ventaja de UITextView es que el texto se alinea automáticamente en la parte superior izquierda


1

Tengo este problema, pero mi etiqueta estaba en UITableViewCell, y en el fondo, la forma más fácil de resolver el problema era crear una UIView vacía y establecer la etiqueta dentro de ella con restricciones en la parte superior y solo en el lado izquierdo, en la maldición establecer el número de líneas en 0


0

Para iOS 7 eso es lo que hice y trabajé para mí

@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX);
    NSDictionary *attributes = @{NSFontAttributeName : self.font};
    CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                              attributes:attributes
                                                 context:nil];
    int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight);

    CGRect newFrame = self.frame;
    newFrame.size.height = numberOfLines * self.font.lineHeight;
    self.frame = newFrame;
}

- (void)alignBottom
{
    CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX);
    NSDictionary *attributes = @{NSFontAttributeName : self.font};
    CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                            attributes:attributes
                                               context:nil];
    int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight);

    int numberOfNewLined = (self.frame.size.height/self.font.lineHeight) - numberOfLines;

    NSMutableString *newLines = [NSMutableString string];
    for(int i=0; i< numberOfNewLined; i++){
        [newLines appendString:@"\n"];
    }
    [newLines appendString:self.text];
    self.text = [newLines mutableCopy];
}

0

Swift 2.0: Uso de la extensión UILabel

Cree valores de enumeración constantes en un archivo Swift vacío.

//  AppRef.swift

import UIKit
import Foundation

enum UILabelTextPositions : String {

 case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
 case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
 case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"

}

Usando la extensión UILabel:

Cree una clase Swift vacía y asígnele un nombre. Agregue lo siguiente.

//  AppExtensions.swift

import Foundation
import UIKit

    extension UILabel{ 
     func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
     {
      let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)

      switch positionIdentifier
      {
      case "VerticalAlignmentTop":
       sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
       break;

      case "VerticalAlignmentMiddle":
       sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
        rect.size.width, rect.size.height);
       break;

      case "VerticalAlignmentBottom":
       sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
       break;

      default:
       sampleLabel!.frame = bounds;
       break;
      }
      return sampleLabel!

     }
    }

Uso:

myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)

¿Podría explicar para qué se necesita sampleLabel: UILabel??
Craig.Pearce

En esta función makeLabelTextPosition (sampleLabel: UILabel ?, positionIdentifier: String) {}, debe pasar el objeto UILabel.
AG

0

Swift 3 versión de la respuesta de @ totiG

class UIVerticalAlignLabel: UILabel {
    enum VerticalAlignment : Int {
        case VerticalAlignmentTop = 0
        case VerticalAlignmentMiddle = 1
        case VerticalAlignmentBottom = 2
    }

    @IBInspectable var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop {
        didSet {
            setNeedsDisplay()
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
        let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)

        switch(verticalAlignment) {
        case .VerticalAlignmentTop:
            return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
        case .VerticalAlignmentMiddle:
            return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
        case .VerticalAlignmentBottom:
            return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
        }
    }

    override func drawText(in rect: CGRect) {
        let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
        super.drawText(in: r)
    }
}

0

La respuesta de @ totiG es correcta y resolvió mi problema. Pero encontré un problema al implementar este método, en dispositivos más pequeños como 5s, SE, esto no funciona para mí. Tengo que ponerme label.sizeToFit()enoverride func layoutSubViews()

override func layoutSubViews() {
    super.layoutSubViews()
    // Do other works if needed
    label.sizeToFit()
}

0

Rápido 5

Es simple, el orden de las propiedades lo es todo.

titleLabel.frame = CGRect(x: 20, y: 20, width: 374, height: 291.2)
titleLabel.backgroundColor = UIColor.clear //set a light color to see the frame
titleLabel.textAlignment = .left
titleLabel.lineBreakMode = .byTruncatingTail
titleLabel.numberOfLines = 4
titleLabel.font = UIFont(name: "HelveticaNeue-Bold", size: 35)
titleLabel.text = "Example"
titleLabel.sizeToFit()
self.view.addSubview(titleLabel)

-2

¿Cómo configurar la alineación superior izquierda para la aplicación UILabel para iOS? La etiqueta Establecer modo de contenido en "Arriba a la izquierda" funciona para mí, muchas gracias:
¿Cómo configurar la alineación superior izquierda para la aplicación UILabel para iOS?  La etiqueta Establecer el modo de contenido en "Arriba a la izquierda" funciona para mí, muchas gracias


1
No hace absolutamente nada por mí. Esto parece intuitivamente que debería ser la solución, por lo que recurrí a Google cuando no funcionó (o aparentemente lo hice todo, para el caso).
velkoon
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.