GeckoGeek.fr

Paradigme d'un lézard

Samedi 22 Juillet 2017

Utiliser un UIButton dans une UIView sur iPhone

Par Lya le 08/11/2009 dans Apple, Programmation | 10 commentaires

Voici le premier billet d’une petite série sur la programmation iPhone. Pour commencer, nous allons voir comment ajouter un bouton à une view et réceptionner l’événement clic de ce bouton. A chaque clic nous incrémenterons un compteur que nous afficherons sur la même view. Ces notions nous serons utiles pour le second billet de la série.

SDK-iPhone

Création d’une UIView

View vide

Tout d’abord, nous allons créer la view. Ajoutons deux nouveaux fichiers à notre projet : CounterView.h & CounterView.m. Comme nous n’avons aucun élément dedans pour le moment, notre .h se limite à ceci :

CounterView.h

@interface CounterView : UIView {

}

@end

Dans le .m, nous implémentons l’interface que nous venons de décrire et nous lui demandons de prendre en paramètre de sa routine d’initialisation, la place qu’elle prendra dans la fenêtre (CGRect frame) :

CounterView.m

#import "CounterView.h"

@implementation CounterView;

-(id) initWithFrame : (CGRect)frame {

  // Call the UIView constructor
  self = [ super initWithFrame : frame ];

  if(self != nil) {

    // View's objects & parameters

  }

  // Return the view
  return self;

}

- (void)dealloc {

  NSLog(@"\tDealloc CounterView");
  [ super dealloc ];

}

@end

Background d’une view

Maintenant que notre view existe, nous pouvons lui ajouter un background. Nous avons plusieurs possibilités. Soit nous fixons une couleur de fond, soit nous définissons une image de background (ou les deux en même temps ^^). Pour fixer la couleur de fond à blanc par exemple, nous devons rajouter cette ligne dans le .m :

if(self != nil) {

  // View's objects & parameters
  [ self setBackgroundColor: [ UIColor colorWithRed:255 green:255 blue:255 alpha:255 ] ];		

}

Si nous souhaitons ajouter une image de fond, nous devons définir une UIImageView dans le .h. Nous l’initialisons alors avec une UIImage, la paramétrons (préciser sa position par exemple) et l’ajoutons en calque à la view dans le .m.

CounterView.h

@interface CounterView : UIView {

  UIImageView *viewBackground;

}

@end

CounterView.m

if(self != nil) {

  // View's objects & parameters
  UIImage *imageBackground;

  imageBackground = [ UIImage imageNamed:@"myBackgroundImage.png" ];
  viewBackground = [[ UIImageView alloc ] initWithImage: imageBackground ];
  // Image's position on the view
  viewBackground.layer.position = CGPointMake(imageBackground.size.width/2, imageBackground.size.height/2);

  [ self setBackgroundColor: [ UIColor colorWithRed:255 green:255 blue:255 alpha:255 ] ];
  [ self.layer addSublayer:viewBackground.layer ];

}

Voilà nous avons une view qui prend toute la fenêtre avec un image centrée et un fond blanc.

Ajouter un UIButton et un UILabel à la view

Ajout des éléments

Maintenant, nous allons ajouter deux éléments, un bouton et un label, et les afficher dans la view.

CounterView.h

@interface CounterView : UIView {

  UIImageView *viewBackground;
  UIButton *buttonCount;
  UILabel *labelCounter;

}

@end

Dans le .m nous initialisons nos deux éléments et nous indiquons leur taille et leur position sur la fenêtre. N’oublions pas également de les ajouter à la view.

CounterView.m

if(self != nil) {

  // View's objects & parameters
  UIImage *imageBackground;

  imageBackground = [ UIImage imageNamed:@"myBackgroundImage.png" ];
  viewBackground = [[ UIImageView alloc ] initWithImage: imageBackground ];
  // Image's position on the view
  viewBackground.layer.position = CGPointMake(imageBackground.size.width/2, imageBackground.size.height/2);

  // Button Count
  buttonCount = [UIButton buttonWithType:UIButtonTypeRoundedRect ];
  // Position & Size : CGRectMake(posx, posy, width, height)
  [ buttonCount setFrame: CGRectMake(frame.size.width/2 - 60, 250, 120, 45) ];
  // Set button label
  [ buttonCount setTitle:@"Increase?" forState:UIControlStateNormal ];

  // Label counter
  labelCounter = [[ UILabel alloc ] initWithFrame:CGRectMake(frame.size.width/2 - 60, 190, 120, 45) ];
  [ labelCounter setBackgroundColor: [ UIColor colorWithWhite:0.0 alpha:0.0 ] ];
  [ labelCounter setTextColor: [ UIColor colorWithWhite:0.0 alpha:1.0 ] ];
  [ labelCounter setTextAlignment: UITextAlignmentCenter ];
  [ labelCounter setFont: [ UIFont fontWithName:@"Marker Felt" size:22.0 ] ];
  [ labelCounter setText: @"0\n" ];
  [ labelCounter setAutoresizesSubviews:TRUE ];

  [ self setBackgroundColor: [ UIColor colorWithRed:255 green:255 blue:255 alpha:255 ] ];
  [ self.layer addSublayer:viewBackground.layer ];
  // Add the button to the view
  [ self addSubview:buttonCount ];
  // Add the label to the view
  [ self addSubview:labelCounter ];

  [ labelCounter release ];

}

