fonts - ¿Puedo cambiar el color de la fuente de datePicker en iOS7?
xcode5 (12)
"No se puede personalizar la apariencia de los selectores de fecha".
Consulte Recursos de diseño de iOS 7 / Catálogo de interfaz de usuario de UIKit / Selector de fecha
Acabo de descargar mi copia de xcode 5 y me preguntaba si alguien sabe cómo puedo cambiar el color o el tamaño de la fuente en el selector de fecha.
¡Esta es la manera más simple y funciona! Lo prometo. Cree el UIDatePicker en la vista, o conéctelo mediante un guión gráfico, luego coloque el siguiente código en el método ViewDidLoad. Reemplace "datepicker" en la primera línea con lo que haya llamado su selector de fecha.
C objetivo:
//Set Color of Date Picker
self.datePicker.datePickerMode = UIDatePickerModeDate;
[self.datePicker setValue:[UIColor colorWithRed:70/255.0f green:161/255.0f blue:174/255.0f alpha:1.0f] forKeyPath:@"textColor"];
SEL selector = NSSelectorFromString(@"setHighlightsToday:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDatePicker instanceMethodSignatureForSelector:selector]];
BOOL no = NO;
[invocation setSelector:selector];
[invocation setArgument:&no atIndex:2];
[invocation invokeWithTarget:self.datePicker];
En swift puedes agregar estas dos líneas a tu viewDidLoad:
datePicker.setValue(DesignHelper.getOffWhiteColor(), forKey: "textColor")
datePicker.performSelector("setHighlightsToday:", withObject: UIColor.whiteColor())
En viewDidLoad,
datePicker.setValue(UIColor.yellowColor(), forKey: "textColor")
datePicker.performSelector("setHighlightsToday:", withObject:UIColor.yellowColor())
Trabajando para iOS 9
Encontré una solución sorprendentemente limpia usando UIAppearance
. Descubrí que intentar establecer textColor
través de UIAppearance
para cualquier UILabel
dentro de UIPickerView
no tenía ningún efecto, pero una propiedad de apariencia personalizada que simplemente llamaba al regular textColor
setter funcionaba bien.
// Implement a custom appearance property via a UILabel category
@interface UILabel (PickerLabelTextColor)
@property (nonatomic, strong) UIColor * textColorWorkaround UI_APPEARANCE_SELECTOR;
@end
@implementation UILabel (PickerLabelTextColor)
- (UIColor *)textColorWorkaround {
return self.textColor;
}
- (void)setTextColorWorkaround:(UIColor *)textColor {
self.textColor = textColor;
}
@end
Y luego use de la siguiente manera:
UILabel *pickerLabelProxy = [UILabel appearanceWhenContainedInInstancesOfClasses:@[UIPickerView.class]];
pickerLabelProxy.textColorWorkaround = UIColor.lightGrayColor;
Esto funciona en iOS 9
[datePicker setValue:[UIColor whiteColor] forKey:@"textColor"];
Estoy luchando con esto también, texto negro sobre fondo negro. :) Aún no he encontrado una forma de cambiar el color del texto. Sin embargo, puedes jugar con el color de fondo:
picker.backgroundColor = [UIColor whiteColor];
Otro truco que encontré que funcionó es dar cada UIView en el datepicker (cada número tiene su propia UIView, (sí lo sé)
[UIView appearanceWhenContainedIn:[UITableView class], [UIDatePicker class], nil].backgroundColor = [UIColor colorWithWhite:1 alpha:0.5]
(No recomiendo usar esta opción ya que causa un efecto de parpadeo molesto mientras gira.)
Espero que esto ayude. :)
Necesito algo similar para mi aplicación y he terminado yendo por el camino más largo. Es una verdadera lástima que no haya una manera más sencilla de cambiar a una versión de texto blanca de UIDatePicker.
El código siguiente utiliza una categoría en UILabel para forzar que el color del texto de la etiqueta sea blanco cuando el mensaje setTextColor: se envía a la etiqueta. Para no hacer esto para cada etiqueta en la aplicación, lo he filtrado para que solo se aplique si es una subvista de una clase UIDatePicker. Finalmente, algunas de las etiquetas tienen sus colores establecidos antes de que se agreguen a sus supervistas. Para atraparlos, el código anula el método willMoveToSuperview:
Es probable que sea mejor dividir el siguiente en más de una categoría, pero lo he agregado todo aquí para facilitar la publicación.
#import "UILabel+WhiteUIDatePickerLabels.h"
#import <objc/runtime.h>
@implementation UILabel (WhiteUIDatePickerLabels)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swizzleInstanceSelector:@selector(setTextColor:)
withNewSelector:@selector(swizzledSetTextColor:)];
[self swizzleInstanceSelector:@selector(willMoveToSuperview:)
withNewSelector:@selector(swizzledWillMoveToSuperview:)];
});
}
// Forces the text colour of the label to be white only for UIDatePicker and its components
-(void) swizzledSetTextColor:(UIColor *)textColor {
if([self view:self hasSuperviewOfClass:[UIDatePicker class]] ||
[self view:self hasSuperviewOfClass:NSClassFromString(@"UIDatePickerWeekMonthDayView")] ||
[self view:self hasSuperviewOfClass:NSClassFromString(@"UIDatePickerContentView")]){
[self swizzledSetTextColor:[UIColor whiteColor]];
} else {
//Carry on with the default
[self swizzledSetTextColor:textColor];
}
}
// Some of the UILabels haven''t been added to a superview yet so listen for when they do.
- (void) swizzledWillMoveToSuperview:(UIView *)newSuperview {
[self swizzledSetTextColor:self.textColor];
[self swizzledWillMoveToSuperview:newSuperview];
}
// -- helpers --
- (BOOL) view:(UIView *) view hasSuperviewOfClass:(Class) class {
if(view.superview){
if ([view.superview isKindOfClass:class]){
return true;
}
return [self view:view.superview hasSuperviewOfClass:class];
}
return false;
}
+ (void) swizzleInstanceSelector:(SEL)originalSelector
withNewSelector:(SEL)newSelector
{
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method newMethod = class_getInstanceMethod(self, newSelector);
BOOL methodAdded = class_addMethod([self class],
originalSelector,
method_getImplementation(newMethod),
method_getTypeEncoding(newMethod));
if (methodAdded) {
class_replaceMethod([self class],
newSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, newMethod);
}
}
@end
Respondí una pregunta similar aquí: UIPickerView Custom Fonts iOS7 Básicamente tienes que hackear el método viewForRow: y en este momento solo lo tengo funcionando para UIPateView''s UIDatePickers. (trabajando en ello...)
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
Y así es como un UIPickerView para mostrar texto atribuido (fuentes personalizadas, colores, etc.)
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
// create attributed string
NSString *yourString; //can also use array[row] to get string
NSDictionary *attributeDict = @{NSForegroundColorAttributeName : [UIColor whiteColor]};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:yourString attributes:attributeDict];
// add the string to a label''s attributedText property
UILabel *labelView = [[UILabel alloc] init];
labelView.attributedText = attributedString;
// return the label
return labelView;
}
Espero que ayude ... ¡Editaré mi respuesta tan pronto como descubra el selector de fecha!
Seguí adelante e implementé un reemplazo de UIDatePicker
usando UIControl
y UIPicker
para iOS 7. Eso te permite editar todo lo que quieras, incluyendo fuentes de texto y colores. Lo único que no pude cambiar es el color de las líneas alrededor de la fila seleccionada.
Hay cosas que podrían simplificarse aún más y muestra solo la fecha, no el tiempo. Esto podría servir como punto de partida para cualquiera que desee hacer algo similar.
@interface SBDatePicker : UIControl
@property (nonatomic, strong, readwrite) NSDate *minimumDate;
@property (nonatomic, strong, readwrite) NSDate *maximumDate;
@property (nonatomic, strong, readwrite) NSDate *date;
- (void)setDate:(NSDate *)date animated:(BOOL)animated;
@end
#import "SBDatePicker.h"
const NSUInteger NUM_COMPONENTS = 3;
typedef enum {
kSBDatePickerInvalid = 0,
kSBDatePickerYear,
kSBDatePickerMonth,
kSBDatePickerDay
} SBDatePickerComponent;
@interface SBDatePicker () <UIPickerViewDataSource, UIPickerViewDelegate> {
SBDatePickerComponent _components[NUM_COMPONENTS];
}
@property (nonatomic, strong, readwrite) NSCalendar *calendar;
@property (nonatomic, weak, readwrite) UIPickerView *picker;
@property (nonatomic, strong, readwrite) NSDateFormatter *dateFormatter;
@property (nonatomic, strong, readwrite) NSDateComponents *currentDateComponents;
@property (nonatomic, strong, readwrite) UIFont *font;
@end
@implementation SBDatePicker
#pragma mark - Life cycle
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
[self commonInit];
return self;
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (!self) {
return nil;
}
[self commonInit];
return self;
}
- (void)commonInit {
self.tintColor = [UIColor whiteColor];
self.font = [UIFont systemFontOfSize:23.0f];
self.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[self setLocale:[NSLocale currentLocale]];
UIPickerView *picker = [[UIPickerView alloc] initWithFrame:self.bounds];
picker.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
picker.dataSource = self;
picker.delegate = self;
picker.tintColor = [UIColor whiteColor];
self.date = [NSDate date];
[self addSubview:picker];
self.picker = picker;
}
- (CGSize)intrinsicContentSize {
return CGSizeMake(320.0f, 216.0f);
}
#pragma mark - Setup
- (void)setMinimumDate:(NSDate *)minimumDate {
_minimumDate = minimumDate;
[self updateComponents];
}
- (void)setMaximumDate:(NSDate *)maximumDate {
_maximumDate = maximumDate;
[self updateComponents];
}
- (void)setDate:(NSDate *)date {
[self setDate:date animated:NO];
}
- (void)setDate:(NSDate *)date animated:(BOOL)animated {
self.currentDateComponents = [self.calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:date];
[self.picker reloadAllComponents];
[self setIndicesAnimated:YES];
}
- (NSDate *)date {
return [self.calendar dateFromComponents:self.currentDateComponents];
}
- (void)setLocale:(NSLocale *)locale {
self.calendar.locale = locale;
[self updateComponents];
}
- (SBDatePickerComponent)componentFromLetter:(NSString *)letter {
if ([letter isEqualToString:@"y"]) {
return kSBDatePickerYear;
}
else if ([letter isEqualToString:@"m"]) {
return kSBDatePickerMonth;
}
else if ([letter isEqualToString:@"d"]) {
return kSBDatePickerDay;
}
else {
return kSBDatePickerInvalid;
}
}
- (SBDatePickerComponent)thirdComponentFromFirstComponent:(SBDatePickerComponent)component1
andSecondComponent:(SBDatePickerComponent)component2 {
NSMutableIndexSet *set = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(kSBDatePickerInvalid + 1, NUM_COMPONENTS)];
[set removeIndex:component1];
[set removeIndex:component2];
return (SBDatePickerComponent) [set firstIndex];
}
- (void)updateComponents {
NSString *componentsOrdering = [NSDateFormatter dateFormatFromTemplate:@"yMMMMd" options:0 locale:self.calendar.locale];
componentsOrdering = [componentsOrdering lowercaseString];
NSString *firstLetter = [componentsOrdering substringToIndex:1];
NSString *lastLetter = [componentsOrdering substringFromIndex:(componentsOrdering.length - 1)];
_components[0] = [self componentFromLetter:firstLetter];
_components[2] = [self componentFromLetter:lastLetter];
_components[1] = [self thirdComponentFromFirstComponent:_components[0] andSecondComponent:_components[2]];
self.dateFormatter = [[NSDateFormatter alloc] init];
self.dateFormatter.calendar = self.calendar;
self.dateFormatter.locale = self.calendar.locale;
[self.picker reloadAllComponents];
[self setIndicesAnimated:NO];
}
- (void)setIndexForComponentIndex:(NSUInteger)componentIndex animated:(BOOL)animated {
SBDatePickerComponent component = [self componentForIndex:componentIndex];
NSRange unitRange = [self rangeForComponent:component];
NSInteger value;
if (component == kSBDatePickerYear) {
value = self.currentDateComponents.year;
}
else if (component == kSBDatePickerMonth) {
value = self.currentDateComponents.month;
}
else if (component == kSBDatePickerDay) {
value = self.currentDateComponents.day;
}
else {
assert(NO);
}
NSInteger index = (value - unitRange.location);
NSInteger middleIndex = (INT16_MAX / 2) - (INT16_MAX / 2) % unitRange.length + index;
[self.picker selectRow:middleIndex inComponent:componentIndex animated:animated];
}
- (void)setIndicesAnimated:(BOOL)animated {
for (NSUInteger componentIndex = 0; componentIndex < NUM_COMPONENTS; componentIndex++) {
[self setIndexForComponentIndex:componentIndex animated:animated];
}
}
- (SBDatePickerComponent)componentForIndex:(NSInteger)componentIndex {
return _components[componentIndex];
}
- (NSCalendarUnit)unitForComponent:(SBDatePickerComponent)component {
if (component == kSBDatePickerYear) {
return NSYearCalendarUnit;
}
else if (component == kSBDatePickerMonth) {
return NSMonthCalendarUnit;
}
else if (component == kSBDatePickerDay) {
return NSDayCalendarUnit;
}
else {
assert(NO);
}
}
- (NSRange)rangeForComponent:(SBDatePickerComponent)component {
NSCalendarUnit unit = [self unitForComponent:component];
return [self.calendar maximumRangeOfUnit:unit];
}
#pragma mark - Data source
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 3;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)componentIndex {
return INT16_MAX;
}
#pragma mark - Delegate
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)componentIndex {
SBDatePickerComponent component = [self componentForIndex:componentIndex];
if (component == kSBDatePickerYear) {
CGSize size = [@"0000" sizeWithAttributes:@{NSFontAttributeName : self.font}];
return size.width + 25.0f;
}
else if (component == kSBDatePickerMonth) {
CGFloat maxWidth = 0.0f;
for (NSString *monthName in self.dateFormatter.monthSymbols) {
CGFloat monthWidth = [monthName sizeWithAttributes:@{NSFontAttributeName : self.font}].width;
maxWidth = MAX(monthWidth, maxWidth);
}
return maxWidth + 25.0f;
}
else if (component == kSBDatePickerDay) {
CGSize size = [@"00" sizeWithAttributes:@{NSFontAttributeName : self.font}];
return size.width + 25.0f;
}
else {
return 0.01f;
}
}
- (NSString *)titleForRow:(NSInteger)row forComponent:(SBDatePickerComponent)component {
NSRange unitRange = [self rangeForComponent:component];
NSInteger value = unitRange.location + (row % unitRange.length);
if (component == kSBDatePickerYear) {
return [NSString stringWithFormat:@"%li", (long) value];
}
else if (component == kSBDatePickerMonth) {
return [self.dateFormatter.monthSymbols objectAtIndex:(value - 1)];
}
else if (component == kSBDatePickerDay) {
return [NSString stringWithFormat:@"%li", (long) value];
}
else {
return @"";
}
}
- (NSInteger)valueForRow:(NSInteger)row andComponent:(SBDatePickerComponent)component {
NSRange unitRange = [self rangeForComponent:component];
return (row % unitRange.length) + unitRange.location;
}
- (BOOL)isEnabledRow:(NSInteger)row forComponent:(NSInteger)componentIndex {
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.year = self.currentDateComponents.year;
dateComponents.month = self.currentDateComponents.month;
dateComponents.day = self.currentDateComponents.day;
SBDatePickerComponent component = [self componentForIndex:componentIndex];
NSInteger value = [self valueForRow:row andComponent:component];
if (component == kSBDatePickerYear) {
dateComponents.year = value;
}
else if (component == kSBDatePickerMonth) {
dateComponents.month = value;
}
else if (component == kSBDatePickerDay) {
dateComponents.day = value;
}
NSDate *rowDate = [self.calendar dateFromComponents:dateComponents];
if (self.minimumDate != nil && [self.minimumDate compare:rowDate] == NSOrderedDescending) {
return NO;
}
else if (self.maximumDate != nil && [rowDate compare:self.maximumDate] == NSOrderedDescending) {
return NO;
}
return YES;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)componentIndex reusingView:(UIView *)view {
UILabel *label;
if ([view isKindOfClass:[UILabel class]]) {
label = (UILabel *) view;
}
else {
label = [[UILabel alloc] init];
label.font = self.font;
}
SBDatePickerComponent component = [self componentForIndex:componentIndex];
NSString *title = [self titleForRow:row forComponent:component];
UIColor *color;
BOOL enabled = [self isEnabledRow:row forComponent:componentIndex];
if (enabled) {
color = [UIColor whiteColor];
}
else {
color = [UIColor colorWithWhite:0.0f alpha:0.5f];
}
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:@{NSForegroundColorAttributeName: color}];
label.attributedText = attributedTitle;
if (component == kSBDatePickerMonth) {
label.textAlignment = NSTextAlignmentLeft;
}
else {
label.textAlignment = NSTextAlignmentRight;
}
return label;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)componentIndex {
SBDatePickerComponent component = [self componentForIndex:componentIndex];
NSInteger value = [self valueForRow:row andComponent:component];
if (component == kSBDatePickerYear) {
self.currentDateComponents.year = value;
}
else if (component == kSBDatePickerMonth) {
self.currentDateComponents.month = value;
}
else if (component == kSBDatePickerDay) {
self.currentDateComponents.day = value;
}
else {
assert(NO);
}
[self setIndexForComponentIndex:componentIndex animated:NO];
NSDate *datePicked = self.date;
if (self.minimumDate != nil && [datePicked compare:self.minimumDate] == NSOrderedAscending) {
[self setDate:self.minimumDate animated:YES];
}
else if (self.maximumDate != nil && [datePicked compare:self.maximumDate] == NSOrderedDescending) {
[self setDate:self.maximumDate animated:YES];
}
else {
[self.picker reloadAllComponents];
}
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
@end
Un poco hacky, pero de nuevo, también lo son todas las otras soluciones. Esto funcionó para mí: subclase UIDatePicker y cambiar el valor del atributo textColor antes de agregarle ninguna vista.
Para cambiar solo el color:
class ColoredDatePicker: UIDatePicker {
var changed = false
override func addSubview(view: UIView) {
if !changed {
changed = true
self.setValue(yourColor, forKey: "textColor")
}
super.addSubview(view)
}
}
Para cambiar el color y otros atributos:
Actualizaré si descubro esto.
Me doy cuenta de que el color no está representado exactamente como lo haría el objeto de color, pero juego con él y obtengo el color que desea.
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.backgroundColor = [UIColor grayColor];
label.textColor = [UIColor whiteColor];
label.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:18];
label.text = [NSString stringWithFormat:@" %d", row+1];
return label;
}
// number Of Components
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
// number Of Rows In Component
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component{
return 6;
}