web-dev-qa-db-fra.com

Comment changer la hauteur de UIPickerView

Est-il possible de changer la hauteur de UIPickerView? Certaines applications semblent avoir des vues de sélecteur plus courtes, mais la définition d'un cadre plus petit ne semble pas fonctionner et le cadre est verrouillé dans Interface Builder.

112
Steven Canfield

Il semble évident que Apple n’invite pas particulièrement la mise à mort avec la hauteur par défaut de la UIPickerView, mais j’ai constaté que vous pouviez modifier la valeur height de la vue en prenant le contrôle complet et en passant une taille de trame souhaitée au moment de la création, par exemple:

smallerPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 120.0)];

Vous découvrirez que, à différentes hauteurs et largeurs, il y a des problèmes visuels. De toute évidence, ces problèmes devraient soit être résolus, soit choisir une autre taille qui ne les expose pas.

54
danielpunkass

Aucune des approches ci-dessus ne fonctionne dans iOS 4.0

La hauteur de pickerView n'est plus redimensionnable. Un message est envoyé à la console si vous essayez de modifier le cadre d'un sélecteur dans 4.0:

-[UIPickerView setFrame:]: invalid height value 66.0 pinned to 162.0 

J'ai fini par faire quelque chose d'assez radical pour obtenir l'effet d'un sélecteur plus petit qui fonctionne à la fois sous OS 3.xx et OS 4.0. J'ai laissé le sélecteur à la taille souhaitée par le SDK et à la place, j'ai créé une fenêtre transparente coupée au travers de mon image d'arrière-plan à travers laquelle le sélecteur devient visible. Ensuite, placez simplement le sélecteur derrière (ordre Z) mon arrière-plan UIImageView afin que seule une partie du sélecteur soit visible, ce qui est dicté par la fenêtre transparente située dans mon fond.

46
bhavinb

Il n'y a que trois hauteurs valides pour UIPickerView (162.0, 180.0 and 216.0)

Vous pouvez utiliser les fonctions CGAffineTransformMakeTranslation et CGAffineTransformMakeScale pour adapter le sélecteur à votre convenance. 

Exemple: 

CGAffineTransform t0 = CGAffineTransformMakeTranslation (0, pickerview.bounds.size.height/2);
CGAffineTransform s0 = CGAffineTransformMakeScale       (1.0, 0.5);
CGAffineTransform t1 = CGAffineTransformMakeTranslation (0, -pickerview.bounds.size.height/2);
pickerview.transform = CGAffineTransformConcat          (t0, CGAffineTransformConcat(s0, t1));

Le code ci-dessus change la hauteur de la vue du sélecteur en demi et la repositionne à la position exacte (Left-x1, Top-y1) .

43
JRSee

Essayer:

pickerview.transform = CGAffineTransformMakeScale(.5, 0.5);
40
vijay adhikari

Dans iOS 4.2 & 4.3, les travaux suivants:

UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.frame = CGRectMake(0, 0, 320, 180);
[self addSubview:datePicker];

Ce qui suit ne fonctionne pas:

UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 320, 180)];
[self addSubview:datePicker];

J'ai une application qui se trouve dans l'App Store avec un sélecteur de date sur 3 lignes. Je pensais que le changement de hauteur avait peut-être été empêché parce que le texte se trouvait sous la bordure du sélecteur de date, mais cela se produit également pour le sélecteur de date de 216 tailles.

Quel est le bug? Votre proposition est aussi bonne que la mienne.

Il existe également 3 hauteurs valides pour UIDatePicker (et UIPickerView) 162.0, 180.0 et 216.0. Si vous définissez une hauteur UIPickerView sur une autre valeur, les éléments suivants s'affichent dans la console lors du débogage sur un périphérique iOS.

2011-09-14 10:06:56.180 DebugHarness[1717:707] -[UIPickerView setFrame:]: invalid height value 300.0 pinned to 216.0
25
mmorris

À partir de iOS 9, vous pouvez modifier librement la largeur et la hauteur de UIPickerView. Pas besoin d'utiliser les hacks de transformation mentionnés ci-dessus.

14
rounak

J'ai trouvé que vous pouvez modifier la taille de UIPickerView - mais pas avec le générateur d'interface. ouvrez le fichier .xib avec un éditeur de texte et définissez la taille de la vue sélecteur sur ce que vous voulez. Le générateur d'interface ne réinitialise pas la taille et semble fonctionner. Je suis sûr que Apple a verrouillé la taille pour une raison, vous devrez donc essayer différentes tailles pour voir ce qui fonctionne.

