Dans le constructeur d'interface, maintenant Command + = redimensionnera un bouton pour adapter son texte. Je me demandais si cela était possible par programmation avant que le bouton ne soit ajouté à la vue.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button.titleLabel setFont:[UIFont fontWithName:@"Arial-BoldMT" size:12]];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
// I need to know the width needed to accomodate NSStringVariable
[button setTitle:NSStringVariable forState:UIControlStateNormal];
// So that I can set the width property of the button before addSubview
[button setFrame:CGRectMake(10, 0, width, fixedHeight)];
[subNavigation addSubview:button];
Dans Xcode 4.5 et supérieur, cela peut maintenant être fait en utilisant ' Auto-layouting/Constraints '.
Les principaux avantages sont les suivants:
Quelques inconvénients:
La chose la plus cool est que nous nous concentrons sur la déclaration d'une intention telle que:
Ici est un tutoriel simple pour se familiariser avec la mise en page automatique.
Pour un plus de détails .
Cela prend du temps au début, mais il semble que cela en vaudra la peine.
Dans UIKit, il y a des ajouts à la classe NSString pour obtenir, à partir d'un objet NSString donné, la taille qu'il prendra lorsqu'il sera restitué dans une police donnée.
Docs était ici . Maintenant, c'est ici sous Obsolète.
En bref, si vous y allez:
CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:14]];
//or whatever font you're using
[button setFrame:CGRectMake(10,0,stringsize.width, stringsize.height)];
... vous aurez défini le cadre du bouton sur la hauteur et la largeur de la chaîne que vous restiturez.
Vous voudrez probablement expérimenter avec un espace tampon autour de cette taille CGSize, mais vous commencerez au bon endroit.
La manière de faire ceci dans le code est:
[button sizeToFit];
Si vous sous-classez et souhaitez ajouter des règles supplémentaires, vous pouvez remplacer:
- (CGSize)sizeThatFits:(CGSize)size;
Si votre bouton a été créé avec Interface Builder et que vous modifiez le titre en code, vous pouvez procéder comme suit:
[self.button setTitle:@"Button Title" forState:UIControlStateNormal];
[self.button sizeToFit];
Swift:
La chose importante ici est when appellerez-vous la .sizeToFit()
, elle devrait l'être après avoir défini le texte à afficher pour qu'il puisse lire la taille requise, si vous mettez le texte à jour ultérieurement, appelez ensuite ça encore.
var button = UIButton()
button.setTitle("Length of this text determines size", forState: UIControlState.Normal)
button.sizeToFit()
self.view.addSubview(button)
Pour ce faire, utilisez autolayout, essayez de définir une contrainte de largeur variable:
Vous devrez peut-être aussi ajuster votre Content Hugging Priority
et Content Compression Resistance Priority
pour obtenir les résultats dont vous avez besoin.
UILabel est complètement auto-dimensionnant automatiquement :
Ce UILabel est simplement configuré pour être centré sur l'écran (deux contraintes seulement, horizontal/vertical):
Il change les largeurs de manière totalement automatique:
Vous n'avez pas besoin de définir la largeur ou la hauteur - c'est totalement automatique.
Notez que les petits carrés jaunes sont simplement attachés ("espacement" de zéro). Ils se déplacent automatiquement lorsque UILabel redimensionne.
L'ajout d'une contrainte "> =" définit une largeur minimale pour UILabel:
Si vous souhaitez redimensionner le texte par opposition au bouton, vous pouvez utiliser ...
button.titleLabel.adjustsFontSizeToFitWidth = YES;
button.titleLabel.minimumScaleFactor = .5;
// The .5 value means that I will let it go down to half the original font size
// before the texts gets truncated
// note, if using anything pre ios6, you would use I think
button.titleLabel.minimumFontSize = 8;
sizeToFit ne fonctionne pas correctement. au lieu:
myButton.size = myButton.sizeThatFits(CGSize.zero)
vous pouvez aussi ajouter contentInset
au bouton:
myButton.contentEdgeInsets = UIEdgeInsetsMake(8, 8, 4, 8)
Simplement:
UIView
comme enveloppe avec une disposition automatique des vues.UILabel
à l'intérieur de cette enveloppe. Ajoutez des contraintes qui colleront votre étiquette sur les bords de l'emballage.UIButton
dans votre wrapper, puis ajoutez simplement les mêmes contraintes que pour UILabel
.J'ai quelques besoins supplémentaires liés à ce poste que sizeToFit
ne résout pas. Je devais garder le bouton centré à son emplacement d'origine, quel que soit le texte. Je ne veux jamais non plus que le bouton soit plus grand que sa taille d'origine.
Donc, je mets en forme le bouton pour sa taille maximale, enregistre cette taille dans le contrôleur et utilise la méthode suivante pour redimensionner le bouton lorsque le texte change:
+ (void) sizeButtonToText:(UIButton *)button availableSize:(CGSize)availableSize padding:(UIEdgeInsets)padding {
CGRect boundsForText = button.frame;
// Measures string
CGSize stringSize = [button.titleLabel.text sizeWithFont:button.titleLabel.font];
stringSize.width = MIN(stringSize.width + padding.left + padding.right, availableSize.width);
// Center's location of button
boundsForText.Origin.x += (boundsForText.size.width - stringSize.width) / 2;
boundsForText.size.width = stringSize.width;
[button setFrame:boundsForText];
}
Swift 4.2
Dieu merci, ceci est résolu. Après avoir défini un texte sur le bouton, vous pouvez récupérer le paramètre intrinsicContentSize, qui correspond à la taille naturelle d’un UIView (le document officiel est ici ). Pour UIButton, vous pouvez l’utiliser comme ci-dessous.
button.intrinsicContentSize.width
Pour votre information, j'ai ajusté la largeur pour lui donner une apparence correcte.
button.frame = CGRect(fx: xOffset, y: 0.0, width: button.intrinsicContentSize.width + 18, height: 40)
Simulateur
boutons UIB avec intrinsicContentSize
Source: https://riptutorial.com/ios/example/16418/get-uibutton-s-size-strictly-based-on-its-text-and-font
Cette classe de boutons à autoréglage en hauteur pour le texte (pour Xamarin mais peut être réécrite pour une autre langue)
[Register(nameof(ResizableButton))]
public class ResizableButton : UIButton
{
NSLayoutConstraint _heightConstraint;
public bool NeedsUpdateHeightConstraint { get; private set; } = true;
public ResizableButton(){}
public ResizableButton(UIButtonType type) : base(type){}
public ResizableButton(NSCoder coder) : base(coder){}
public ResizableButton(CGRect frame) : base(frame){}
protected ResizableButton(NSObjectFlag t) : base(t){}
protected internal ResizableButton(IntPtr handle) : base(handle){}
public override void LayoutSubviews()
{
base.LayoutSubviews();
UpdateHeightConstraint();
InvalidateIntrinsicContentSize();
}
public override void SetTitle(string title, UIControlState forState)
{
NeedsUpdateHeightConstraint = true;
base.SetTitle(title, forState);
}
private void UpdateHeightConstraint()
{
if (!NeedsUpdateHeightConstraint)
return;
NeedsUpdateHeightConstraint = false;
var labelSize = TitleLabel.SizeThatFits(new CGSize(Frame.Width - TitleEdgeInsets.Left - TitleEdgeInsets.Right, float.MaxValue));
var rect = new CGRect(Frame.X, Frame.Y, Frame.Width, labelSize.Height + TitleEdgeInsets.Top + TitleEdgeInsets.Bottom);
if (_heightConstraint != null)
RemoveConstraint(_heightConstraint);
_heightConstraint = NSLayoutConstraint.Create(this, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1, rect.Height);
AddConstraint(_heightConstraint);
}
public override CGSize IntrinsicContentSize
{
get
{
var labelSize = TitleLabel.SizeThatFits(new CGSize(Frame.Width - TitleEdgeInsets.Left - TitleEdgeInsets.Right, float.MaxValue));
return new CGSize(Frame.Width, labelSize.Height + TitleEdgeInsets.Top + TitleEdgeInsets.Bottom);
}
}
}