How to change UIPickerView height

Is it possible to change the height of UIPickerView? Some applications seem to have shorter PickerViews but setting a smaller frame doesn't seem to work and the frame is locked in Interface Builder.

142583 次浏览

据我所知,缩小 UIPickerView 是不可能的。我也没见过更短的。我的猜测是,如果他们设法缩小它,那么它就是一个自定义实现。

很明显,苹果公司并没有特别要求改变 UIPickerView的默认高度,但是我发现你可以通过完全控制并在创建时传递一个想要的帧大小来改变 身高的视图,例如:

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

你会发现,在不同的高度和宽度,有视觉故障。显然,这些小故障要么需要设法解决,要么选择另一种尺寸不显示它们。

I have found that you 可以 edit the size of the UIPickerView - just not with interface builder. open the .xib file with a text editor and set the size of the picker view to whatever you want. Interface builder does not reset the size and it seems to work. I'm sure apple locked the size for a reason so you'll have to experiment with different sizes to see what works.

如果要在 IB 中创建选择器,可以将其后调整为较小的大小。检查确保它仍然正确绘制虽然,因为有一点,它看起来令人发指。

上述方法都不适用于 iOS 4.0

PickerView 的高度不再可以重新调整。如果您试图在4.0中更改选择器的框架,将有一条消息转储到控制台:

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

我最终做了一些相当激进的事情,以获得一个更小的选择器的效果,这两个操作系统都可以工作。Xx 和 OS 4.0。我离开了选择器是任何大小的 SDK 决定它应该是,取而代之的是一个切通透明的窗口对我的背景图像,通过这个选择器变得可见。然后简单地将选择器放在我的背景 UIImageView 后面(Z 订单明智) ,这样只有选择器的一部分是可见的,它是由我的背景中的透明窗口指定的。

好吧,在与 iOS4中愚蠢的 pickerview 进行了长时间的斗争之后,我决定将我的控件改为简单的表: 这是密码:

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

Here is the .h file for that:

//
//  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];

就这样,现在唯一剩下的事情就是在 combobox 视图中创建一个成员变量,它将保存当前的行选择,我们就可以开始了。

好好享受吧。

即使它没有调整大小,当 UIPicker 位于屏幕底部时,另一个技巧可能会有所帮助。

人们可以尝试将它稍微向下移动,但是中间的行应该保持可见。这将有助于显示一些空间以上的采摘,因为底部行将离开屏幕。

我重复一遍,这不是改变 UIPicker 视图高度的方法,而是一些如果所有其他尝试都失败了你可以做什么的想法。

stockPicker = [[UIPickerView alloc] init];
stockPicker.frame = CGRectMake(70.0,155, 180,100);

如果你想设置 UiPickerView 的大小,以上代码肯定对你有用。

经过一整天的挠头,我终于找到了适合自己的东西。下面的代码将在用户每次更改手机方向时重新创建 UIDatePicker。这将消除 UIDatePicker 在方向改变后出现的任何小故障。

Since we are recreating the UIDatePicker, we need an instance variable that will keep the selected date value. The codes below are tested on 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

试试:

pickerview.transform = CGAffineTransformMakeScale(.5, 0.5);

在 iOS 4.2和4.3中,以下工作是:

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

以下内容不起作用:

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

我有一个应用程序,是在应用程序商店与3行日期选择器。我认为高度变化可能已经被阻止,因为你看到的文字下的日期选择器的边界,但这发生在正常的216高度日期选择器太。

- 哪个是窃听器?-你的猜测和我的一样。

UIDatePicker(和 UIPickerView)162.0、180.0和216.0也有3个有效高度。如果将 UIPickerView高度设置为其他值,在 iOS 设备上进行调试时,您将在控制台中看到以下内容。

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

UIPickerView (162.0, 180.0 and 216.0)只有三个有效高度。

您可以使用 CGAffineTransformMakeTranslationCGAffineTransformMakeScale函数来适当地适合您的方便采集器。

例如:

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));

以上代码将采集器视图的高度改为一半,并将其重新定位到确切的 (左 x1,顶 y1)位置。

在 iOS 5.0中,我得到了以下工作:

UIDatePicker *picker = [[UIDatePicker alloc] init];
picker.frame = CGRectMake(0.0, 0.0, 320.0, 160.0);

