web-dev-qa-db-fra.com

Case à cocher dans l'application iOS

J'ai besoin d'ajouter des contrôles de case à cocher à mon formulaire. Je sais qu’il n’existe pas de contrôle de ce type dans le SDK iOS. Comment pourrais-je faire ça?

34
saikamesh

cela m'a rendu fou aussi et j'ai trouvé une solution différente qui fonctionne bien pour moi et évite d'avoir à utiliser des images.

  1. Ajoutez un nouvel objet étiquette à Interface Builder.
  2. Créez une propriété IBOutlet dans Xcode et connectez-la. Dans le code ci-dessous, je l'ai appelé «entièrement payé» car je veux savoir si quelqu'un a entièrement payé une somme d'argent.
  3. Ajoutez les 2 fonctions ci-dessous. La fonction 'touchesBegan' vérifie si vous avez touché quelque part à l'intérieur de l'objet de libellé 'FullyPaid' et si oui, elle appelle la fonction 'togglePaidStatus' une case vide (\ u2610) et une case à cocher (\ u2611) respectivement. Ensuite, il compare ce qui se trouve actuellement dans l'objet 'FullyPaid' et le bascule avec l'autre chaîne.

Vous souhaiterez peut-être appeler la fonction togglePaidStatus dans la fonction viewDidLoad pour la définir initialement sur une chaîne vide.

Bien entendu, vous pouvez ajouter des vérifications supplémentaires pour empêcher les utilisateurs de basculer la case à cocher si le libellé n'est pas activé, mais ce n'est pas indiqué ci-dessous.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];   
    if (CGRectContainsPoint([fullyPaid frame], [touch locationInView:self.view]))
    {
        [self togglePaidStatus];
    }
}
-(void) togglePaidStatus
{
    NSString *untickedBoxStr = [[NSString alloc] initWithString:@"\u2610"];
    NSString *tickedBoxStr = [[NSString alloc] initWithString:@"\u2611"];   

    if ([fullyPaid.text isEqualToString:tickedBoxStr])
    {
        fullyPaid.text = untickedBoxStr;
    }
    else
    {
        fullyPaid.text = tickedBoxStr;
    }

    [tickedBoxStr release];
    [untickedBoxStr release];
}
31
Adrian

En règle générale, vous utiliseriez UISwitch pour une fonctionnalité de type case à cocher.

Vous pouvez toutefois utiliser votre propre contrôle en utilisant un contrôle d’image avec deux images (cochées/décochées) et en les commutant quand elles touchent le contrôle /

26
Eric Petroelje

Si vous affichez un groupe d'options et que l'utilisateur peut en sélectionner une, utilisez une vue de table avec un accessoire de coche et une couleur de texte différente sur la ligne sélectionnée.

Si vous avez une seule option, le mieux est d’utiliser un commutateur. Si vous ne pouvez ou ne voulez pas utiliser un bouton, définissez l'image normale sur une case vide et l'image sélectionnée sur une case à cocher. Vous devrez créer ces deux images vous-même ou trouver des illustrations graphiques à utiliser.

11
Brent Royal-Gordon

En prolongeant jusqu'à l'idée d'Adrean , j'ai réalisé cela en utilisant une approche très simple.
Mon idée est de changer le texte du bouton (disons checkBtn) en fonction de son état, puis de changer l’état du bouton dans sa IBAction.
Ci-dessous le code comment j'ai fait ceci:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [checkBtn setTitle:@"\u2610" forState:UIControlStateNormal];    // uncheck the button in normal state
    [checkBtn setTitle:@"\u2611" forState:UIControlStateSelected];  // check the button in selected state
}

- (IBAction)checkButtonTapped:(UIButton*)sender {
    sender.selected = !sender.selected;    // toggle button's selected state  

    if (sender.state == UIControlStateSelected) {    
        // do something when button is checked 
    } else {
        // do something when button is unchecked
    }
}
8
S1LENT WARRIOR

Voici ma version de la case à cocher pour iphone.

C'est une classe unique qui étend UIButton . C'est simple donc je vais le coller ici.

Contenu du fichier CheckBoxButton.h

#import <UIKit/UIKit.h>

@interface CheckBoxButton : UIButton

@property(nonatomic,assign)IBInspectable BOOL isChecked;