10
Mark Mieczkowski

Avantages:

  1. Fait que setFrame of UIPickerView se comporte comme il se doit
  2. Aucun code de transformation dans votre UIViewController
  3. Fonctionne dans viewWillLayoutSubviews pour redimensionner/positionner la UIPickerView 
  4. Fonctionne sur l'iPad sans UIPopover
  5. La superclasse reçoit toujours une hauteur valide
  6. Fonctionne avec iOS 5

Désavantages:

  1. Vous oblige à sous-classe UIPickerView
  2. Nécessite l'utilisation de pickerView viewForRow pour annuler la transformation des sous-aperçus
  3. UIAnimations pourrait ne pas fonctionner

Solution:

Sous-classe UIPickerView et écrasez les deux méthodes à l'aide du code suivant. Il combine le sous-classement, la hauteur fixe et l'approche de transformation.

#define FIXED_PICKER_HEIGHT 216.0f
- (void) setFrame:(CGRect)frame
{
    CGFloat targetHeight = frame.size.height;
    CGFloat scaleFactor = targetHeight / FIXED_PICKER_HEIGHT;
    frame.size.height = FIXED_PICKER_HEIGHT;//fake normal conditions for super
    self.transform = CGAffineTransformIdentity;//fake normal conditions for super
    [super setFrame:frame];
    frame.size.height = targetHeight;
    CGFloat dX=self.bounds.size.width/2, dY=self.bounds.size.height/2;
    self.transform = CGAffineTransformTranslate(CGAffineTransformScale(CGAffineTransformMakeTranslation(-dX, -dY), 1, scaleFactor), dX, dY);
}

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    //Your code goes here

    CGFloat inverseScaleFactor = FIXED_PICKER_HEIGHT/self.frame.size.height;
    CGAffineTransform scale = CGAffineTransformMakeScale(1, inverseScaleFactor);
    view.transform = scale;
    return view;
}
7
HeikoG

Un moyen simple de modifier la hauteur visible d'une vue de sélecteur consiste à l'intégrer au UIView, à ajuster la hauteur de la vue parent à la hauteur souhaitée du sélecteur, puis à activer "Clip Subviews" dans Interface Builder sur la vue parent ou définissez view.clipsToBounds = true dans le code.

Clip Subviews in IB

7
svarrall

Je n'ai pu suivre aucun des conseils ci-dessus. 

J'ai regardé plusieurs tutoriels et trouvé this one le plus bénéfique:

J'ai ajouté le code suivant pour définir la nouvelle hauteur dans la méthode "viewDidLoad", qui fonctionnait dans mon application.

UIPickerView *picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 120.0)]; 
[self.view addSubview:picker];
picker.delegate = self;
picker.dataSource = self;

J'espère que cela a été utile!

5
erran