这就创建了一个日期选择器,就像苹果在日历应用程序中创建横向模式的新事件时使用的那样。(3行而不是5行)当我在 initWithFrame:方法中设置框架时,这种方法不起作用,但是到目前为止,当使用单独的方法设置框架时,这种方法起作用。

for iOS 5:

如果你快速浏览一下 UIPickerView Protocol参考文献

你会发现

– pickerView:rowHeightForComponent:
– pickerView:widthForComponent:

我想这是你要找的第一个

I wasn't able to follow any of the above advice.

我看了很多教程,发现 这个是最有益的:

I added the following code to set the new height inside the "viewDidLoad" method, which worked in my app.

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

希望这对你有帮助!

优点:

  1. 使 UIPickerView的 setFrame 按照应该的方式运行
  2. UIViewController中没有转换代码
  3. viewWillLayoutSubviews内工作以重新调整/定位 UIPickerView
  4. Works on the iPad without UIPopover
  5. 超类总是接收有效的高度
  6. 适用于 iOS5

缺点:

  1. 需要你的子类 UIPickerView
  2. 要求使用 pickerView viewForRow撤消子视图的转换
  3. UIAnimation 可能不起作用

解决方案:

子类 UIPickerView 并使用以下代码覆盖这两个方法。

#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;
}

我在用 ios 7和 Xcode 5。我能够通过将日期选择器封装在视图中来间接调整它的高度。可以调整容器视图高度。

您通常不能在 xib 中或通过编程方式设置帧,但是如果您将其父 xib 作为源打开并从那里更改高度,那么它就可以工作。右键单击包含 pickerview 的 xib,搜索 pickerview,您可以在该标记中找到高度、宽度等,更改高度然后保存文件。

<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>

更改选择器视图可见高度的一个简单方法是将选择器嵌入到 UIView 中,将父视图的高度调整为您希望看到的选择器的高度,然后在父 UIView 中启用“剪辑子视图”Interface Builder,或在代码中设置 view.clipsToBounds = true

Clip Subviews in IB

Create a view in IB or code. Add your picker as a subview of this view. Resize the view. This is easiest to do in IB. Create constraints from the view to its superview and from the picker to this new view.

因为 Picker 曲线在它周围溢出在视图的顶部和底部。您可以在 IB 中看到,当您将顶部和底部约束从选择器添加到视图中时,它显示了一个标准空间,类似于 Superview 容器上方和下方的16点。如果你不想要这样的行为(丑陋的警告) ,设置视图剪辑它。

下面是 iPhone5高达96点的样子。带有溢出效应的采样器大约有130点高。好瘦啊!

我在我的项目中使用这个,以防止采摘扩展到一个不必要的高度。这种技术削减它,并迫使更严格的溢出。它实际上看起来更光滑,更紧凑一点。

enter image description here

下面是一个显示溢出效应的视图图像。

enter image description here

下面是我添加的 IB 约束。

enter image description here

Swift: You need to add a subview with clip to bounds

    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)

这将在视图控制器的顶部添加一个剪裁过的100高度日期选择器。

As of iOS 9, you can freely change UIPickerView's width and height. No need to use the above mentioned transform hacks.

我的技巧是: 使用 datePicker 的掩码层使 datePicker 的某些部分可见。就像你看到的那样,改变日期表格的框架。

- (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;
}

This has changed a lot in iOS 9 (in iOS 8 it's pretty similar to what we're seeing here). If you can afford to target iOS 9 only, then you resize the UIPickerView as you see fit, by setting its frame. Good!

这是来自 IOS9发行说明

UIPickerView and UIDatePicker are now resizable and adaptive—previously, these views would enforce a default size even if 您试图调整它们的大小。这些视图现在也默认为宽度 所有设备上的320点,而不是设备宽度上 IPhone.

依赖于默认大小的旧实施的接口将 在为 iOS9编译时很可能看起来是错误的 可以通过完全约束或调整选择器视图的大小来解决 而不是依赖于隐含的行为。

我使用一个蒙版图层来改变它的显示大小

// 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

嵌入到堆栈视图中。堆栈视图是苹果公司最近在其 iOS SDK 中添加的一个组件,用于反映基于 Java 脚本 Web 的前端库(如 bootstrap)中基于网格的实现。

如上所述,UIPickerView现在可以调整大小。我只是想补充一点,如果你想在 tableView 单元格中改变 pickerView 的高度,我没有成功地将高度锚设置为一个常量。然而,使用 lessThanOrEqualToConstant似乎有效。

 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)
}


}