UIPickerView看起来像UIDatePicker,但秒
我正在制作一个计时器应用程序,需要显示小时,分钟和秒钟给用户。 我尝试使用UIDatePicker
但它只显示小时和分钟作为select。 不是几秒钟。 在网上做了一些研究之后,我发现没有办法在UIDatePicker
获得秒数,我不得不从头开始写自己的UIPickerView
。
所以我的问题是,有这样的示例代码,即有人写了CustomUIPickerView
小时,分钟和秒,我可以在我的项目中纳入? UIDatePicker
有一个很好的覆盖时间和分钟的文本,保持在用户旋转拨号时。 如果有人在他们的自定义选取器中添加了这个,那也不错。 如果不需要,我宁愿不要从头开始写一个自定义的UIPickerView
。 谢谢。
Alrighty的人,这里是你的UIPickerView
获得小时/分钟/秒的代码。 您可以添加3个标签,并将其置于选取器上。 我也附上了一张照片。
如果你喜欢答案,请评价! 好的开发者分享知识并不像一些人所build议的那样隐藏它 玩得开心编码!
在你的头文件.h文件把这个
@interface v1AddTableViewController : UITableViewController { IBOutlet UIPickerView *pickerView; NSMutableArray *hoursArray; NSMutableArray *minsArray; NSMutableArray *secsArray; NSTimeInterval interval; } @property(retain, nonatomic) UIPickerView *pickerView; @property(retain, nonatomic) NSMutableArray *hoursArray; @property(retain, nonatomic) NSMutableArray *minsArray; @property(retain, nonatomic) NSMutableArray *secsArray;
在你的.m文件把这个
@synthesize pickerView; @synthesize hoursArray; @synthesize minsArray; @synthesize secsArray; @synthesize interval; - (void)viewDidLoad { [super viewDidLoad]; //initialize arrays hoursArray = [[NSMutableArray alloc] init]; minsArray = [[NSMutableArray alloc] init]; secsArray = [[NSMutableArray alloc] init]; NSString *strVal = [[NSString alloc] init]; for(int i=0; i<61; i++) { strVal = [NSString stringWithFormat:@"%d", i]; //NSLog(@"strVal: %@", strVal); //Create array with 0-12 hours if (i < 13) { [hoursArray addObject:strVal]; } //create arrays with 0-60 secs/mins [minsArray addObject:strVal]; [secsArray addObject:strVal]; } NSLog(@"[hoursArray count]: %d", [hoursArray count]); NSLog(@"[minsArray count]: %d", [minsArray count]); NSLog(@"[secsArray count]: %d", [secsArray count]); } //Method to define how many columns/dials to show - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 3; } // Method to define the numberOfRows in a component using the array. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent :(NSInteger)component { if (component==0) { return [hoursArray count]; } else if (component==1) { return [minsArray count]; } else { return [secsArray count]; } } // Method to show the title of row for a component. - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { switch (component) { case 0: return [hoursArray objectAtIndex:row]; break; case 1: return [minsArray objectAtIndex:row]; break; case 2: return [secsArray objectAtIndex:row]; break; } return nil; } -(IBAction)calculateTimeFromPicker { NSString *hoursStr = [NSString stringWithFormat:@"%@",[hoursArray objectAtIndex:[pickerView selectedRowInComponent:0]]]; NSString *minsStr = [NSString stringWithFormat:@"%@",[minsArray objectAtIndex:[pickerView selectedRowInComponent:1]]]; NSString *secsStr = [NSString stringWithFormat:@"%@",[secsArray objectAtIndex:[pickerView selectedRowInComponent:2]]]; int hoursInt = [hoursStr intValue]; int minsInt = [minsStr intValue]; int secsInt = [secsStr intValue]; interval = secsInt + (minsInt*60) + (hoursInt*3600); NSLog(@"hours: %d ... mins: %d .... sec: %d .... interval: %f", hoursInt, minsInt, secsInt, interval); NSString *totalTimeStr = [NSString stringWithFormat:@"%f",interval]; }
与上面所接受的解决scheme不同,我想出了一些不太可怕的东西。 绝对不是完美的,但它具有预期的效果(我只在iPhone上testingiOS 7,只能在写作肖像)。 编辑做出更好的表示欢迎。 下面的相关显示代码:
// assumes you conform to UIPickerViewDelegate and UIPickerViewDataSource in your .h - (void)viewDidLoad { [super viewDidLoad]; // assumes global UIPickerView declared. Move the frame to wherever you want it picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 200)]; picker.dataSource = self; picker.delegate = self; UILabel *hourLabel = [[UILabel alloc] initWithFrame:CGRectMake(42, picker.frame.size.height / 2 - 15, 75, 30)]; hourLabel.text = @"hour"; [picker addSubview:hourLabel]; UILabel *minsLabel = [[UILabel alloc] initWithFrame:CGRectMake(42 + (picker.frame.size.width / 3), picker.frame.size.height / 2 - 15, 75, 30)]; minsLabel.text = @"min"; [picker addSubview:minsLabel]; UILabel *secsLabel = [[UILabel alloc] initWithFrame:CGRectMake(42 + ((picker.frame.size.width / 3) * 2), picker.frame.size.height / 2 - 15, 75, 30)]; secsLabel.text = @"sec"; [picker addSubview:secsLabel]; [self.view addSubview:picker]; } - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 3; } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { if(component == 0) return 24; return 60; } - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { return 30; } - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { UILabel *columnView = [[UILabel alloc] initWithFrame:CGRectMake(35, 0, self.view.frame.size.width/3 - 35, 30)]; columnView.text = [NSString stringWithFormat:@"%lu", (long) row]; columnView.textAlignment = NSTextAlignmentLeft; return columnView; }
结果是:
快速实施
class TimePickerView: UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate { var hour:Int = 0 var minute:Int = 0 override init() { super.init() self.setup() } required internal init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.setup() } override init(frame: CGRect) { super.init(frame: frame) self.setup() } func setup(){ self.delegate = self self.dataSource = self /*let height = CGFloat(20) let offsetX = self.frame.size.width / 3 let offsetY = self.frame.size.height/2 - height/2 let marginX = CGFloat(42) let width = offsetX - marginX let hourLabel = UILabel(frame: CGRectMake(marginX, offsetY, width, height)) hourLabel.text = "hour" self.addSubview(hourLabel) let minsLabel = UILabel(frame: CGRectMake(marginX + offsetX, offsetY, width, height)) minsLabel.text = "min" self.addSubview(minsLabel)*/ } func getDate() -> NSDate{ let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "HH:mm" let date = dateFormatter.dateFromString(String(format: "%02d", self.hour) + ":" + String(format: "%02d", self.minute)) return date! } func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { return 2 } func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { switch component { case 0: self.hour = row case 1: self.minute = row default: println("No component with number \(component)") } } func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { if component == 0 { return 24 } return 60 } func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat { return 30 } func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView { if (view != nil) { (view as UILabel).text = String(format:"%02lu", row) return view } let columnView = UILabel(frame: CGRectMake(35, 0, self.frame.size.width/3 - 35, 30)) columnView.text = String(format:"%02lu", row) columnView.textAlignment = NSTextAlignment.Center return columnView } }
我对@Stonz2的版本做了一些小小的改进。 标签的y位置的计算也有错误。
这里的.h文件
@interface CustomUIDatePicker : UIPickerView <UIPickerViewDataSource, UIPickerViewDelegate> @property NSInteger hours; @property NSInteger mins; @property NSInteger secs; -(NSInteger) getPickerTimeInMS; -(void) initialize; @end
在这里.m文件的改进
@implementation CustomUIDatePicker -(instancetype)init { self = [super init]; [self initialize]; return self; } -(id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; [self initialize]; return self; } -(instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; [self initialize]; return self; } -(void) initialize { self.delegate = self; self.dataSource = self; int height = 20; int offsetX = self.frame.size.width / 3; int offsetY = self.frame.size.height / 2 - height / 2; int marginX = 42; int width = offsetX - marginX; UILabel *hourLabel = [[UILabel alloc] initWithFrame:CGRectMake(marginX, offsetY, width, height)]; hourLabel.text = @"hour"; [self addSubview:hourLabel]; UILabel *minsLabel = [[UILabel alloc] initWithFrame:CGRectMake(marginX + offsetX, offsetY, width, height)]; minsLabel.text = @"min"; [self addSubview:minsLabel]; UILabel *secsLabel = [[UILabel alloc] initWithFrame:CGRectMake(marginX + offsetX * 2, offsetY, width, height)]; secsLabel.text = @"sec"; [self addSubview:secsLabel]; } -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { if (component == 0) { self.hours = row; } else if (component == 1) { self.mins = row; } else if (component == 2) { self.secs = row; } } -(NSInteger)getPickerTimeInMS { return (self.hours * 60 * 60 + self.mins * 60 + self.secs) * 1000; } -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 3; } -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { if(component == 0) return 24; return 60; } - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { return 30; } -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { if (view != nil) { ((UILabel*)view).text = [NSString stringWithFormat:@"%lu", row]; return view; } UILabel *columnView = [[UILabel alloc] initWithFrame:CGRectMake(35, 0, self.frame.size.width/3 - 35, 30)]; columnView.text = [NSString stringWithFormat:@"%lu", row]; columnView.textAlignment = NSTextAlignmentLeft; return columnView; } @end
我不喜欢不依赖将UILabel
作为子视图添加到UIPickerView
的答案,因为如果iOS决定在某一天改变外观,则硬编码帧将会中断。
一个简单的技巧是将小时/分钟/秒标签作为1行的组件 。
小时/分钟/秒的标签将远离它们的值,但是没关系。 大多数用户甚至不会注意到这一点。 你自己看:
这是“小时/分钟/秒”叠加的另一个解决scheme。 它使用pickerView(UIPickerView, didSelectRow: Int, inComponent: Int)
view的委托中的pickerView(UIPickerView, didSelectRow: Int, inComponent: Int)
方法来更新视图的标签。
这样,无论屏幕方向如何,它都能工作。 它仍然不是最优的,但是非常简单。
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { let label = UILabel() label.text = String(row) label.textAlignment = .center return label } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { if let label = pickerView.view(forRow: row, forComponent: component) as? UILabel { if component == 0, row > 1 { label.text = String(row) + " hours" } else if component == 0 { label.text = String(row) + " hour" } else if component == 1 { label.text = String(row) + " min" } else if component == 2 { label.text = String(row) + " sec" } } }
要显示选取器视图时显示叠加层,必须以编程方式select行…
func selectPickerViewRows() { pickerView.selectRow(0, inComponent: 0, animated: false) pickerView.selectRow(0, inComponent: 1, animated: false) pickerView.selectRow(30, inComponent: 2, animated: false) pickerView(pickerView, didSelectRow: 0, inComponent: 0) pickerView(pickerView, didSelectRow: 0, inComponent: 1) pickerView(pickerView, didSelectRow: 30, inComponent: 2) }
一个select是使用ActionSheetPicker
https://github.com/skywinder/ActionSheetPicker-3.0
并利用ActionSheetMultipleStringPicker。 您可以按照ActionSheetPicker文档中的示例代码。
我也面临同样的问题。 这就是为什么我做了一个自定义时间select器与秒,几天和许多其他选项,我发表在GitHub上:
iOSSecondsTimerPicker
试一试。