web-dev-qa-db-fra.com

Masquer/Afficher UIPickerView

J'ai un événement touchesEnded qui vérifie si un UITextField est enfoncé. Ce que je voudrais, c'est masquer/afficher un UIPickerView. Comment cela peut-il être fait?

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [[event allTouches] anyObject];
    if (CGRectContainsPoint([self.textField frame], [touch locationInView:self.view]))
    {
        NSString * error = @"Touched the TextField";
        UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:@"Selection!" message:error delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [errorAlert show];
        //Want to show or hide UIPickerView
    }
}

J'ai déjà un UIPickerView alloué lorsque des contacts se produisent

@interface ThirdViewController : UIViewController <UITextFieldDelegate,UIPickerViewDelegate> {
    IBOutlet UIPickerView *pickerView;
}
18
aahrens

UIPickerView hérite de UIView, vous devriez donc pouvoir basculer sa propriété 'hidden':

if (pickerView) pickerView.hidden = !pickerView.hidden;
14
Joe Strout

Activer la propriété "hidden" fera l'affaire, mais donnera également une révélation très abrupte. 

Une façon d'éviter cela consiste à faire glisser le sélecteur du bas de l'écran en l'intégrant dans une feuille UIAction.

Voici un exemple:

    UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil 
delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];

    CGRect pickerFrame = CGRectMake(0, 0, 0, 0);
    UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
    pickerView.showsSelectionIndicator = YES;
    pickerView.dataSource = self;
    pickerView.delegate = self;
    [sheet addSubview:pickerView];
    [pickerView release];

    [sheet showInView:view];
    [sheet setBounds:CGRectMake(0, 0, 320, 415)];
    self.actionSheet = sheet; // assuming you have setup a property to hold the action sheet
    [sheet release];

Lorsque vous avez terminé avec le sélecteur, fermez-le:

[self.actionSheet dismissWithClickedButtonIndex:0 animated:YES];

Cette approche peut également être utilisée pour incorporer des boutons dans une barre au-dessus du sélecteur ("Terminé", "Précédent", "Suivant", etc.) - il existe une bonne explication de la procédure à suivre ici .

35
Jonathan Moffatt

Comme j'ai vu un commentaire sur le fait que ces solutions ne fonctionnent pas sur iOS 7, je suppose que ce fil est toujours pertinent et recherché.

Pour ce faire, la meilleure solution consiste à attacher UIPickerView à un UITextField (masqué) en tant que vue d'entrée, comme suit:

_myPicker = [[UIPickerView alloc] init];
_myPicker.delegate = self;
_myPicker.showsSelectionIndicator = YES;
myTextField.inputView = _myPicker;

Vous pouvez toujours masquer le champ de texte si vous le souhaitez. Ensuite, vous pouvez afficher/masquer UIPickerView en activant le champ de texte en tant que premier répondant, comme:

[myTextField becomeFirstResponder];
[myTextField resignFirstResponder];

J'ai vérifié que cela fonctionnait sur iOS 7 et que cela fonctionnait déjà depuis iOS 5.

23
Joe

J'utilise une variable UITextField pour afficher/masquer la UIPickerView

Premièrement, ajoutez un UITextField en tant que @property sur votre UIViewController. Ajoutez éventuellement la variable UIPickerView

@property (strong, nonatomic) UITextField *dummyTextField;

Deuxièmement, attribuez une UIPickerView à inputView pour la UITextField. Attribuez-vous les variables dataSource et delegate pour UIPickerView. UITextField doit être ajouté en tant que sous-vue de votre UIViewController 's view.

- (void)viewDidLoad {

    [super viewDidLoad];

    UIPickerView *picker = [[UIPickerView alloc] init];
    [picker setDataSource:self];
    [picker setDelegate:self];

    self.dummyTextField = [UITextField new];
    self.dummyTextField.inputView = picker;
    [self.dummyTextField setHidden:YES];
    [self.view addSubview:self.dummyTextField];
}