@end

Contenu du fichier CheckBoxButton.m

#import "CheckBoxButton.h"

@interface CheckBoxButton()

@property(nonatomic,strong)IBInspectable UIImage* checkedStateImage;
@property(nonatomic,strong)IBInspectable UIImage* uncheckedStateImage;

@end

@implementation CheckBoxButton

-(id)init
{
    self = [super init];

    if(self)
    {
        [self addTarget:self action:@selector(switchState) forControlEvents:UIControlEventTouchUpInside];
    }

    return self;
}

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if(self)
    {
        [self addTarget:self action:@selector(switchState) forControlEvents:UIControlEventTouchUpInside];
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    if(self)
    {
        [self addTarget:self action:@selector(switchState) forControlEvents:UIControlEventTouchUpInside];
    }

    return self;
}

-(void)setIsChecked:(BOOL)isChecked
{
    _isChecked = isChecked;

    if(isChecked)
    {
        [self setImage:self.checkedStateImage forState:UIControlStateNormal];
    }
    else
    {
        [self setImage:self.uncheckedStateImage forState:UIControlStateNormal];
    }
}

-(void)switchState
{
    self.isChecked = !self.isChecked;
    [self sendActionsForControlEvents:UIControlEventValueChanged];
}

@end

Vous pouvez définir des images à cocher/décocher ainsi que la propriété isChecked dans l'inspecteur d'attributs de visual studio.

enter image description here

Pour ajouter CheckBoxButton au storyboard ou à la xib, ajoutez simplement UIButton et définissez une classe personnalisée comme sur l'image suivante.

enter image description here

Button enverra un événement UIControlEventValueChanged à chaque fois que l'état isChecked est modifié.

6
slobodans

Je voulais faire cela par programme, et aussi résoudre le problème de la zone de contact était vraiment trop petite. Ceci est adapté de diverses sources, y compris Agha, le commentateur de Mike.

Dans votre entête

@interface YourViewController : UIViewController {
    BOOL checkboxSelected;
    UIButton *checkboxButton;
}

@property BOOL checkboxSelected;;
@property (nonatomic, retain) UIButton *checkboxButton;

-(void)toggleButton:(id)sender;

Et dans votre mise en œuvre

// put this in your viewDidLoad method. if you put it somewhere else, you'll probably have to change the self.view to something else
// create the checkbox. the width and height are larger than actual image, because we are creating the hit area which also covers the label
UIButton* checkBox = [[UIButton alloc] initWithFrame:CGRectMake(100, 60,120, 44)];  
[checkBox setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal];
// uncomment below to see the hit area
// [checkBox setBackgroundColor:[UIColor redColor]];
[checkBox addTarget:self action:@selector(toggleButton:) forControlEvents: UIControlEventTouchUpInside];
// make the button's image flush left, and then Push the image 20px left
[checkBox setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[checkBox setImageEdgeInsets:UIEdgeInsetsMake(0.0, 20.0, 0.0, 0.0)];
[self.view addSubview:checkBox];

// add checkbox text text
UILabel *checkBoxLabel = [[UILabel alloc] initWithFrame:CGRectMake(140, 74,200, 16)];
[checkBoxLabel setFont:[UIFont boldSystemFontOfSize:14]];
[checkBoxLabel setTextColor:[UIColor whiteColor]];
[checkBoxLabel setBackgroundColor:[UIColor clearColor]];
[checkBoxLabel setText:@"Checkbox"];
[self.view addSubview:checkBox];

// release the buttons
[checkBox release];
[checkBoxLabel release];

Et mettez cette méthode aussi:

- (void)toggleButton: (id) sender
{
    checkboxSelected = !checkboxSelected;
    UIButton* check = (UIButton*) sender;
    if (checkboxSelected == NO)
        [check setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal];
    else
        [check setImage:[UIImage imageNamed:@"checkbox-checked.png"] forState:UIControlStateNormal];

}
6
cannyboy

Le code de Everyones ici est très long, légèrement en désordre et pourrait être fait beaucoup plus simplement. J'ai un projet sur GitHub qui sous-classe UIControl que vous pouvez télécharger et extraire et vous donne un élément d'interface utilisateur presque checkbox:

https://github.com/Brayden/UICheckbox

4
Brayden

Sous-classe UIButton, déposez un bouton pour afficher le contrôleur, sélectionnez-le et remplacez le nom de la classe par CheckBox dans l'inspecteur d'identité.

#import "CheckBox.h"

@implementation CheckBox

#define checked_icon @"checked_box_icon.png"
#define empty_icon @"empty_box_icon.png"

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self)
    {
        [self setImage:[UIImage imageNamed:empty_icon] forState:UIControlStateNormal];
        [self addTarget:self action:@selector(didTouchButton) forControlEvents:UIControlEventTouchUpInside];
    }
    return self;
}