Cela a beaucoup changé dans iOS 9 (dans iOS 8, c'est assez similaire à ce que nous voyons ici). Si vous pouvez vous permettre de cibler uniquement iOS 9, redimensionnez la UIPickerView comme bon vous semble en définissant son cadre. Bien!

Le voici de Notes de version iOS 9

UIPickerView et UIDatePicker sont maintenant redimensionnables et Adaptive: auparavant, ces vues imposaient une taille par défaut même si vous avez essayé de les redimensionner. Ces vues ont également désormais une largeur par défaut de 320 points sur tous les périphériques, au lieu de la largeur de périphérique sur iPhone.

Les interfaces qui reposent sur l’ancienne application de la taille par défaut seront semble mal paraître lors de la compilation pour iOS 9. Problèmes rencontrés peuvent être résolus en limitant ou en dimensionnant entièrement les vues de sélecteur sur le fichier taille souhaitée au lieu de compter sur un comportement implicite.

3
Dan Rosenstark

Je travaille avec ios 7, Xcode 5. J'ai été en mesure de régler la hauteur du sélecteur de date indirectement en le plaçant dans une vue. La hauteur des vues du conteneur peut être ajustée.

2
serverman

Vous ne pouvez généralement pas le faire dans xib ou les cadres programmés, mais si vous ouvrez son xib parent en tant que source et que vous en modifiez la hauteur, cela fonctionne. dans cette balise, changez la hauteur puis sauvegardez le fichier.

<pickerView contentMode="scaleToFill" id="pai-pm-hjZ">
                                    <rect key="frame" x="0.0" y="41" width="320" height="100"/>
                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
                                    <connections>
                                        <outlet property="dataSource" destination="-1" id="Mo2-zp-Sl4"/>
                                        <outlet property="delegate" destination="-1" id="nfW-lU-tsU"/>
                                    </connections>
                                </pickerView>
1
Bhoomi

Ok, après avoir longtemps lutté avec le stupide pickerview sous iOS 4, j'ai décidé de changer mon contrôle en tableau simple:

ComboBoxView.m = which is actually looks more like pickerview.

//
//  ComboBoxView.m
//  iTrophy
//
//  Created by Gal Blank on 8/18/10.
//

#import "ComboBoxView.h"
#import "AwardsStruct.h"


@implementation ComboBoxView

@synthesize displayedObjects;

#pragma mark -
#pragma mark Initialization

/*
- (id)initWithStyle:(UITableViewStyle)style {
    // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
    if ((self = [super initWithStyle:style])) {
    }
    return self;
}
*/


#pragma mark -
#pragma mark View lifecycle

/*
- (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
*/

/*
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/


#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    return [[self displayedObjects] count];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


    NSString *MyIdentifier = [NSString stringWithFormat:@"MyIdentifier %i", indexPath.row];

    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
        //cell.contentView.frame = CGRectMake(0, 0, 230.0,16);
        UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 5, 230.0,19)] autorelease];
        VivatAwardsStruct *vType = [displayedObjects objectAtIndex:indexPath.row];
        NSString *section = [vType awardType]; 
        label.tag = 1;
        label.font = [UIFont systemFontOfSize:17.0];
        label.text = section;
        label.textAlignment = UITextAlignmentCenter;
        label.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
        label.adjustsFontSizeToFitWidth=YES;
        label.textColor = [UIColor blackColor];
        //label.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        [cell.contentView addSubview:label]; 
        //UIImage *image = nil;
        label.backgroundColor = [UIColor whiteColor];
        //image = [awards awardImage];
        //image = [image imageScaledToSize:CGSizeMake(32.0, 32.0)];

        //[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
        //UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
        //cell.accessoryView = imageView;
        //[imageView release];
    }

    return cell;
}


/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/


/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/


/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/


/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/


#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and Push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     [detailViewController release];
     */
}


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Relinquish ownership any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}


- (void)dealloc {
    [super dealloc];
}


@end

Voici le fichier .h pour cela:

//
//  ComboBoxView.h
//  iTrophy
//
//  Created by Gal Blank on 8/18/10.
//

#import <UIKit/UIKit.h>


@interface ComboBoxView : UITableViewController {
    NSMutableArray *displayedObjects;
}

@property (nonatomic, retain) NSMutableArray *displayedObjects;


@end

now, in the ViewController where I had Apple UIPickerView I replaced with my own ComboBox view and made it size what ever I wish.

ComboBoxView *mypickerholder = [[ComboBoxView alloc] init]; 
[mypickerholder.view setFrame:CGRectMake(50, 220, 230, 80)];
[mypickerholder setDisplayedObjects:awardTypesArray];

ça y est, il ne reste plus qu'à créer dans la liste déroulante une variable membre qui conservera la sélection de lignes actuelle, et nous pouvons continuer.

Profitez de tout le monde.

1
Alex

Même s'il ne s'agit pas d'un redimensionnement, une autre astuce peut vous aider dans la situation où UIPicker est situé au bas de l'écran. 

On peut essayer de le déplacer légèrement vers le bas, mais la rangée centrale doit rester visible. Cela aidera à révéler un peu d'espace au-dessus du sélecteur, car les rangées du bas seront hors écran. 

Je répète que ce n'est pas le moyen de changer la hauteur de la vue UIPicker mais une idée de ce que vous pouvez faire si toutes les autres tentatives échouent. 

1
Sergey Lost

Créez une vue dans IB ou code. Ajoutez votre sélecteur en tant que sous-vue de cette vue. Redimensionnez la vue. C'est plus facile à faire dans IB. Créez des contraintes de la vue à sa vue d'ensemble et du sélecteur à cette nouvelle vue. 

Puisque le sélecteur se courbe, il déborde en haut et en bas de la vue. Vous pouvez voir dans IB que, lorsque vous ajoutez des contraintes du haut et du bas du sélecteur à la vue, un espace standard de 16 points au dessus et en dessous du conteneur superview apparaît. Définissez la vue pour la couper si vous ne souhaitez pas ce comportement (avertissement déplaisant). 