Enfin, ajoutez un mécanisme pour afficher et masquer la UIPickerView. Depuis que j'utilise une variable UITextField, j'ai décidé d'ajouter une UIBarButtonItem nommée "Filtre" avec la IBAction suivante:

- (IBAction)tappedFilterButton:(UIBarButtonItem *)sender {

    if (self.dummyTextField.isFirstResponder) {

        [self.dummyTextField resignFirstResponder];
    }
    else {

        [self.dummyTextField becomeFirstResponder];
    }
}
4
Yunus Nedim Mehel

Vous pouvez utiliser ActionSheetPicker-3.0

Il ressemble à UIPickerView dans UIActionSheet et a également été adopté pour iOS 6-7-8.

animation

enter image description here

3
skywinder

J'ai donc utilisé de nombreuses références pour essayer de comprendre cela, puis ma meilleure référence (croyez-le ou non) était tirée de la documentation Apple sur la référence de classe UIView.

J'ai construit une mini-vue ("_pickerView" au-dessus de ma vue principale contenant un UIToolBar, UIToolButton (avec IBAction "closePicker") et UIPicker.

*** s'il vous plaît noter que cela ne fonctionne que pour iOS 4.0 et plus

le code pour fermer et afficher UIView ("_pickerView") est:

-(IBAction)closePicker:(id)sender
{
    [UIView animateWithDuration:0.3 animations:^{ 
        _pickerView.frame = CGRectMake(_pickerView.frame.Origin.x,
                                       460, //Displays the view off the screen
                                       _pickerView.frame.size.width,
                                       _pickerView.frame.size.height);
    }];
}

-(IBAction)showPicker:(id)sender
{
    [UIView animateWithDuration:0.3 animations:^{ 
        _pickerView.frame = CGRectMake(_pickerView.frame.Origin.x,
                                       107, //Displays the view a little past the
                                            //center ling of the screen
                                       _pickerView.frame.size.width,
                                       _pickerView.frame.size.height);
    }];
}

Et pour que votre viewDidLoad appelle simplement "closePicker" pour que la vue soit cachée au chargement

2
SolThoth

Dans une application basée sur scrollView, afficher et masquer UIPickerView peut s'avérer un problème difficile, car il est relativement difficile de l'épingler au bas du rectangle visible screen. Vous pouvez le faire facilement avec le code suivant. 

let alertController = UIAlertController(title: title, message: "\n\n\n\n\n\n\n\n\n\n", preferredStyle: .ActionSheet)
alertController.view.addSubview(pickerView)
alertController.addAction(UIAlertAction(title: "OK", style: .Cancel) { action in
})
self.presentViewController(alertController, animated: true, completion: nil)

Pour résumer, vous créez un UIAlertController avec un message vide. Afin de faire en sorte que alertController ait la taille de votre sélecteur, vous indiquez au message le nombre de sauts de ligne nécessaire. Et enfin, vous ajoutez votre sélecteur en tant que sous-vue de alertController.view

Vous suivez ensuite les lignes pickerView sélectionnées avec les méthodes UIPickerViewDelegate.

1
Murat Yasar

J'ai cherché partout un moyen propre de masquer et d'afficher UIPickerView à l'aide d'un seul bouton et de ne trouver que des éléments. Pour ceux qui cherchent à faire de même, voici mon résultat de travail via une instruction conditionnelle de base.

ViewController.m

- (IBAction)animatePicker {
    if ([self.userSelection.title isEqualToString: (NSString *)@"Select"]) {
        _userPicker.hidden = NO;
        UIPickerView *pickerView = [[UIPickerView alloc] init]; // default frame is set
        float pvHeight = pickerView.frame.size.height;
        float y = [[UIScreen mainScreen] bounds].size.height - (pvHeight); // the root view of view controller
        [UIView animateWithDuration:0.25f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
            self.userPicker.frame = CGRectMake(0 , y, pickerView.frame.size.width, pvHeight);
        } completion:nil];
    } else if ([self.userSelection.title isEqualToString: (NSString *)@"Done"]) {
            UIPickerView *pickerView = [[UIPickerView alloc] init]; // default frame is set
            float pvHeight = pickerView.frame.size.height;
            float y = [[UIScreen mainScreen] bounds].size.height - (pvHeight * -2); // the root view of view controller
            [UIView animateWithDuration:0.25f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
                self.userPicker.frame = CGRectMake(0 , y, pickerView.frame.size.width, pvHeight);
            } completion:nil];
        self.userSelection.title = @"Select";
        }
    }

