Reproducción automática: el tamaño intrínseco del button UIB no incluye inserciones de títulos.

Si tengo un button UIB configurado con autolayout, su tamaño se ajusta muy bien para adaptarse a su contenido.

Si configuro una image como button.image , el tamaño de button.image parece explicar esto.

Sin embargo, si titleEdgeInsets el titleEdgeInsets del button, el layout no count con esto y, en su lugar, trunca el título del button.

¿Cómo puedo asegurarme de que el ancho intrínseco del button representa el recuadro?

introduzca la descripción de la imagen aquí

Editar:

Estoy usando lo siguiente:

 [self.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)]; 

El objective es agregar cierta separación entre la image y el text.

Puede resolver esto sin tener que anular ningún método o establecer una restricción de ancho arbitrario. Puede hacerlo todo en Interface Builder de la siguiente manera.

  • El ancho del button intrínseco se deriva del ancho del título más el ancho del icono más las inserciones del borde del contenido izquierdo y derecho.

  • Si un button tiene una image y un text, se centran como un grupo, sin relleno entre ellos.

  • Si agrega un recuadro de contenido izquierdo, se calcula en relación con el text, no el text + icono.

  • Si configura una inserción negativa de image izquierda, la image se despliega hacia la izquierda, pero el ancho general del button no se ve afectado.

  • Si establece un recuadro negativo de image izquierda, el layout real usa la mitad de ese valor. Por lo tanto, para get un recuadro de 20 puntos, debe usar un valor de recuadro de -40 puntos en Interface Builder.

Por lo tanto, proporciona un recuadro de contenido izquierdo lo suficientemente grande como para crear espacio tanto para el recuadro izquierdo deseado como para el recuadro interno entre el icono y el text, y luego desplace el icono hacia la izquierda duplicando la cantidad de relleno que desea entre el icono y el text. El resultado es un button con inserciones iguales de contenido izquierdo y derecho, y un par de text e icons centrados en un grupo, con una cantidad específica de relleno entre ellos.

Algunos valores de ejemplo:

 // Produces a button with the layout: // |-20-icon-10-text-20-| // AutoLayout intrinsic width works as you'd desire. button.contentEdgeInsets = UIEdgeInsetsMake(10, 30, 10, 20) button.imageEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0) 

Puede hacer que esto funcione en Interface Builder (sin escribir ningún código), mediante el uso de una combinación de inserciones de título y contenido negativas y positivas.

introduzca la descripción de la imagen aquí

Actualización : Xcode 7 tiene un error en el que no puede ingresar valores negativos en el campo Recuadro Right , pero puede usar el control paso a paso al lado para disminuir el valor. (Gracias Stuart)

Al hacer esto, se agregará 8 pt de espacio entre la image y el título y se boostá el ancho intrínseco del button en la misma cantidad. Me gusta esto:

introduzca la descripción de la imagen aquí

¿Por qué no anular el método intrinsicContentSize en UIView? Por ejemplo:

 - (CGSize) intrinsicContentSize { CGSize s = [super intrinsicContentSize]; return CGSizeMake(s.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right, s.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom); } 

Esto debería indicar al sistema de reproducción automática que debería boost el tamaño del button para permitir las inserciones y mostrar el text completo. No estoy en mi propia computadora, así que no lo he probado.

No ha especificado cómo configura los recuadros, así que supongo que está utilizando titleEdgeInsets porque veo el mismo efecto que obtiene. Si uso contentEdgeInsets en su lugar funciona correctamente.

 - (IBAction)ChangeTitle:(UIButton *)sender { self.button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20); [self.button setTitle:@"Long Long Title" forState:UIControlStateNormal]; } 

Este hilo es un poco viejo, pero me topé con esto y pude resolverlo usando un recuadro negativo. Por ejemplo, sustituya los valores de relleno deseados aquí:

 UIButton* myButton = [[UIButton alloc] init]; // setup some autolayout constraints here myButton.titleEdgeInsets = UIEdgeInsetsMake(-desinetworkingBottomPadding, -desinetworkingRightPadding, -desinetworkingTopPadding, -desinetworkingLeftPadding); 

¡Combinado con las limitaciones correctas de la reproducción automática, termina con un button de cambio de tamaño automático que contiene una image y un text! Se ve a continuación con el desinetworkingLeftPadding Set de desinetworkingLeftPadding establecido en 10.

Botón con image y text corto

Botón con image y text largo

Puede ver que el marco real del button no abarca la label (ya que la label se desplaza 10 puntos hacia la derecha, fuera de los límites), pero hemos logrado 10 puntos de relleno entre el text y la image.

Y para Swift funcionó esto:

 extension UIButton { public override func intrinsicContentSize() -> CGSize { let intrinsicContentSize = super.intrinsicContentSize() let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom return CGSize(width: adjustedWidth, height: adjustedHeight) } } 

Amor u swift

Todo lo anterior no funcionó para iOS 9+ , lo que hice es:

  • Agregue una restricción de ancho (para un ancho mínimo cuando el button no tiene text. El button escalará automáticamente si se proporciona text)
  • establezca la relación con Greater Than o Equal

introduzca la descripción de la imagen aquí

Ahora para agregar un borde alnetworkingedor del button solo usa el método:

 button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20); 

La opción también está disponible en el generador de interfaces. Mira el recuadro. Puse a izquierda y derecha a 3. Funciona como un encanto.

Capturador de interfaz de pantalla

Quería agregar un espacio de 5 pt entre mi ícono de UIB y la label. Así es como lo logré:

 UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeCustom]; // more button config etc infoButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 5); infoButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, -5); 

La forma en que contentEdgeInsets, titleEdgeInsets y imageEdgeInsets se relacionan entre sí requiere un pequeño dar y recibir de cada inserción. Por lo tanto, si agrega algunas inserciones a la izquierda del título, debe agregar un recuadro negativo a la derecha y proporcionar más espacio (a través de un recuadro positivo) en el derecho de contenido.

Al agregar un recuadro de contenido adecuado para que coincida con el cambio de las inserciones del título, mi text no sale de los límites del button.

La solución que uso es agregar una restricción de ancho en el button. Luego, en algún lugar de la initialization, una vez que su text está configurado, actualice la restricción de ancho de la siguiente manera:

self.buttonWidthConstraint.constant = self.shareButton.intrinsicContentSize.width + 8;

Donde 8 es lo que sea su inserción.

Para Swift 3 basado en la respuesta de pegpeg :

 extension UIButton { override open var intrinsicContentSize: CGSize { let intrinsicContentSize = super.intrinsicContentSize let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom return CGSize(width: adjustedWidth, height: adjustedHeight) } }