UIPickerView qui ressemble à UIDatePicker mais avec des secondes
je fais une app et nécessaire à l'affichage heure, minute et secondes de l'utilisateur. J'ai essayé d'utiliser UIDatePicker
mais il montre seulement les heures et les minutes comme sélections. Pas secondes. Après avoir fait un peu de recherche en ligne, j'ai trouvé qu'il n'y a aucun moyen d'obtenir secondes UIDatePicker
et j'ai eu à écrire mes propres UIPickerView
à partir de zéro.
alors ma question Est, y a-t-il un exemple de code pour un tel i.e. quelqu'un a écrit un CustomUIPickerView
pendant des heures, min et sec que je peux intégrer dans mon projet? UIDatePicker
a une belle superposition D'heures et de minutes de texte qui reste mis pendant que l'utilisateur tourne les cadrans. Ce serait bien si quelqu'un ajoutait cela dans leur picker personnalisé aussi. Je préfère ne pas écrire un custom UIPickerView
à partir de zéro si je n'ai pas. Remercier.
9 réponses
très bien les amis, voici le code pour obtenir des heures / Minutes / secondes dans votre UIPickerView
. Vous pouvez ajouter 3 étiquettes un placer stratégiquement sur le sélecteur. J'ai joint une photo.
Si vous aimez la réponse ne taux de! Les bons développeurs partagent leurs connaissances et ne les cachent pas comme certains l'ont suggéré. Ont le plaisir de codage!
Dans votre en-tête .h du dossier de ce
@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;
dans votre .m du dossier de ce
@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];
}
contrairement à la solution acceptée ci-dessus, j'ai trouvé quelque chose d'un peu moins terrible. Certainement pas parfait, mais il a l'effet désiré (j'ai seulement testé dans iOS 7 sur iPhone, ne fonctionne que dans portrait tel qu'écrit). Les modifications pour faire mieux sont les bienvenues. Code d'affichage pertinent ci-dessous:
// 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;
}
et le résultat:
mise en œuvre de swift
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
}
}
je n'ai pas aimé les réponses ne comptent plus sur l'ajout d' UILabel
comme subviews à UIPickerView
, parce que le codage dur les cadres se casseront si iOS décide de changer l'apparence un jour.
un truc simple est d'avoir les étiquettes heure/min/sec comme composants avec 1 ligne.
les étiquettes heure/min/sec seront plus éloignées de leurs valeurs, mais ce n'est pas grave. La plupart des utilisateurs ne le remarqueront même pas. Pour voir vous-même:
j'ai apporté quelques petites améliorations à la version de @Stonz2. Il y avait aussi une erreur dans le calcul de la position y des étiquettes.
Ici le .h fichier
@interface CustomUIDatePicker : UIPickerView <UIPickerViewDataSource, UIPickerViewDelegate>
@property NSInteger hours;
@property NSInteger mins;
@property NSInteger secs;
-(NSInteger) getPickerTimeInMS;
-(void) initialize;
@end
Et ici la .m fichier avec les améliorations
@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
une option est D'utiliser ActionSheetPicker
https://github.com/skywinder/ActionSheetPicker-3.0
et d'utiliser L'ActionSheetMultipleStringPicker. Vous pouvez suivre le code d'exemple dans les documents ActionSheetPicker.
j'ai une solution simple ici, vous pouvez implémenter la méthode 3 D'UIPickerViewDataSource pour UIPickerView
- (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;
}
}
Voici une autre solution pour la superposition" heure/min/sec". Il utilise le pickerView(UIPickerView, didSelectRow: Int, inComponent: Int)
méthode du délégué de la vue du picker pour mettre à jour l'étiquette de la vue.
de cette façon, cela fonctionnera quelle que soit l'orientation de l'écran. Il n'est toujours pas optimale mais c'est assez simple.
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"
}
}
}
pour que la superposition apparaisse lorsque la vue de picker est affichée, les lignes doivent être programmées sélectionné...
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)
}
j'ai également fait face à un même problème. C'est pourquoi j'ai fait un chronomètre personnalisé avec des secondes, des jours et beaucoup d'autres options et je l'ai publié sur GitHub:
ioss secondstimerpicker
Lui donner un essai.