22

我正在制作一个计时器应用程序,需要向用户显示小时、分钟和秒。我尝试使用UIDatePicker,但它只显示小时和分钟作为选择。不是秒。在网上做了一些研究后,我发现没有办法获得秒数,我不得不从头开始UIDatePicker编写自己的。UIPickerView

所以我的问题是,是否有这样的示例代码,即有人写了CustomUIPickerView几个小时、分钟和秒,我可以合并到我的项目中?UIDatePicker有一个很好的 Hours & Mins 文本覆盖,当用户旋转表盘时会保持不变。如果有人在他们的自定义选择器中添加它会很好。UIPickerView如果没有必要,我不想从头开始编写自定义。谢谢你。

4

8 回答 8

42

好的伙计们,这里是获取小时/分钟/秒的代码UIPickerView。您可以添加 3 个标签,并有策略地将它们放置在选择器上。我也附上了一张图片。

如果你喜欢这个答案,那就给它评分吧!优秀的开发人员会分享知识,而不是像某些人建议的那样隐藏它。玩得开心编码!

在此处输入图像描述

在你的头 .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];

}
于 2012-06-13T02:27:21.343 回答
31

与上面公认的解决方案不同,我想出了一些不那么可怕的东西。绝对不是完美的,但它具有预期的效果(我只在 iPhone 上的 iOS 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;
}

结果:

H/M/S 选择器

于 2014-03-11T21:28:48.223 回答
8

迅速实施

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
    }

}
于 2015-04-09T10:50:52.297 回答
7

我不喜欢不依赖于添加UILabel为子视图的答案UIPickerView,因为如果 iOS 决定某天改变外观,硬编码框架将会中断。

一个简单的技巧是将小时/分钟/秒标签作为具有 1 行的组件

小时/分钟/秒标签将远离它们的值,但这没关系。大多数用户甚至不会注意到这一点。你自己看:

在此处输入图像描述

于 2015-10-16T02:26:53.217 回答
4

我对@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
于 2015-03-01T19:00:50.177 回答
1

我这里有一个简单的解决方案,你可以为 UIPickerView 实现 UIPickerViewDataSource 的 3 个方法

    - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 5;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    switch (component) {
        case 0:
            return 24;
            break;
        case 1:
        case 3:
            return 1;
            break;
        case 2:
        case 4:
            return 60;
            break;
        default:
            return 1;
            break;
    }
}

- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    switch (component) {
        case 1:
        case 3:
            return @":";
            break;
        case 0:
        case 2:
        case 4:
            return [NSString stringWithFormat:@"%lu", (long) row];
            break;
        default:
            return @"";
            break;
    }
}

在此处输入图像描述

于 2018-07-19T03:15:33.903 回答
1

一种选择是使用 ActionSheetPicker

https://github.com/skywinder/ActionSheetPicker-3.0

并利用 ActionSheetMultipleStringPicker。您可以按照 ActionSheetPicker 文档中的示例代码进行操作。

于 2017-08-01T20:39:27.503 回答
0

这是“小时/分钟/秒”叠加的另一种解决方案。它使用pickerView(UIPickerView, didSelectRow: Int, inComponent: Int)选择器视图的委托中的方法来更新视图的标签。

这样,无论屏幕方向如何,它都可以工作。它仍然不是最佳的,但它非常简单。

UIPickerView 示例

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

要在显示选择器视图时显示覆盖,必须以编程方式选择行...

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)
}
于 2017-06-19T14:41:32.510 回答