Fonctionnalités des éléments

Pour le bouton, il est possible de changer le label (ou sa couleur) en fonction de l’état (highlighted, …) :

  [ buttonCount setTitle:@"Increase!" forState:UIControlStateHighlighted ];

Vous pouvez également lui donner une image à la place du label :

  [ buttonApropos setBackgroundImage:[ UIImage imageNamed:@"buttonImage.png" ] forState:UIControlStateNormal ];
  [ buttonApropos setBackgroundImage:[ UIImage imageNamed:@"buttonImageHighlighted.png" ] forState:UIControlStateHighlighted];

Vous pouvez aussi l’activer ou le désactiver :

  [ buttonCount setUserInteractionEnabled:YES ];

N’hésitez pas à regarder la documentation de la classe UIButton (et UILabel) pour plus d’informations sur ses méthodes et attributs ;-]

Gérer l’événement clic

Ajoutons dans le .m une action qui intervient quand un événement clic est détecté sur le bouton.

  [ buttonCount addTarget:self action:@selector(changeCounter:) forControlEvents:UIControlEventTouchUpInside ];

Nous venons de marquer que si l’on clique (événement) sur le bouton (cible), alors la méthode changeCounter (action) sera appelée. Il ne nous reste qu’à la définir dans le .h et à l’écrire en dessous du constructeur dans le .m :

- (void)changeCounter:(id)sender {

  [ labelCounter setText: [ NSString stringWithFormat:@"%d", ([ labelCounter.text intValue ] + 1) ]];

}

Conclusion

Voici les fichiers finaux que nous obtenons (sans oublier de désallouer les objets que nous avons ajouté dans la view) :

CounterView.h

@interface CounterView : UIView {

  UIImageView *viewBackground;
  UIButton *buttonCount;
  UILabel *labelCounter;

}

- (void)changeCounter:(id)sender;

@end

CounterView.m

#import "CounterView.h"

@implementation CounterView;

-(id) initWithFrame : (CGRect)frame {

  // Call the UIView constructor
  self = [ super initWithFrame : frame ];

  if(self != nil) {

    // View's objects & parameters
    UIImage *imageBackground;

    imageBackground = [ UIImage imageNamed:@"myBackgroundImage.png" ];
    viewBackground = [[ UIImageView alloc ] initWithImage: imageBackground ];
    // Image's position on the view
    viewBackground.layer.position = CGPointMake(imageBackground.size.width/2, imageBackground.size.height/2);

    // Button Count
    buttonCount = [UIButton buttonWithType:UIButtonTypeRoundedRect ];
    // Position & Size : CGRectMake(posx, posy, width, height)
    [ buttonCount setFrame: CGRectMake(80, 250, 120, 45) ];
    // Set button label
    [ buttonCount setTitle:@"Increase?" forState:UIControlStateNormal ];
    [ buttonCount setTitle:@"Increase!" forState:UIControlStateHighlighted ];
    [ buttonCount addTarget:self action:@selector(changeCounter:) forControlEvents:UIControlEventTouchUpInside ];

    // Label counter
    labelCounter = [[ UILabel alloc ] initWithFrame:CGRectMake(80, 190, 120, 45) ];
    [ labelCounter setBackgroundColor: [ UIColor colorWithWhite:0.0 alpha:0.0 ] ];
    [ labelCounter setTextColor: [ UIColor colorWithWhite:0.0 alpha:1.0 ] ];
    [ labelCounter setTextAlignment: UITextAlignmentCenter ];
    [ labelCounter setFont: [ UIFont fontWithName:@"Marker Felt" size:22.0 ] ];
    [ labelCounter setText: @"0\n" ];
    [ labelCounter setAutoresizesSubviews:TRUE ];

    [ self.layer addSublayer:viewBackground.layer ];
    [ self setBackgroundColor: [ UIColor colorWithRed:255 green:255 blue:255 alpha:255 ] ];
    // Add the button to the view
    [ self addSubview:buttonCount ];
    // Add the label to the view
    [ self addSubview:labelCounter ];

    [ labelCounter release ];

  }

  // Return the id of this view
  return self;

}

- (void)changeCounter:(id)sender {

  [ labelCounter setText: [ NSString stringWithFormat:@"%d", ([ labelCounter.text intValue ] + 1) ]];

}
- (void)dealloc {

  NSLog(@"\tDealloc CounterView");
  [ labelCounter release ];
  [ viewBackground release ];
  [ super dealloc ];

}