Voici à quoi cela ressemble à 96 points de haut sur un iPhone 5. Le sélecteur avec le débordement est à environ 130 points de haut. Assez maigre! 

J'utilise ceci dans mon projet pour empêcher le préparateur de s’étendre à une hauteur inutile. Cette technique la réduit et force un débordement plus serré. En fait, il semble plus compact pour être un peu plus compact.

enter image description here

Voici une image de la vue montrant le débordement.

enter image description here

Voici les contraintes IB que j'ai ajoutées. 

enter image description here

1
smileBot

Autant que je sache, il est impossible de réduire UIPickerView. De plus, je n’ai pas vu de version plus courte utilisée nulle part. À mon avis, il s’agissait d’une implémentation personnalisée s’ils parvenaient à la réduire.

0
NilObject

Comme mentionné ci-dessus, UIPickerView est maintenant redimensionnable. Je veux juste ajouter que si vous voulez changer la hauteur de pickerView dans une cellule tableView, je n'ai pas réussi à définir l'ancre de hauteur sur une constante. Cependant, utiliser lessThanOrEqualToConstant semble fonctionner.

 class PickerViewCell: UITableViewCell {

    let pickerView = UIPickerView()

    func setup() {

        // call this from however you initialize your cell

        self.contentView.addSubview(self.pickerView)
        self.pickerView.translatesAutoresizingMaskIntoConstraints = false

        let constraints: [NSLayoutConstraint] = [
            // pin the pickerView to the contentView's layoutMarginsGuide

            self.pickerView.leadingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.leadingAnchor),
            self.pickerView.topAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.topAnchor),
            self.pickerView.trailingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.trailingAnchor),
            self.pickerView.bottomAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.bottomAnchor),

            // set the height using lessThanOrEqualToConstant
            self.pickerView.heightAnchor.constraint(lessThanOrEqualToConstant: 100)
        ]

        NSLayoutConstraint.activate(constraints)
     }

 }
0
MH175

Voir ma réponse à cette question: Dimensionnement UIPicker en mode paysage

0
Can Berk Güder

J'utilise un calque de masque pour changer sa taille d'affichage

// Swift 3.x
let layer = CALayer()
layer.frame = CGRect(x: 0,y:0, width: displayWidth, height: displayHeight)
layer.backgroundColor = UIColor.red.cgColor
pickerView.layer.mask = layer
0
John Lee

Swift : Vous devez ajouter une sous-vue avec clip aux limites.

    var DateView = UIView(frame: CGRectMake(0, 0, view.frame.width, 100))
    DateView.layer.borderWidth=1
    DateView.clipsToBounds = true

    var myDatepicker = UIDatePicker(frame:CGRectMake(0,-20,view.frame.width,162));
    DateView.addSubview(myDatepicker);
    self.view.addSubview(DateView)

Cela devrait ajouter un sélecteur de date découpé de 100 hauteurs en haut du contrôleur de vue.

0
Miika Pakarinen

Si vous souhaitez créer votre sélecteur dans IB, vous pouvez le redimensionner ultérieurement. Assurez-vous qu’il dessine toujours correctement, car il arrive un moment où il semble odieux.

0
Rob Winchester

Mon astuce: utilisez le calque de masque de datepicker pour rendre certaines parties de datePicker visibles. comme vous le voyez, tout comme changer le cadre du datepicke.

- (void)timeSelect:(UIButton *)timeButton {
UIDatePicker *timePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 550)];
timePicker.backgroundColor = [UIColor whiteColor];
timePicker.layer.mask = [self maskLayerWithDatePicker:timePicker];
timePicker.layer.masksToBounds = YES;
timePicker.datePickerMode = UIDatePickerModeTime;
[self.view addSubview:timePicker];
}

- (CALayer *)maskLayerWithDatePicker:(UIDatePicker *)datePicker {
CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, datePicker.width*0.8, datePicker.height*0.8) cornerRadius:10];
shapeLayer.path = path.CGPath;
return shapeLayer;
}
0
frank

Intégrer dans une vue de pile. La vue de pile est un composant récemment ajouté par Apple dans son SDK iOS pour refléter les implémentations basées sur la grille dans les bibliothèques frontales basées sur le script Java, telles que bootstrap.

0
user5590043