UIDatePicker 选择月份和年份
Posted
技术标签:
【中文标题】UIDatePicker 选择月份和年份【英文标题】:UIDatePicker select Month and Year 【发布时间】:2011-03-21 20:47:48 【问题描述】:我需要UIDatePicker
来仅选择月份和年份。我检查了类参考文件。看起来UIDatePicker
是UIView
。我想象UIPickerView
可能是一个子视图,如果我能抓住它,我可以隐藏它。但不是。那是不可能的。那我必须创建自己的自定义选择器吗?有什么想法吗?
【问题讨论】:
自从提出这个问题后,我推荐的SRMonthPicker等开源库已经添加到CocoaPods中了。 【参考方案1】:这是获得相同效果的解决方案。要使用此 sn-p 代码,您应该将“Indentity 检查器”的“自定义类”中的 nib 文件中的 UIPickerView
替换为 CDatePickerViewEx
。
.h 文件
#import <UIKit/UIKit.h>
@interface CDatePickerViewEx : UIPickerView <UIPickerViewDelegate, UIPickerViewDataSource>
@property (nonatomic, strong, readonly) NSDate *date;
-(void)selectToday;
@end
.m 文件
#import "CDatePickerViewEx.h"
// Identifiers of components
#define MONTH ( 0 )
#define YEAR ( 1 )
// Identifies for component views
#define LABEL_TAG 43
@interface CDatePickerViewEx()
@property (nonatomic, strong) NSIndexPath *todayIndexPath;
@property (nonatomic, strong) NSArray *months;
@property (nonatomic, strong) NSArray *years;
-(NSArray *)nameOfYears;
-(NSArray *)nameOfMonths;
-(CGFloat)componentWidth;
-(UILabel *)labelForComponent:(NSInteger)component selected:(BOOL)selected;
-(NSString *)titleForRow:(NSInteger)row forComponent:(NSInteger)component;
-(NSIndexPath *)todayPath;
-(NSInteger)bigRowMonthCount;
-(NSInteger)bigRowYearCount;
-(NSString *)currentMonthName;
-(NSString *)currentYearName;
@end
@implementation CDatePickerViewEx
const NSInteger bigRowCount = 1000;
const NSInteger minYear = 2008;
const NSInteger maxYear = 2030;
const CGFloat rowHeight = 44.f;
const NSInteger numberOfComponents = 2;
@synthesize todayIndexPath;
@synthesize months;
@synthesize years = _years;
-(void)awakeFromNib
[super awakeFromNib];
self.months = [self nameOfMonths];
self.years = [self nameOfYears];
self.todayIndexPath = [self todayPath];
self.delegate = self;
self.dataSource = self;
[self selectToday];
-(NSDate *)date
NSInteger monthCount = [self.months count];
NSString *month = [self.months objectAtIndex:([self selectedRowInComponent:MONTH] % monthCount)];
NSInteger yearCount = [self.years count];
NSString *year = [self.years objectAtIndex:([self selectedRowInComponent:YEAR] % yearCount)];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"MMMM:yyyy"];
NSDate *date = [formatter dateFromString:[NSString stringWithFormat:@"%@:%@", month, year]];
return date;
#pragma mark - UIPickerViewDelegate
-(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
return [self componentWidth];
-(UIView *)pickerView: (UIPickerView *)pickerView
viewForRow: (NSInteger)row
forComponent: (NSInteger)component
reusingView: (UIView *)view
BOOL selected = NO;
if(component == MONTH)
NSInteger monthCount = [self.months count];
NSString *monthName = [self.months objectAtIndex:(row % monthCount)];
NSString *currentMonthName = [self currentMonthName];
if([monthName isEqualToString:currentMonthName] == YES)
selected = YES;
else
NSInteger yearCount = [self.years count];
NSString *yearName = [self.years objectAtIndex:(row % yearCount)];
NSString *currenrYearName = [self currentYearName];
if([yearName isEqualToString:currenrYearName] == YES)
selected = YES;
UILabel *returnView = nil;
if(view.tag == LABEL_TAG)
returnView = (UILabel *)view;
else
returnView = [self labelForComponent: component selected: selected];
returnView.textColor = selected ? [UIColor blueColor] : [UIColor blackColor];
returnView.text = [self titleForRow:row forComponent:component];
return returnView;
-(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
return rowHeight;
#pragma mark - UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
return numberOfComponents;
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
if(component == MONTH)
return [self bigRowMonthCount];
return [self bigRowYearCount];
#pragma mark - Util
-(NSInteger)bigRowMonthCount
return [self.months count] * bigRowCount;
-(NSInteger)bigRowYearCount
return [self.years count] * bigRowCount;
-(CGFloat)componentWidth
return self.bounds.size.width / numberOfComponents;
-(NSString *)titleForRow:(NSInteger)row forComponent:(NSInteger)component
if(component == MONTH)
NSInteger monthCount = [self.months count];
return [self.months objectAtIndex:(row % monthCount)];
NSInteger yearCount = [self.years count];
return [self.years objectAtIndex:(row % yearCount)];
-(UILabel *)labelForComponent:(NSInteger)component selected:(BOOL)selected
CGRect frame = CGRectMake(0.f, 0.f, [self componentWidth],rowHeight);
UILabel *label = [[UILabel alloc] initWithFrame:frame];
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
label.textColor = selected ? [UIColor blueColor] : [UIColor blackColor];
label.font = [UIFont boldSystemFontOfSize:18.f];
label.userInteractionEnabled = NO;
label.tag = LABEL_TAG;
return label;
-(NSArray *)nameOfMonths
NSDateFormatter *dateFormatter = [NSDateFormatter new];
return [dateFormatter standaloneMonthSymbols];
-(NSArray *)nameOfYears
NSMutableArray *years = [NSMutableArray array];
for(NSInteger year = minYear; year <= maxYear; year++)
NSString *yearStr = [NSString stringWithFormat:@"%i", year];
[years addObject:yearStr];
return years;
-(void)selectToday
[self selectRow: self.todayIndexPath.row
inComponent: MONTH
animated: NO];
[self selectRow: self.todayIndexPath.section
inComponent: YEAR
animated: NO];
-(NSIndexPath *)todayPath // row - month ; section - year
CGFloat row = 0.f;
CGFloat section = 0.f;
NSString *month = [self currentMonthName];
NSString *year = [self currentYearName];
//set table on the middle
for(NSString *cellMonth in self.months)
if([cellMonth isEqualToString:month])
row = [self.months indexOfObject:cellMonth];
row = row + [self bigRowMonthCount] / 2;
break;
for(NSString *cellYear in self.years)
if([cellYear isEqualToString:year])
section = [self.years indexOfObject:cellYear];
section = section + [self bigRowYearCount] / 2;
break;
return [NSIndexPath indexPathForRow:row inSection:section];
-(NSString *)currentMonthName
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"MMMM"];
return [formatter stringFromDate:[NSDate date]];
-(NSString *)currentYearName
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy"];
return [formatter stringFromDate:[NSDate date]];
@end
【讨论】:
你能解释一下,如何使用这个类。 这里是 githab 项目的链接:github.com/IgorFedorchuk/MonthYearDatePicker 您能告诉我使用 bigRowMonthCount 和 bigRowYearCount 等常量的目的吗?【参考方案2】:是的,您可能只想制作自己的选择器。但是,您不必将其子类化或其他任何东西;只需使用通用 UIPickerView
并从您的 UIPickerViewDelegate
/UIPickerViewDataSource
方法返回适当的值。
【讨论】:
您如何处理必须阻止选择器选择未来日期的事实?【参考方案3】:我用 Swift 重写了 Igor 的答案:
class CLIVEDatePickerView: UIPickerView
enum Component: Int
case Month = 0
case Year = 1
let LABEL_TAG = 43
let bigRowCount = 1000
let numberOfComponentsRequired = 2
let months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
var years: [String]
get
var years: [String] = [String]()
for i in minYear...maxYear
years.append("\(i)")
return years;
var bigRowMonthsCount: Int
get
return bigRowCount * months.count
var bigRowYearsCount: Int
get
return bigRowCount * years.count
var monthSelectedTextColor: UIColor?
var monthTextColor: UIColor?
var yearSelectedTextColor: UIColor?
var yearTextColor: UIColor?
var monthSelectedFont: UIFont?
var monthFont: UIFont?
var yearSelectedFont: UIFont?
var yearFont: UIFont?
let rowHeight: NSInteger = 44
/**
Will be returned in user's current TimeZone settings
**/
var date: NSDate
get
let month = self.months[selectedRowInComponent(Component.Month.rawValue) % months.count]
let year = self.years[selectedRowInComponent(Component.Year.rawValue) % years.count]
let formatter = NSDateFormatter()
formatter.dateFormat = "MM yyyy"
return formatter.dateFromString("\(month) \(year)")!
var minYear: Int!
var maxYear: Int!
override init(frame: CGRect)
super.init(frame: frame)
loadDefaultParameters()
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
loadDefaultParameters()
override func awakeFromNib()
super.awakeFromNib()
loadDefaultParameters()
func loadDefaultParameters()
minYear = NSCalendar.currentCalendar().components(NSCalendarUnit.Year, fromDate: NSDate()).year
maxYear = minYear! + 10
self.delegate = self
self.dataSource = self
monthSelectedTextColor = UIColor.blueColor()
monthTextColor = UIColor.blackColor()
yearSelectedTextColor = UIColor.blueColor()
yearTextColor = UIColor.blackColor()
monthSelectedFont = UIFont.boldSystemFontOfSize(17)
monthFont = UIFont.boldSystemFontOfSize(17)
yearSelectedFont = UIFont.boldSystemFontOfSize(17)
yearFont = UIFont.boldSystemFontOfSize(17)
func setup(minYear: NSInteger, andMaxYear maxYear: NSInteger)
self.minYear = minYear
if maxYear > minYear
self.maxYear = maxYear
else
self.maxYear = minYear + 10
func selectToday()
selectRow(todayIndexPath.row, inComponent: Component.Month.rawValue, animated: false)
selectRow(todayIndexPath.section, inComponent: Component.Year.rawValue, animated: false)
var todayIndexPath: NSIndexPath
get
var row = 0.0
var section = 0.0
for cellMonth in months
if cellMonth == currentMonthName
row = Double(months.indexOf(cellMonth)!)
row = row + Double(bigRowMonthsCount / 2)
break
for cellYear in years
if cellYear == currentYearName
section = Double(years.indexOf(cellYear)!)
section = section + Double(bigRowYearsCount / 2)
break
return NSIndexPath(forRow: Int(row), inSection: Int(section))
var currentMonthName: String
get
let formatter = NSDateFormatter()
let locale = NSLocale(localeIdentifier: "en_US")
formatter.locale = locale
formatter.dateFormat = "MM"
return formatter.stringFromDate(NSDate())
var currentYearName: String
get
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy"
return formatter.stringFromDate(NSDate())
func selectedColorForComponent(component: NSInteger) -> UIColor
if component == Component.Month.rawValue
return monthSelectedTextColor!
return yearSelectedTextColor!
func colorForComponent(component: NSInteger) -> UIColor
if component == Component.Month.rawValue
return monthTextColor!
return yearTextColor!
func selectedFontForComponent(component: NSInteger) -> UIFont
if component == Component.Month.rawValue
return monthSelectedFont!
return yearSelectedFont!
func fontForComponent(component: NSInteger) -> UIFont
if component == Component.Month.rawValue
return monthFont!
return yearFont!
func titleForRow(row: Int, forComponent component: Int) -> String?
if component == Component.Month.rawValue
return self.months[row % self.months.count]
return self.years[row % self.years.count]
func labelForComponent(component: NSInteger) -> UILabel
let frame = CGRect(x: 0.0, y: 0.0, width: bounds.size.width, height: CGFloat(rowHeight))
let label = UILabel(frame: frame)
label.textAlignment = NSTextAlignment.Center
label.backgroundColor = UIColor.clearColor()
label.userInteractionEnabled = false
label.tag = LABEL_TAG
return label
extension CLIVEDatePickerView: UIPickerViewDelegate, UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
return numberOfComponentsRequired
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
if(component == Component.Month.rawValue)
return bigRowMonthsCount
else
return bigRowYearsCount
func pickerView(pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat
return self.bounds.size.width / CGFloat(numberOfComponentsRequired)
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView
var selected = false
if component == Component.Month.rawValue
let monthName = self.months[(row % self.months.count)]
if monthName == currentMonthName
selected = true
else
let yearName = self.years[(row % self.years.count)]
if yearName == currentYearName
selected = true
var returnView: UILabel
if view?.tag == LABEL_TAG
returnView = view as! UILabel
else
returnView = labelForComponent(component)
returnView.font = selected ? selectedFontForComponent(component) : fontForComponent(component)
returnView.textColor = selected ? selectedColorForComponent(component) : colorForComponent(component)
returnView.text = titleForRow(row, forComponent: component)
return returnView
func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
return CGFloat(rowHeight)
【讨论】:
【参考方案4】:不,这不能使用股票UIDatePicker
来完成。
UIDatePickerModeDate
日期选择器显示月、日 月份和年份。这些的确切顺序 项目取决于区域设置。 这种模式的一个例子是 [11 月 | 15 | 2007]。
来源:UIDatePicker class reference
我建议自定义 UIPickerView
以使用两个组件,并使用从 NSDateFormatter
检索到的月份和年份符号填充其行。
【讨论】:
用户在此 PickerView 中选择日期后,如何获取其值? @Brave - pickerView:didSelectRow:inComponent:【参考方案5】:在 Swift 4 中重写 answer 的 RossP:
import Foundation
@objc class ShortDatePickerView: UIPickerView
enum Component: Int
case Month = 0
case Year = 1
let LABEL_TAG = 43
let bigRowCount = 1000
let numberOfComponentsRequired = 2
let months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
var years: [String]
get
var years: [String] = [String]()
for i in minYear...maxYear
years.append("\(i)")
return years;
var bigRowMonthsCount: Int
get
return bigRowCount * months.count
var bigRowYearsCount: Int
get
return bigRowCount * years.count
var monthSelectedTextColor: UIColor?
var monthTextColor: UIColor?
var yearSelectedTextColor: UIColor?
var yearTextColor: UIColor?
var monthSelectedFont: UIFont?
var monthFont: UIFont?
var yearSelectedFont: UIFont?
var yearFont: UIFont?
let rowHeight: NSInteger = 44
/**
Will be returned in user's current TimeZone settings
**/
var date: Date
get
let month = self.months[selectedRow(inComponent: Component.Month.rawValue) % months.count]
let year = self.years[selectedRow(inComponent: Component.Year.rawValue) % years.count]
let formatter = DateFormatter()
formatter.dateFormat = "MM yyyy"
return formatter.date(from: "\(month) \(year)")!
var minYear: Int!
var maxYear: Int!
override init(frame: CGRect)
super.init(frame: frame)
loadDefaultParameters()
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
loadDefaultParameters()
override func awakeFromNib()
super.awakeFromNib()
loadDefaultParameters()
func loadDefaultParameters()
minYear = Calendar.current.dateComponents([.year], from: Date()).year
maxYear = minYear! + 10
self.delegate = self
self.dataSource = self
monthSelectedTextColor = .blue
monthTextColor = .black
yearSelectedTextColor = .blue
yearTextColor = .black
monthSelectedFont = .boldSystemFont(ofSize: 17)
monthFont = .boldSystemFont(ofSize: 17)
yearSelectedFont = .boldSystemFont(ofSize: 17)
yearFont = .boldSystemFont(ofSize: 17)
func setup(minYear: NSInteger, andMaxYear maxYear: NSInteger)
self.minYear = minYear
if maxYear > minYear
self.maxYear = maxYear
else
self.maxYear = minYear + 10
func selectToday()
selectRow(todayIndexPath.row, inComponent: Component.Month.rawValue, animated: false)
selectRow(todayIndexPath.section, inComponent: Component.Year.rawValue, animated: false)
var todayIndexPath: NSIndexPath
get
var row = 0.0
var section = 0.0
for cellMonth in months
if cellMonth == currentMonthName
row = Double(months.index(of: cellMonth)!)
row = row + Double(bigRowMonthsCount / 2)
break
for cellYear in years
if cellYear == currentYearName
section = Double(years.index(of: cellYear)!)
section = section + Double(bigRowYearsCount / 2)
break
return NSIndexPath(row: Int(row), section: Int(section))
var currentMonthName: String
get
let formatter = DateFormatter()
let locale = Locale.init(identifier: "en_US")
formatter.locale = locale
formatter.dateFormat = "MM"
return formatter.string(from: Date())
var currentYearName: String
get
let formatter = DateFormatter()
formatter.dateFormat = "yyyy"
return formatter.string(from: Date())
func selectedColorForComponent(component: NSInteger) -> UIColor
if component == Component.Month.rawValue
return monthSelectedTextColor!
return yearSelectedTextColor!
func colorForComponent(component: NSInteger) -> UIColor
if component == Component.Month.rawValue
return monthTextColor!
return yearTextColor!
func selectedFontForComponent(component: NSInteger) -> UIFont
if component == Component.Month.rawValue
return monthSelectedFont!
return yearSelectedFont!
func fontForComponent(component: NSInteger) -> UIFont
if component == Component.Month.rawValue
return monthFont!
return yearFont!
func titleForRow(row: Int, forComponent component: Int) -> String?
if component == Component.Month.rawValue
return self.months[row % self.months.count]
return self.years[row % self.years.count]
func labelForComponent(component: NSInteger) -> UILabel
let frame = CGRect(x: 0.0, y: 0.0, width: bounds.size.width, height: CGFloat(rowHeight))
let label = UILabel(frame: frame)
label.textAlignment = .center
label.backgroundColor = .clear
label.isUserInteractionEnabled = false
label.tag = LABEL_TAG
return label
extension ShortDatePickerView: UIPickerViewDelegate, UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
return numberOfComponentsRequired
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
if (component == Component.Month.rawValue)
return bigRowMonthsCount
else
return bigRowYearsCount
func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat
return self.bounds.size.width / CGFloat(numberOfComponentsRequired)
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView
var selected = false
if component == Component.Month.rawValue
let monthName = self.months[(row % self.months.count)]
if monthName == currentMonthName
selected = true
else
let yearName = self.years[(row % self.years.count)]
if yearName == currentYearName
selected = true
var returnView: UILabel
if view?.tag == LABEL_TAG
returnView = view as! UILabel
else
returnView = labelForComponent(component: component)
returnView.font = selected ? selectedFontForComponent(component: component) : fontForComponent(component: component)
returnView.textColor = selected ? selectedColorForComponent(component: component) : colorForComponent(component: component)
returnView.text = titleForRow(row: row, forComponent: component)
return returnView
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
return CGFloat(rowHeight)
func numberOfComponents(in pickerView: UIPickerView) -> Int
return 2
【讨论】:
【参考方案6】:我有一个懒惰的解决方法——我制作了一个 10x10 黑色的 png。 然后,我将其用作带有 scaletofill 图像视图的遮罩,其大小可以完美地覆盖日期列。我将 alpha 设置为 0.75 以勉强显示该列。对用户来说很清楚,看起来还不错。
【讨论】:
谨防本地化。日期列并不总是第二个;在法国,我们将日期格式化为:dd/MM/yyyy,所以选择器会读取类似 [ 16 |费夫里尔 | 2012] 好点,如果支持本地化,您必须相应地移动它,而我们不支持。到那时,您不妨像 Noah 所说的那样重写选择器方法,但是用户并不清楚发生了什么,所以您不妨制作自己的自定义选择器!【参考方案7】:当值更改事件发生时,我只是将日期重置为每月的第一天,如下所示。所以当用户选择一天时,它会滚动回第一天。我使用以下选择开始日期(月和年)。
-(void) resetDay
NSDate *currentDate = [startDatePicker date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit| NSMonthCalendarUnit) fromDate:currentDate];
NSInteger yearNum = [ componentsYear year];
NSInteger monthNum = [componentsYear month];
NSLog(@"Month %d, Year %d", monthNum, yearNum);
NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
[componentStartDate setDay:1];
[componentStartDate setMonth:monthNum];
[componentStartDate setYear:yearNum];
NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
[startDatePicker setDate:startDate animated:YES];
[componentStartDate release];
[gregorian release];
对于选择结束日期(月和年),它有点长,因为我想将日期设置为所选月份的 31 日或 30 日。
-(NSInteger) findDaysInYear
NSDate *currentDate = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit) fromDate:currentDate];
NSInteger yearNum = [ componentsYear year];
NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
[componentStartDate setDay:1];
[componentStartDate setMonth:1];
[componentStartDate setYear:yearNum];
NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
NSLog(@"Start date set to %@", startDate);
NSDateComponents *componentEndDate = [[NSDateComponents alloc] init];
[componentEndDate setDay:31];
[componentEndDate setMonth:12];
[componentEndDate setYear:yearNum];
NSDate *endDate = [gregorian dateFromComponents:componentEndDate];
NSLog(@"End date set to %@", endDate);
NSUInteger unitFlags = NSDayCalendarUnit ;
NSDateComponents *componentsDay = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0];
NSInteger days = [componentsDay day] +1;
NSLog(@"Number of days in the year:%d, is %d", yearNum,days);
[componentEndDate release];
[componentStartDate release];
[gregorian release];
if (days != 365 && days != 366)
return 366;
return days;
-(NSInteger) findDaysInMonth:(NSInteger) monthNum
NSInteger days = 30;
switch (monthNum)
case 1:
days = 31;
break;
case 2:
if([self findDaysInYear] == 366) days = 29;
else days = 28;
break;
case 3:
days = 31;
break;
case 4:
days = 30;
break;
case 5:
days = 31;
break;
case 6:
days = 30;
break;
case 7:
days = 31;
break;
case 8:
days = 31;
break;
case 9:
days = 30;
break;
case 10:
days = 31;
break;
case 11:
days = 30;
break;
case 12:
days = 31;
break;
default:
break;
return days;
-(void) resetDay
NSDate *currentDate = [endDatePicker date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *componentsYear = [gregorian components:(NSYearCalendarUnit| NSMonthCalendarUnit) fromDate:currentDate];
NSInteger yearNum = [ componentsYear year];
NSInteger monthNum = [componentsYear month];
NSDateComponents *componentStartDate = [[NSDateComponents alloc] init];
[componentStartDate setDay:[self findDaysInMonth:monthNum]];
[componentStartDate setMonth:monthNum];
[componentStartDate setYear:yearNum];
NSDate *startDate = [gregorian dateFromComponents:componentStartDate];
[endDatePicker setDate:startDate animated:YES];
[componentStartDate release];
[gregorian release];
【讨论】:
【参考方案8】:我正在使用一个简单的UIPickerView
,其中包含 2 个组件(月和年)。
并在每行选择时调用UIPickerViewDelegate
:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
//Today year and month
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"yyyy"];
int year = [[dateFormat stringFromDate:[NSDate date]] intValue];
[dateFormat setDateFormat:@"MM"];
int month = [[dateFormat stringFromDate:[NSDate date]] intValue] - 1;
//picker year and month
int selectedYear = [[self.yearsArray objectAtIndex:[pickerView selectedRowInComponent:1]] intValue];
int selectedMonth = [pickerView selectedRowInComponent:0];
// if month in the past, change the month
if (year == selectedYear && selectedMonth < month)
[pickerView selectRow:month inComponent:0 animated:YES];
【讨论】:
也许将 NSDateFormatter 作为 ivar,而不是在每次选择一行时初始化一个新的。【参考方案9】:您可以使用名为
的开源库AKMonthYearPickerView
import AKMonthYearPickerView
AKMonthYearPickerView.sharedInstance.show(vc: viewController, doneHandler: doneHandler, completetionalHandler: completetionalHandler)
https://github.com/ali-cs/AKMonthYearPickerView
使用 pod 安装它,
pod 'AKMonthYearPickerView'
自定义往年限制和条形颜色
AKMonthYearPickerView.sharedInstance.barTintColor = UIColor.blue
AKMonthYearPickerView.sharedInstance.previousYear = 4
【讨论】:
【参考方案10】:您可以使用 UICustomDatePicker 仅显示月份和年份选项
https://github.com/Anandsan/UICustomDatePicker
@interface ViewController ()
@property (nonatomic, weak) IBOutlet UICustomDatePicker *customDatePicker;
@end
-(void) viewDidLoad
[super viewDidLoad];
self.customDatePicker.option = NSCustomDatePickerOptionLongMonth | NSCustomDatePickerOptionYear;
self.customDatePicker.order = NSCustomDatePickerOrderMonthDayAndYear;
-(IBAction)didCustomDatePickerValueChanged:(id)sender
NSLog(@"%@",[(UICustomDatePicker *)sender currentDate]);
Refer the Screen
【讨论】:
欢迎来到 SO :) 请不要回答 只是 一个链接。还可以添加解释和/或一些代码以提高答案的质量。【参考方案11】:您可以像这样非常轻松地隐藏日期列:
datePicker.subviews[0].subviews[0].subviews[1].hidden = true
享受:)
【讨论】:
@CanAksoy 好的!它可能没有工作!但是你的问题到底是什么?我刚刚发现 UIDatePicker 的 NSLocale 是什么很重要。第三组子视图是 [月][日][年] 列。但是,例如法语,它将是 [day][month][year],而我上面的解决方案将隐藏月份列并显示日期列。因此,例如,如果您想隐藏法语集 UIDatePicker 的日期列,您可以这样做datePicker.subviews[0].subviews[0].subviews[0].hidden = true
。您还可以将月份列移动一点....subviews[1].frame.origin.x -= 50.0
虽然这可能非常有效,但强烈不推荐(因此,反对票)。你永远不应该像这样乱用 ios 标准控件,因为你不能保证它会在下一次 iOS 更新后保持在这个确切的层次结构索引中。而是(正如大多数其他答案所暗示的那样)继承默认的 UIPickerView 并给它一个仅满足一个月和一年的需求的委托。
抱歉,选民们讨厌我,因为这是他们无法想出的单线简单解决方案;)和平!以上是关于UIDatePicker 选择月份和年份的主要内容,如果未能解决你的问题,请参考以下文章