iphone - data - Cómo cambiar la altura de UIPickerView
uipickerview swift 4 (27)
¿Es posible cambiar la altura de UIPickerView? Algunas aplicaciones parecen tener PickerViews más cortos, pero la configuración de un marco más pequeño no parece funcionar y el marco está bloqueado en el Interface Builder.
Ventajas:
- Hace que setFrame of
UIPickerView
comporte como debería - Sin código de transformación dentro de su
UIViewController
- Funciona dentro de
viewWillLayoutSubviews
paraviewWillLayoutSubviews
/ posicionar elUIPickerView
- Funciona en el iPad sin
UIPopover
- La superclase siempre recibe una altura válida
- Funciona con iOS 5
Desventajas:
- Requiere que subclass
UIPickerView
- Requiere el uso de
pickerView viewForRow
para deshacer la transformación de las subViews - UIAnimations podría no funcionar
Solución:
Subclase UIPickerView y sobrescribe los dos métodos utilizando el siguiente código. Combina subclases, altura fija y el enfoque de transformación.
#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;
}
A partir de iOS 9, puede cambiar libremente el ancho y alto de UIPickerView
. No es necesario utilizar los hacks de transformación mencionados anteriormente.
Crea una vista en IB o código. Agregue su selector como una subvista de esta vista. Cambiar el tamaño de la vista. Esto es más fácil de hacer en IB. Cree restricciones desde la vista a su supervista y desde el selector a esta nueva vista.
Dado que las curvas del selector giran a su alrededor, se derraman sobre la parte superior e inferior de la vista. Puede ver en IB cuando agrega restricciones superiores e inferiores desde el selector a la vista que muestra un espacio estándar algo así como 16 puntos por encima y debajo del contenedor de la supervista. Configure la vista para recortarla si no desea este comportamiento (advertencia desagradable).
Esto es lo que parece a 96 puntos de altura en un iPhone 5. El selector con el efecto secundario tiene alrededor de 130 puntos de alto. ¡Bastante flaco!
Estoy usando esto en mi proyecto para evitar que el selector se extienda a una altura innecesaria. Esta técnica lo recorta y fuerza un derrame más apretado. En realidad parece más impermeable para ser un poco más compacto.
Aquí hay una imagen de la vista que muestra el derrame.
Aquí están las restricciones de IB que agregué.
Descubrí que puedes editar el tamaño de UIPickerView, pero no con el constructor de interfaz. abra el archivo .xib con un editor de texto y configure el tamaño de la vista del seleccionador a lo que desee. El generador de interfaz no restablece el tamaño y parece funcionar. Estoy seguro de que Apple bloqueó el tamaño por una razón, por lo que tendrás que experimentar con diferentes tamaños para ver qué funciona.
Después de un largo día de rascarse la cabeza, he encontrado algo que funciona para mí. Los siguientes códigos recrearán el UIDatePicker cada vez que el usuario cambie la orientación del teléfono. Esto eliminará los fallos técnicos que tenga el UIDatePicker después de un cambio de orientación.
Dado que estamos recreando el UIDatePicker, necesitamos una variable de instancia que mantendrá el valor de la fecha seleccionada. Los siguientes códigos están probados en iOS 4.0.
@interface AdvanceDateViewController : UIViewController<UIPickerViewDelegate> {
UIDatePicker *datePicker;
NSDate *date;
}
@property (nonatomic, retain) UIDatePicker *datePicker;
@property (nonatomic, retain) NSDate *date;
-(void)resizeViewWithOrientation:(UIInterfaceOrientation) orientation;
@end
@implementation AdvanceDateViewController
@synthesize datePicker, date;
- (void)viewDidLoad {
[super viewDidLoad];
[self resizeViewWithOrientation:self.interfaceOrientation];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self resizeViewWithOrientation:self.interfaceOrientation];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self resizeViewWithOrientation:toInterfaceOrientation];
}
-(void)resizeViewWithOrientation:(UIInterfaceOrientation) orientation{
[self.datePicker removeFromSuperview];
[self.datePicker removeTarget:self action:@selector(refreshPickupDate) forControlEvents:UIControlEventValueChanged];
self.datePicker = nil;
//(Re)initialize the datepicker, thanks to Apple''s buggy UIDatePicker implementation
UIDatePicker *dummyDatePicker = [[UIDatePicker alloc] init];
self.datePicker = dummyDatePicker;
[dummyDatePicker release];
[self.datePicker setDate:self.date animated:YES];
[self.datePicker addTarget:self action:@selector(refreshPickupDate) forControlEvents:UIControlEventValueChanged];
if(UIInterfaceOrientationIsLandscape(orientation)){
self.datePicker.frame = CGRectMake(0, 118, 480, 162);
} else {
self.datePicker.frame = CGRectMake(0, 200, 320, 216);
}
[self.view addSubview:self.datePicker];
[self.view setNeedsDisplay];
}
@end
En iOS 4.2 y 4.3, funciona lo siguiente:
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.frame = CGRectMake(0, 0, 320, 180);
[self addSubview:datePicker];
Lo siguiente no funciona:
UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 320, 180)];
[self addSubview:datePicker];
Tengo una aplicación que está en la tienda de aplicaciones con un selector de fecha de 3 líneas. Pensé que el cambio de altura podría haberse evitado porque se ve el texto debajo del borde del selector de fecha, pero esto también sucede con el selector de fecha de altura 216 normal.
¿Cuál es el error? Tu invitado es tan bueno como el mío.
También hay 3 alturas válidas para UIDatePicker
(y UIPickerView
) UIPickerView
, 180.0 y 216.0. Si establece una altura de UIPickerView
en cualquier otra cosa, verá lo siguiente en la consola al depurar en un dispositivo con iOS.
2011-09-14 10:06:56.180 DebugHarness[1717:707] -[UIPickerView setFrame:]: invalid height value 300.0 pinned to 216.0
En iOS 5.0, obtuve lo siguiente para trabajar:
UIDatePicker *picker = [[UIDatePicker alloc] init];
picker.frame = CGRectMake(0.0, 0.0, 320.0, 160.0);
Esto creó un selector de fechas como el que usa Apple en la aplicación Calendario al crear un nuevo evento en modo horizontal. (3 filas de altura en lugar de 5.) Esto no funcionó cuando configuré el marco dentro del método initWithFrame:
pero hasta ahora funciona al configurarlo usando un método separado.
Esto ha cambiado mucho en iOS 9 (en iOS 8 es bastante similar a lo que estamos viendo aquí). Si puede permitirse apuntar solo a iOS 9, UIPickerView
el tamaño de UIPickerView
como mejor le parezca, configurando su marco. ¡Bueno!
Aquí está de iOS 9 Release Notes
UIPickerView y UIDatePicker ahora son redimensionables y adaptables; anteriormente, estas vistas impondrían un tamaño predeterminado incluso si intentaste cambiar su tamaño. Estas vistas ahora también tienen un ancho predeterminado de 320 puntos en todos los dispositivos, en lugar de un ancho de dispositivo en iPhone.
Es probable que las interfaces que se basan en el antiguo cumplimiento del tamaño predeterminado se vean mal cuando se compilan para iOS 9. Cualquier problema que se encuentre se puede resolver restringiendo o dimensionando las vistas del selector al tamaño deseado en lugar de confiar en el comportamiento implícito.
Estoy trabajando con iOS 7, Xcode 5. Pude ajustar la altura del selector de fecha indirectamente al encerrarlo en una vista. La altura de las vistas del contenedor se puede ajustar.
Generalmente no puede hacerlo en xib o establecer el marco programáticamente, pero si abre su xib padre como fuente y cambia la altura desde allí, entonces funciona. Haga clic derecho en el xib dentro del cual se encuentra pickerview, busque pickerview y puede encontrar alto, ancho, etc. en esa etiqueta, cambie la altura allí y luego guarde el archivo.
<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>
Hasta donde yo sé, es imposible reducir el UIPickerView. Tampoco he visto uno más corto usado en ninguna parte. Supongo que fue una implementación personalizada si lograron reducirla.
Incluso si no se está redimensionando, otro truco puede ayudar en la situación cuando el UIPicker se encuentra en la parte inferior de la pantalla.
Uno puede intentar moverlo ligeramente hacia abajo, pero la fila central debe permanecer visible. Esto ayudará a revelar un espacio encima del selector ya que las filas inferiores estarán fuera de la pantalla.
Repito que esta no es la forma de cambiar la altura de la vista de UIPicker, sino una idea de lo que puede hacer si fallan todos los demás intentos.
Incrustar en una vista de pila. Stack view es un componente agregado recientemente por Apple en su SDK de iOS para reflejar las implementaciones basadas en grid en las bibliotecas de front-end basadas en web java script como bootstrap.
Mi truco: usar la capa de máscara de datepicker para hacer que datePicker sea visible. como ves, cambia el marco de 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;
}
Ninguno de los enfoques anteriores funciona en iOS 4.0
La altura del selector Picker ya no es re-considerable. Hay un mensaje que se descarga a la consola si intentas cambiar el marco de un selector en 4.0:
-[UIPickerView setFrame:]: invalid height value 66.0 pinned to 162.0
Terminé haciendo algo bastante radical para obtener el efecto de un selector más pequeño que funciona tanto en OS 3.xx como en OS 4.0. Dejé el selector para que sea del tamaño que el SDK decida que debería ser y en su lugar hice una ventana transparente transparente en mi imagen de fondo a través de la cual el selector se hace visible. Luego simplemente coloque el selector (Z Order wise) mi UIImageView de fondo para que solo se vea una parte del selector que viene dictada por la ventana transparente en mi fondo.
No pude seguir ninguno de los consejos anteriores.
Vi varios tutoriales y encontré this el más beneficioso:
Agregué el siguiente código para establecer la nueva altura dentro del método "viewDidLoad", que funcionó en mi aplicación.
UIPickerView *picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 120.0)];
[self.view addSubview:picker];
picker.delegate = self;
picker.dataSource = self;
Espero que esto haya sido útil.
Ok, después de luchar durante mucho tiempo con la estúpida selección de iOS 4, decidí cambiar mi control en una tabla simple: aquí está el código:
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
Aquí está el archivo .h para eso:
//
// 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];
eso es todo, ahora lo único que queda es crear una variable miembro en la vista del cuadro combinado que contendrá la selección de fila actual, y estamos listos para continuar.
Disfruta a todos
Si desea crear su selector en IB, puede cambiar el tamaño de la publicación a un tamaño más pequeño. Sin embargo, asegúrate de que todavía se dibuja correctamente, ya que llega un punto en el que se ve atroz.
Solo hay tres alturas válidas para UIPickerView (162.0, 180.0 and 216.0)
.
Puede usar las funciones CGAffineTransformMakeTranslation
y CGAffineTransformMakeScale
para que se ajusten adecuadamente al selector a su conveniencia.
Ejemplo:
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));
El código anterior cambia la altura de la vista del selector a la mitad y la vuelve a colocar en la posición exacta (Izquierda-x1, Superior-y1) .
Tratar:
pickerview.transform = CGAffineTransformMakeScale(.5, 0.5);
Una manera fácil de cambiar la altura visible de una vista de selector es incrustar el selector en una UIView, ajustar la altura de la vista principal a la altura que desea ver del selector, luego habilitar "Subvistas de clip" en el Constructor de interfaz en la UIView padre o establecer view.clipsToBounds = true
en el código.
Uso una capa de máscara para cambiar su tamaño de visualización
// 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
Ver mi respuesta a esta pregunta: UIPicker dimensionando en modo horizontal
para iOS 5:
si echa un vistazo rápido a la referencia del protocolo UIPickerView
encontrarás
– pickerView:rowHeightForComponent:
– pickerView:widthForComponent:
Creo que es el primero que estás buscando
Swift : necesita agregar una subvista con clip a límites
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)
Esto debería agregar un recortador de fecha recortado de 100 alturas en la parte superior del controlador de vista.
Parece obvio que Apple no invita especialmente a la limpieza con la altura predeterminada de UIPickerView
, pero he descubierto que puede lograr un cambio en la altura de la vista al tomar el control completo y pasar un tamaño de fotograma deseado en el momento de la creación, por ejemplo :
smallerPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 120.0)];
Descubrirá que en varias alturas y anchos, hay fallas visuales. Obviamente, estos fallos técnicos tendrían que solucionarse de alguna manera o elegir otro tamaño que no los muestre.
stockPicker = [[UIPickerView alloc] init];
stockPicker.frame = CGRectMake(70.0,155, 180,100);
Si desea establecer el tamaño de UiPickerView. El código anterior seguramente te va a funcionar.