Voici donc ce qui se passe ici: j'ai un élément de bouton appelé "userSelection" avec le titre "Select" et un UIPickerView caché appelé "userPicker" (pour le masquer, copiez simplement le bit relatif à "_userPicker.hidden", collez-le dans votre déclaration de sélecteur et définissez le booléen sur OUI). L'élément de bouton est connecté à l'action ci-dessus. Lors du chargement (c’est-à-dire lorsque le titre du bouton indique "Select"), il affiche le sélecteur et l’anime. Vous pouvez utiliser les options animateWithDuration et delay pour contrôler cette fonction, mais ces paramètres me semblent plutôt naturels.

Ensuite, cette méthode modifie le titre du bouton en "Terminé" lorsque quelque chose a été sélectionné. Je suis convaincu qu'il existe une façon plus simple de procéder, mais la méthode de commutation me laisse une certaine liberté au cas où je souhaiterais apporter des modifications à l'interface utilisateur ultérieurement.

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row   inComponent:(NSInteger)component{

    NSLog(@"Selected Row %ld", (long)row);
    switch(row)
    {

        case 0:
            self.userSelection.title = @"Done";
            break;
        case 1:
            self.userSelection.title = @"Done";
            break;
        case 2:
            self.userSelection.title = @"Done";
            break;
        case 3:
            self.userSelection.title = @"Done";
            break;
        case 4:
            self.userSelection.title = @"Done";
            break;
        case 5:
            self.userSelection.title = @"Done";
            break;
    }
}

Enfin, l'action se termine par un "else if" qui indique que le bouton indique "Terminé", masque le sélecteur avec l'animation inversée (même code, mais avec "pvHeight * -2"), puis redéfinit le titre du bouton sur " Sélectionnez "qui sert à compléter la boucle de toute l'action.

Probablement un moyen plus facile pour les professionnels, mais pour les personnes novices dans ce domaine, comme moi, cela avait tout son sens. De plus, cela fonctionne, donc c'est toujours un bonus!

0
jeremytripp

Voici l'exemple de code à cacher et afficher de UIPickerView avec animation: -

// pour l'affichage

-(void)showPickerView{
    self.pickerSheet = [UIAlertController alertControllerWithTitle:@"Select font" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    self.pickerView = [[UIPickerView alloc]initWithFrame:CGRectZero];
    self.pickerView.dataSource = self;
    self.pickerView.delegate = self;
    self.pickerView.showsSelectionIndicator = YES;
    [self.pickerView selectRow:1 inComponent:0 animated:YES];
    [self.pickerSheet.view addSubview:self.pickerView];
    self.pickerView.translatesAutoresizingMaskIntoConstraints = NO;
    UIView *view = self.pickerView;
    [self.pickerSheet.view addConstraints:[NSLayoutConstraint
                               constraintsWithVisualFormat:@"V:|[view]|"
                               options:0l
                               metrics:nil
                               views:NSDictionaryOfVariableBindings(view)]];

    [self.pickerSheet.view addConstraints:[NSLayoutConstraint
                               constraintsWithVisualFormat:@"H:|[view]|"
                               options:0l
                               metrics:nil
                               views:NSDictionaryOfVariableBindings(view)]];
    [self presentViewController:self.pickerSheet animated:YES completion:^{
    }];

}

// pour se cacher

-(void)hidePickerView{
    [self.pickerSheet dismissViewControllerAnimated:YES completion:^{
    }];
}
0
Hussain Shabbir