@end

N’oubliez pas de rajouter les images que vous utilisez à votre projet ;-]

Normalement, la view devrait seulement afficher des données. Tout ce qui est calcul ne devrait pas s’y trouver. Cette partie doit être gérée par un contrôleur. C’est ce que nous verrons dans un second billet.

Commentaires (10)
  1. Maxxx le 22 Apr 2010 à 14:16

    Bonjour,

    Cette série de Tuto est très intéressant !!!
    Cependant j’aimerais savoir sur quoi vous développez tout ceci ??? J’ai pour ma part commencer avec Xcode et IB, mais la je ne comprends pas ou vous développé tout ceci !!!

    J’espère avoir était clair dans mes interrogation.

    Bonne continuation

    Cordialement.

  2. Vinz le 22 Apr 2010 à 17:23

    Hello :-)
    On développe sous xCode ^^
    C’est juste qu’on utilise pas IB (on aime pas ^^), donc on programme chaque classe (.h et .m)
    Bon codage 😉
    Vincent

  3. Maxxx le 23 Apr 2010 à 16:46

    Encore une petite question 😀

    Vous n’utilisez pas IB d’accord, mais les fichier .xib (qui sont les vues) vous ne les éditez pas non plus ???

    Je débute et j’ai bien du mal a faire les différentes liaison sur IB, c’est pourquoi votre méthode m’intéresse au plus au point.
    Cordialement

  4. Vinz le 23 Apr 2010 à 16:51

    Re !
    En fait, si on utilise pas XIB (créés par IB), c’est parce qu’on aime bien savoir ce qui se passe dans un code ^^
    Un XIB est effectivement une sorte de vue. Par exemple tu vas avoir un mainWindow.xib et nous à la place on va faire un alloc d’un UIWindow dans notre code.
    C’est juste qu’au lieu d’utiliser un xib (derrière y’a des allocation mémoire), on fait les alloc nous même :-)
    Faudrait que je vois ce week-end si je retrouve un “hello world” sans xib 😉
    A+

  5. Maxxx le 27 Apr 2010 à 11:12

    Merci pour cette réponse aussi rapide.

    Lorsque je crée un projet le mainWindows.xib est créé. C’est lui qui est appelé automatiquement a l’exécution.
    Ma question est la suivante comment faire l’appel à la vue que l’on peut créer avec l’exemple si dessus ???

  6. Vinz le 27 Apr 2010 à 11:46

    Re,
    Dans ton AppDelegate.m il faudrait que tu rajoutes ces lignes :
    // Init Window
    self.window = [ [ [ UIWindow alloc ] initWithFrame:[ [ UIScreen mainScreen ] bounds ] ]
    autorelease
    ];
    Sachant que ton AppDelegate.h devrait contenir :
    @property (nonatomic, retain) UIWindow *window;
    Et toujours dans ton AppDelegate.m pour afficher une view tu fais :
    [ window addSubview:viewController.view ];
    [ window makeKeyAndVisible ];
    Et ATTENTION ! dans ton .plist (la configuration de ton app), il faut supprimer la liste qui dit que ton mainWindow est lancé par défaut ^^
    En principe ça devrait fonctionner… au pire up moi ton projet test xcode et puis j’irai te le modifier.
    A+ !

  7. Maxxx le 29 Apr 2010 à 08:39

    Re-bonjour !!!

    Après plusieurs essais infructueux, ma vue ne se lance toujours pas !!!
    Auriez vous une adresse-mail, pour que je puisse vous faire parvenir mon projet ??

    Cordialement

  8. Vinz le 29 Apr 2010 à 13:04

    Re !
    Envoie ça à contact _at_ geckogeek.fr (remplace le at comme il faut ;-)) et avec quelques commentaires sur ton projet, je regarderai ce soir.
    Vinz

  9. DonSilya le 1 Jun 2010 à 14:39

    Bonjour,

    Je développe une application iPhone et j’ai un petit souci.

    Je souhaiterai connaître la postion d’un UITableView à un instant donné.

    pour cela, j’ai essayé ce code mais il ne me donne que la taille (alors que je souhaite avoir la position) :
    Code:
    CGFloat x = [[self view] frame].size.width/2;
    CGFloat y = [[self view] frame].size.height/2;
    [waitView setFrame:CGRectMake(x,y,300,300)];
    [self.view addSubview:maView];

    Merci d’avance pour vos réponses

  10. Vinz le 1 Jun 2010 à 16:33

    Hello !
    En principe tu as l’élèment origin qui devrait pouvoir te donner des informations :-) “frame.origin”
    Puis tu as “frame.origin.x” ou “frame.origin.y”
    Donc dans ton cas cela devrait donner :
    [[self view] frame].origin
    A tester :-)


Laisser un commentaire