- (void)didTouchButton {
    selected = !selected;
    if (selected)
        [self setImage:[UIImage imageNamed:checked_icon] forState:UIControlStateNormal];
    else
        [self setImage:[UIImage imageNamed:empty_icon] forState:UIControlStateNormal];
}

@end
1
hasan

J'aime l'idée qu'Adrian utilise les caractères plutôt que les images. Mais je n'aime pas la boîte, elle n'a besoin que de la coche (@ "\ u2713"). Je dessine une boîte (une boîte arrondie) par programme et place un UILabel contenant la coche à l'intérieur. Cette méthode d'implémentation facilite l'utilisation de la vue personnalisée dans toute application sans se soucier des ressources dépendantes. Vous pouvez également personnaliser facilement la couleur de la coche, de la case arrondie et de l’arrière-plan. Voici le code complet:

#import <UIKit/UIKit.h>

@class CheckBoxView;

@protocol CheckBoxViewDelegate
- (void) checkBoxValueChanged:(CheckBoxView *) cview;
@end

@interface CheckBoxView : UIView {
    UILabel *checkMark;
    bool isOn;
    UIColor *color;
    NSObject<CheckBoxViewDelegate> *delegate;
}
@property(readonly) bool isOn;
@property(assign) NSObject<CheckBoxViewDelegate> *delegate;

- (void) drawRoundedRect:(CGRect) rect inContext:(CGContextRef) context;
@end



#import "CheckBoxView.h"

#define SIZE 30.0
#define STROKE_WIDTH 2.0
#define ALPHA .6
#define RADIUS 5.0

@implementation CheckBoxView
@synthesize isOn, delegate;

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:CGRectMake(frame.Origin.x, frame.Origin.y, SIZE, SIZE)])) {
        // Initialization code
    }
    //UIColor *color = [UIColor blackColor];
    color = [[UIColor alloc] initWithWhite:.0 alpha:ALPHA];

    self.backgroundColor = [UIColor clearColor];
    checkMark = [[UILabel alloc] initWithFrame:CGRectMake(STROKE_WIDTH, STROKE_WIDTH, SIZE - 2 * STROKE_WIDTH, SIZE - 2*STROKE_WIDTH)];
    checkMark.font = [UIFont systemFontOfSize:25.];
    checkMark.text = @"\u2713";
    checkMark.backgroundColor = [UIColor clearColor];
    checkMark.textAlignment = UITextAlignmentCenter;
    //checkMark.textColor = [UIColor redColor];
    [self addSubview:checkMark];
    [checkMark setHidden:TRUE];
    isOn = FALSE;
    return self;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
    CGRect _rect = CGRectMake(STROKE_WIDTH, STROKE_WIDTH, SIZE - 2 * STROKE_WIDTH, SIZE - 2*STROKE_WIDTH);
    [self drawRoundedRect:_rect inContext:UIGraphicsGetCurrentContext()];
    [checkMark setHidden:!isOn];
}


- (void)dealloc {
    [checkMark release];
    [color release];
    [super dealloc];
}

- (void) drawRoundedRect:(CGRect) rect inContext:(CGContextRef) context{
    CGContextBeginPath(context);
    CGContextSetLineWidth(context, STROKE_WIDTH);
    CGContextSetStrokeColorWithColor(context, [color CGColor]);
    CGContextMoveToPoint(context, CGRectGetMinX(rect) + RADIUS, CGRectGetMinY(rect));
    CGContextAddArc(context, CGRectGetMaxX(rect) - RADIUS, CGRectGetMinY(rect) + RADIUS, RADIUS, 3 * M_PI / 2, 0, 0);
    CGContextAddArc(context, CGRectGetMaxX(rect) - RADIUS, CGRectGetMaxY(rect) - RADIUS, RADIUS, 0, M_PI / 2, 0);
    CGContextAddArc(context, CGRectGetMinX(rect) + RADIUS, CGRectGetMaxY(rect) - RADIUS, RADIUS, M_PI / 2, M_PI, 0);
    CGContextAddArc(context, CGRectGetMinX(rect) + RADIUS, CGRectGetMinY(rect) + RADIUS, RADIUS, M_PI, 3 * M_PI / 2, 0);
    CGContextClosePath(context);
    CGContextStrokePath(context);
}

