web-dev-qa-db-fra.com

Utilisation d'images extensibles dans les storyboards Xcode

J'utilise des storyboards pour disposer mes contrôleurs de vue et je voudrais utiliser des images extensibles pour mes boutons (de sorte que je n'ai pas besoin de générer plusieurs images de tailles différentes).

Est-il possible de le faire directement dans les story-boards sans écrire de code? J'aime vraiment la possibilité d'utiliser des storyboards pour tous les trucs graphiques et de garder le code propre des trucs d'interface utilisateur, mais il semble que je ne peux pas m'en tirer ici.

Si ce n'est pas possible, que suggéreriez-vous autrement?

33
Joel

Mise à jour pour iOS 7 +
iOS 7+ prend désormais en charge les images extensibles en mode natif via le catalogue d'actifs. À l'aide du catalogue de ressources, vous pouvez désormais spécifier la façon dont les images sont découpées et leur échelle (étirement ou mosaïque). Ces attributs de catalogue d'actifs pour l'image seront immédiatement reflétés dans le storyboard. Grande nouvelle amélioration. Pour plus d'informations, consultez Documents d'Apple sur le catalogue d'actifs

Pour le déploiement sur les versions iOS avant 7:
C'est un fait peu connu, mais vous pouvez absolument définir des encarts de cap d'une image en utilisant uniquement Interface Builder/Storyboard et les propriétés d'étirement dans l'inspecteur d'attributs. Merci à Victor pour la réponse originale.

En regardant les propriétés d'étirement dans l'inspecteur d'attributs d'un UIImage, les valeurs X et Y sont les positions du point de départ de l'étirement, par rapport à toute la largeur et la hauteur de l'image. Une valeur de 0,5 signifierait un point au milieu de l'image.

La largeur et la hauteur sont des tailles pour la zone extensible par rapport à la taille de l'image. Ainsi, définir la largeur à une valeur de 1/imageWidth définirait la zone extensible à 1px de large.

La plupart des images extensibles s'étireront du milieu, donc l'utilisation de ces valeurs pour X, Y, largeur et hauteur fonctionnera généralement:

X = 0.5
Y = 0.5
Width = 1/imageWidth
Height = 1/imageHeight

Remarque: Sauf si vous avez une très petite image que vous étirez, cela signifie que les propriétés de largeur et de hauteur seront très petites (par exemple 0,008) et 0,0 peut être utilisé à la place. Donc, pratiquement, 0,5, 0,5, 0,0, 0,0 fonctionneront presque toujours pour X, Y, Largeur et Hauteur.

Dans le petit nombre de cas où 0,0 ne fonctionne pas pour la largeur et la hauteur, cela signifie que vous devez utiliser une calculatrice pour définir ces valeurs dans IB. Cependant, je pense que c'est généralement préférable que d'avoir à le définir par programme car vous pourrez voir l'image étirée résultante en IB (WYSIWYG).

Stretchable image attributes

Mise à jour: Certaines personnes ont souligné que bien que l'étirement des images fonctionne dans Storyboard en utilisant les suggestions ci-dessus, l'étirement des images sur les boutons est toujours cassé, même à partir d'iOS7. Ne vous inquiétez pas, cela est facilement résolu en créant une catégorie UIButton qui prend en charge la définition des encarts de cap pour les états de contrôle:

@implementation UIButton (Stretchable)

/* Automatically set cap insets for the background image. This assumes that
   the image is a standard slice size with a 1 px stretchable interior */
- (void)setBackgroundImageStretchableForState:(UIControlState)controlState
{
    UIImage *image = [self backgroundImageForState:controlState];
    if (image)
    {
       CGFloat capWidth =  floorf(image.size.width / 2);
       CGFloat capHeight =  floorf(image.size.height / 2);
       UIImage *capImage = [image resizableImageWithCapInsets:
                     UIEdgeInsetsMake(capHeight, capWidth, capHeight, capWidth)];

       [self setBackgroundImage:capImage forState:controlState];
    }
}

En utilisant cette catégorie, vous pouvez définir votre image extensible pour votre bouton via Storyboard, puis vous assurer facilement qu'elle s'étire correctement en appelant -setBackgroundImageStretchableForState: dans ton -viewDidLoad. L'itération dans votre hiérarchie de vues rend cela insignifiant même pour un grand nombre de boutons dans votre vue:

NSPredicate *predicate = 
    [NSPredicate predicateWithFormat:@"self isKindOfClass:%@",[UIButton class]];
NSArray *buttons = [self.view.subviews filteredArrayUsingPredicate:predicate];
for (UIButton *button in buttons)
   [button setBackgroundImageStretchableForState:UIControlStateNormal];

Bien que ce ne soit pas aussi bon que d'avoir une sous-classe UIButton qui le fait automatiquement pour vous (la sous-classe UIButton n'est pas pratique car c'est un cluster de classes), cela vous donne presque la même chose fonctionnalité avec juste un peu de code passe-partout dans votre viewDidLoad - vous pouvez définir toutes vos images de bouton dans Storyboard et toujours les étirer correctement.

73
memmons

Avec Xcode 6 (et iOS7 + cible), vous pouvez utiliser l'éditeur de découpage lorsque vous travaillez avec des ressources d'images. Basculez le mode de découpage avec Editeur -> Afficher le menu de découpage ou appuyez sur Afficher le découpage lorsque vous sélectionnez une image spécifique avec l'éditeur (illustré ci-dessous).

Show Slicing button

Ensuite, vous pouvez sélectionner l'image pour une échelle d'affichage spécifique et faire glisser les règles ou modifier manuellement les valeurs des encarts.

Rules

Après cela, vous pouvez sélectionner cette image dans Interface Builder. Par exemple, je l'utilise pour UIButton Image de fond (La représentation du bouton IB peut sembler mauvaise, mais elle devrait être correcte lorsque fonctionnement).

Mes boutons semblent bien (exécutant le simulateur iOS 7.1 et le périphérique iOS 8).

enter image description here

Cela Apple doc link pourrait être utile.

14
Anton Gaenko

C'est faisable dans le générateur d'interface 5.0 de XCode avec le catalogue d'actifs. Créez un élément d'image (si vous ne disposez pas déjà d'un catalogue d'éléments, vous pouvez en créer un comme suit:

  1. File-> New-> File-> Resources-> Asset Catalog
  2. Puis Editor-> New Image Set
  3. Définissez les images pour chaque Idiom & Scale
  4. Appuyez ensuite sur Show Slicing pour régler les tranches comme vous le souhaitez.

Cochez Apple docs ici: Développeur Apple: Aide du catalogue d'actifs Ensuite, tout ce que vous avez à faire est de définir l'image d'arrière-plan du bouton comme l'actif demandé.

EDIT: j'ai oublié de mentionner que cela fonctionne comme souhaité uniquement dans iOS7

11
Lorenzo NEY

Voici ce que j'ai fait: j'ai défini une prise pour le bouton et l'ai connecté, puis j'ai fait cela dans viewDidLoad:

[self.someButton setBackgroundImage:[[self.someButton backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];

Cela fait en sorte qu'il réutilise l'image que vous avez définie dans le storyboard, donc si vous la changez d'une couleur à une autre, cela fonctionnera, tant que les encarts ne changeront pas.

Pour une vue qui avait beaucoup de ces choses, je l'ai fait:

for (UIView * subview in self.view.subviews) {
        if ([subview isKindOfClass:[UIImageView class]] && subview.tag == 10) {
            UIImageView* textFieldImageBackground = (UIImageView*)subview;
            textFieldImageBackground.image = [textFieldImageBackground.image stretchableImageWithLeftCapWidth:7 topCapHeight:5];
        } else if([subview isKindOfClass:[UIButton  class]] && subview.tag == 11) {
            UIButton * button = (UIButton*)subview;
            [button setBackgroundImage:[[button backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];
        }
    }

Notez que j'ai défini les balises pour toutes celles que je voulais étirer.

Je suis dans le même bateau que vous, j'aimerais pouvoir mettre ces choses très centrées sur l'interface utilisateur sur le storyboard lui-même.

2
Philippe Sabourin

Utilisez la fonction de découpage Xcode pour spécifier les dimensions d'une zone centrale redimensionnable de l'image et pour spécifier éventuellement des embouts, qui sont des zones de l'image qui ne doivent pas être remplies par la zone redimensionnable. Voir À propos des catalogues d'actifs

0
backslash112