Posicionar un UILabel directamente debajo de otro UILabel

Tengo una adición a NSString que cambia automáticamente el tamaño de una UILabel según el text que se esté leyendo (tengo una aplicación simple que muestra citas, por lo que algunas son algunas palabras, algunas son un par de oraciones). Debajo de esa label de quote , también tengo una label de author , que (por extraño que parezca) tiene el autor de la cita.

Estoy tratando de ubicar esa label de author directamente debajo de la label de la quote (como en, su coorderada y sería la coorderada y de la label de quote más la height la label de quote . Lo que estoy viendo es un espacio entre las dos tags, que dependiendo de la longitud de la cotización, cambia el tamaño. Las comillas más pequeñas tienen más espacio, mientras que las comillas más largas tienen less espacio. Aquí hay un diagtwig rápido de lo que estoy viendo:

introduzca la descripción de la imagen aquíintroduzca la descripción de la imagen aquí

Tenga en count el espacio entre los cuadros rojo y azul (que he configurado utilizando layer.borderColor/borderWidth para que pueda verlos en la aplicación), cuanto más grande sea, más corta será la cita.

Si alguien puede examinar el código a continuación y ayudarme a señalar exactamente qué causa la discrepancia, estaría muy agradecido. Por lo que puedo ver, la label del author siempre debe ser de 35 píxeles debajo del valor de y + height la label de quote y + height .

Solo para confirmar: todo está conectado correctamente en Interface Builder, etc. El contenido de la cita entra bien, todo lo demás funciona, por lo que está conectado, ese no es el problema.

Para aclarar, mi pregunta es: ¿Por qué la diferencia entre las tags cambia dependiendo de la longitud de la cita y cómo puedo get un espacio estable y ajustable de 35 píxeles correctamente?

Aquí está el código que estoy usando para ubicar las tags:

 // Fill and format Quote Details _quoteLabel.text = [NSString stringWithFormat:@"\"%@\"", _selectedQuote.quote]; _authorLabel.text = _selectedQuote.author; [_quoteLabel setFont: [UIFont fontWithName: kScriptFont size: 28.0f]]; [_authorLabel setFont: [UIFont fontWithName: kScriptFontAuthor size: 30.0f]]; // Automatically resize the label, then center it again. [_quoteLabel sizeToFitMultipleLines]; [_quoteLabel setFrame: CGRectMake(11, 11, 298, _quoteLabel.frame.size.height)]; // Position the author label below the quote label, however high it is. [_authorLabel setFrame: CGRectMake(11, 11 + _quoteLabel.frame.size.height + 35, _authorLabel.frame.size.width, _authorLabel.frame.size.height)]; 

Aquí está mi método personalizado para sizeToFitMultipleLines :

 - (void) sizeToFitMultipleLines { if (self.adjustsFontSizeToFitWidth) { CGFloat adjustedFontSize = [self.text fontSizeWithFont: self.font constrainedToSize: self.frame.size minimumFontSize: self.minimumScaleFactor]; self.font = [self.font fontWithSize: adjustedFontSize]; } [self sizeToFit]; } 

Y aquí está mi fontSizeWithFont:constrainedToSize:minimumFontSize: method:

 - (CGFloat) fontSizeWithFont: (UIFont *) font constrainedToSize: (CGSize) size minimumFontSize: (CGFloat) minimumFontSize { CGFloat fontSize = [font pointSize]; CGFloat height = [self sizeWithFont: font constrainedToSize: CGSizeMake(size.width, FLT_MAX) lineBreakMode: NSLineBreakByWordWrapping].height; UIFont *newFont = font; // Reduce font size while too large, break if no height (empty string) while (height > size.height && height != 0 && fontSize > minimumFontSize) { fontSize--; newFont = [UIFont fontWithName: font.fontName size: fontSize]; height = [self sizeWithFont: newFont constrainedToSize: CGSizeMake(size.width, FLT_MAX) lineBreakMode: NSLineBreakByWordWrapping].height; }; // Loop through words in string and resize to fit for (NSString *word in [self componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]) { CGFloat width = [word sizeWithFont: newFont].width; while (width > size.width && width != 0 && fontSize > minimumFontSize) { fontSize--; newFont = [UIFont fontWithName: font.fontName size: fontSize]; width = [word sizeWithFont: newFont].width; } } return fontSize; } 

Después de llamar al tamaño para que encaje en ambas tags, calcule la distancia entre sus frameworks y cámbielos según corresponda:

 [quoteLabel sizeToFit]; [authorLabel sizeToFit]; float distance = authorLabel.frame.origin.y - quoteLabel.frame.size.height; float difference = distance - 35; authorLabel.frame = CGRectMake(authorLabel.frame.origin.x,(authorLabel.frame.origin.y - difference),authorLabel.frame.size.width,authorLabel.frame.size.height); 

La razón por la que cambia la brecha es que el marco de label de cotización cambia su altura dependiendo de su contenido cuando llama a sizeToFit.

ACTUALIZAR

Teniendo en count los recientes desarrollos en los comentarios, creo que tienes 3 posibilidades:

  • cambiar el tamaño del espacio en blanco en lugar de solo las palabras, para que la cadena encaje correctamente en el marco correctamente
  • de alguna manera acceder al CTFramesetter de UILabel para ver qué es lo que el marco real, cuando todo está dicho y hecho, equivale a
  • haga su propia subclass UIView que maneja el dibujo de Texto Principal en su método de dibujar rect (debería ser fácil en su caso), ya que después de todo está intentando darle a UILabel un comportamiento que no está destinado a

Probablemente se esté moviendo donde lo desee, pero luego una restricción de layout automático o un resorte / puntal lo está moviendo después.

EDITAR:
Mi primer pensamiento (que descarté porque dijiste que el recuadro alnetworkingedor de las palabras era el marco de la label. En comentarios posteriores, dices que esta no es una captura de pantalla real, sino solo una representación de ella, por lo que podría ser correcta ) fue que estás haciendo esto mal:

 [_quoteLabel sizeToFitMultipleLines]; [_quoteLabel setFrame: CGRectMake(11, 11, 298, _quoteLabel.frame.size.height)]; 

En la primera línea, está ajustando el tamaño del text para que se ajuste al ancho actual de la label, y luego se gira en la segunda línea y cambia el ancho de la label. Lo más probable es que lo que está sucediendo es que está dimensionando la label para un ancho más pequeño, lo que lo hace alto. A continuación, hace que la label sea más ancha de lo que era antes y el text se expande para ajustarse a la label más ancha, dejando un área en blanco debajo del text real, aunque el marco no ha cambiado. Esto hace que el espacio entre las tags sea exactamente el 35 que desee, sin embargo, el text de la label superior no llega hasta el final de su marco, por lo que el espacio en blanco es más de lo que desea. Básicamente, tienes esto:

 ************* * text text * * text text * * * * * * * ************* ************* * text text * ************* 

Si este es el caso, entonces lo arreglará estableciendo el ancho primero, así:

 // You could put anything for the 200 height since you will be changing it in the next line anyway. [_quoteLabel setFrame: CGRectMake(11, 11, 298, 200]; [_quoteLabel sizeToFitMultipleLines]; 

Terminé de resolver el problema utilizando una única UILabel y CoreText con una NSAttributedString . Una especie de cop-out, pero funciona.