#pragma mark Touch
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint loc = [touch locationInView:self];
    if(CGRectContainsPoint(self.bounds, loc)){
        isOn = !isOn;
        //[self setNeedsDisplay];
        [checkMark setHidden:!isOn];
        if([delegate respondsToSelector:@selector(checkBoxValueChanged:)]){
            [delegate checkBoxValueChanged:self];
        }
    }
}
1
hiepnd

Je l'ai fait avec un UITextField pour éviter de dessiner quelque chose d'étrange mais j'aimais mettre à l'intérieur du texte la coche unicode (caractère Unicode 'CHECK MARK' (U + 2713)) pour NSString: @ "\ u2713".

De cette façon, dans mon fichier .h (implémentant le protocole pour UITextField 'UITextFieldDelegate'):

UITextField * myCheckBox;

Dans mon viewDidLoad ou la fonction pour préparer l'interface utilisateur:

...
myCheckBox = [[UITextField alloc] initWithFrame:aFrame];
myCheckBox.borderStyle = UITextBorderStyleRoundedRect; // System look like
myCheckBox.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
myCheckBox.textAlignment = NSTextAlignmentLeft;
myCheckBox.delegate = self;
myCheckBox.text = @" -"; // Initial text of the checkbox... editable!
...

Ajoutez ensuite un sélecteur d’événement à créer dans l’événement tactile et appelez l’événement 'responseSelected':

...
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(checkboxSelected)];
[myCheckBox addGestureRecognizer:tapGesture];
...

Enfin répondre à ce sélecteur

-(void) checkboxSelected
{
    if ([self isChecked])
    {
        // Uncheck the selection
        myCheckBox.text = @" -";
    }else{
       //Check the selection
       myCheckBox.text = @"\u2713";
    }
}

La fonction 'isChecked' ne vérifie que si le texte correspond à la coche @ "\ u2713". Pour empêcher l'affichage du clavier lorsque le champ de texte est sélectionné, utilisez l'événement de UITextField 'textFieldShouldBeginEditing' et ajoutez le sélecteur d'événement pour gérer la sélection:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    // Question selected form the checkbox
    [self checkboxSelected];

    // Hide both keyboard and blinking cursor.
    return NO;
}
1
mTouch

dans le fichier .h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    BOOL isChecked;
    UIImageView * checkBoxIV;
}
@end

Et le fichier .m

- (void)viewDidLoad
{
    [super viewDidLoad];
    isChecked = NO;

    //change this property according to your need
    checkBoxIV = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 15, 15)]; 
    checkBoxIV.image =[UIImage imageNamed:@"checkbox_unchecked.png"]; 

    checkBoxIV.userInteractionEnabled = YES;
    UITapGestureRecognizer *checkBoxIVTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handlecheckBoxIVTapGestureTap:)];
    checkBoxIVTapGesture.numberOfTapsRequired = 1;
    [checkBoxIV addGestureRecognizer:checkBoxIVTapGesture];
}

- (void)handlecheckBoxIVTapGestureTap:(UITapGestureRecognizer *)recognizer {
    if (isChecked) {
        isChecked = NO;
        checkBoxIV.image =[UIImage imageNamed:@"checkbox_unchecked.png"];
    }else{
        isChecked = YES;
        checkBoxIV.image =[UIImage imageNamed:@"checkbox_checked.png"];   
    }
}

Ça fera l'affaire...

1
Dilip

l'utilisateur Aruna Lakmal; Pour votre information, lorsque vous ajoutez ce code à IB lorsque vous décrivez que initWithFrame n'est pas appelé, initWithCoder l'est. Implémentez initWithCoder et cela fonctionnera comme vous le décrivez.

0
Nostradamus