【问题标题】:Custom iOS UIDatepicker using UIAppearance使用 UIAppearance 自定义 iOS UIDatepicker
【发布时间】:2012-06-06 08:44:10
【问题描述】:

UNIQLO's new alarm app 有一个自定义的UIDatePicker

我想创建自己的自定义UIDatePicker

我尝试更改 DatePicker 的外观,但在 UIDatePicker 中查找 UI_APPEARANCE_SELECTOR 会返回 nothing

这意味着它不可能更改任何值,根据文档:

To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR.

如何更改我的UIDatePicker 的外观?

【问题讨论】:

  • 请原谅这个巨大的图像..
  • 您只需要 UIDatePicker 中的 2 个组件,还是只需要自定义文本的白色字体?
  • 尽我所能自定义:字体、颜色、一切。
  • 请看我已经自定义了picker的内部视图,您可以根据需要更改代码。
  • 您在使用我采用的方法自定义选择器内容时遇到任何问题吗?

标签: iphone ios ios5 uidatepicker uiappearance


【解决方案1】:

API 不提供执行此操作的方法。 您可以使用 UIPickerView 而不是使用 UIDatePicker 自己制作一个非常令人信服的副本。

由于 UIDatePicker 或 UIPickerView 没有 UI_APPEARANCE_SELECTOR,即使您无法将 UIDatePicker 内容的外观更改为其 UIControl 并且没有任何委托,因此它具有其本机外观,而在 UIPickerView 的情况下,您可以更改其内容'外观类似于 UITableView。

#pragma mark -
#pragma mark UIPicker Delegate & DataSource

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 2;
}

// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    return 100;
}
//- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:  (NSInteger)component {
     //    return [NSString stringWithFormat:@"%d",row];
//}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {

      UILabel *label= [[[UILabel alloc] initWithFrame:CGRectMake(30.0, 0.0, 50.0, 50.0)] autorelease];
      [label setBackgroundColor:[UIColor clearColor]];
      [label setTextColor:[UIColor blueColor]];
      [label setFont:[UIFont boldSystemFontOfSize:40.0]];
      [label setText:[NSString stringWithFormat:@"%d",row]];

      return label;
}

看看这个。

【讨论】:

    【解决方案2】:

    在你的实现文件中添加这个方法

    -(UIView *)pickerViews{
    
        return ([datePicker.subviews objectAtIndex:0]);
    }
    
    -(void)viewDidLoad{
    
        [super viewDidLoad];
    
        [[self pickerViews].subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSLog(@"%@ --- > %i",obj, idx);
        }];
    }
    

    当您运行您的应用程序时,它将在您的控制台上显示 datePicker 的所有子视图,只需选择任何索引并一一修改它们

    修改viewDidLoad并插入这段代码

    UIView *background = (UIView *)[[self pickerViews].subviews objectAtIndex:0];
    background.backgroundColor = [UIColor clearColor];
    
    UIView *wheel2 = (UIView *)[[self pickerViews].subviews objectAtIndex:4];
    wheel2.backgroundColor = [UIColor redColor];
    
    UIView *wheel3 = (UIView *)[[self pickerViews].subviews objectAtIndex:11];
    wheel3.backgroundColor = [UIColor redColor];
    

    在这种情况下,我更改索引“0”、“4”、“11”的背景颜色

    【讨论】:

      【解决方案3】:

      在 iOS 5 中引入了UIAppearance 协议,它允许您自定义多个 UI 元素。 UIDatePicker 恰好符合这个协议,所以这可能是最简单的方法。也就是说,如果您愿意只支持 iOS 5 用户。 Matthew 的选项可能是次优选择,它也应该适用于较旧的 iOS 版本。

      【讨论】:

      • 谢谢我忘了 UIAppearance
      • 抱歉,Scott,我无法让 UIAppearance 在 UIDatePicker 上工作。请查看已编辑的问题。
      • 这应该是一个评论,而不是一个答案,因为它只建议使用 UIAppearance,而不是如何在这种情况下使用它。
      • 不,您不能使用外观来更改UIDatePickers 图形。查看我的答案以获得更多见解。
      【解决方案4】:

      似乎很难改变UIDatePicker 的出现方式。

      在我看来,您提供的示例是一个简单的 UIPickerView 的复杂定制,它有两列,可能是一个模拟的无限滚动(就像 Apple 在日期选择器中所做的那样,实现起来非常简单)。

      您可以通过UIAppearance 代理对UIDatePicker 进行少量更改,如下例所示:

      UIDatePicker *picker = [UIDatePicker appearance];
      picker.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.3];
      
      UIView *view;
      view = [UIView appearanceWhenContainedIn:[UITableView class], [UIDatePicker class], nil];
      view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
      
      UILabel *label = [UILabel appearanceWhenContainedIn:[UITableView class], [UIDatePicker class], nil];
      label.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
      label.textColor = [UIColor blueColor];
      

      在应用程序启动时使用这段代码(试一试),您只能更改日期选择器的几个主要组件的外观。

      标签是不可能自定义的(这个测试代码证明了这一点);显然,每次旋转列时它们的外观都会发生变化,因为它们被放在自定义 UITableView 控制器中。

      要完全改变这些外观,您可能应该使用 Apple 的私有 API,这最终会导致您的应用被拒绝

      如果您只需要自定义小时-分钟选择器(如屏幕截图所示),则只能扩展 UIPickerView 类或将适当的委托分配给 UIPickerView 实例,才能实现外观的完全自定义。

      通过

      - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
      

      委托上的方法,您可以使选择器视图的单个元素以您想要的方式显示。然后您必须适当地处理数据源,以使选择器的两个组件实际上是无限的。

      【讨论】:

      • 我查看了 UIApperance,但仍然看不到如何更改 UIDatePicker 的文本颜色。支持吗?
      • 正如我在回答中所说,标签是不可能自定义的。
      【解决方案5】:

      您可以使用两个 UIScrollView 自己实现一个,一个用于几小时,一个用于几分钟。您只需要计算每个滚动视图停止移动时的 contentOffset,在我的脑海中看起来像这样:

      - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
        if (!decelerate) {
          // get the offset here
        }
      }
      
      - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        // also get the offset here
      }
      

      获取内容偏移量的值并将其转换为小时值和分钟值,可能是通过将内容偏移量的 y 位置分别除以 24 或 60。您需要自己制作自定义艺术品。

      【讨论】:

      • 请注意,选择器具有“无限”滚动:当您到达终点(例如 59)时,您会回到起点。实际上,确实没有结束和开始,但由于那里的数字,它看起来如此。在自定义 UIScrollView 以模仿 UIDatePicker 行为时,这绝对是需要牢记的。
      • 是的,这是真的。我刚刚下载了 UNIQLO 应用程序进行检查,它还需要伪造无限滚动(当然,这也会使数学复杂化)并且还需要使用分页的一些技巧来使滚动视图锁定到特定位置。跨度>
      • 在没有完全考虑到这一点的情况下,我认为 UITableView 可能是一种选择。不涉及复杂的数学运算,只是在滚动到它们时懒惰地继续添加单元格。重用单元格只会对性能造成很小的影响,使用“scrollToRowAtIndexPath”对位置锁定机制很有用。
      【解决方案6】:

      更改日期选择器颜色:

      [datePickerView setValue:self.pickerLabelColor forKey:@"textColor"];
      

      而要更改字体,我知道的唯一方法是:

      创建类别UIFont+System并将此代码放入其中

      #pragma clang diagnostic push
      #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
          + (UIFont *)systemFontOfSize:(CGFloat)fontSize
          {
              return [UIFont fontWithName:fontName size:fontSize];
          }
      #pragma clang diagnostic pop
      

      这将在您的应用程序的其他位置设置字体(用您的字体替换系统字体)。

      【讨论】:

        【解决方案7】:

        您应该浏览 Apple 的 UICatalog。它具有可以使用 UIDatePicker 的所有方法,包括自定义日期选择器方法。研究这个链接 developer.apple.com/library/ios/samplecode/UICatalog/ 。他们还实现了标准开关和后者中给出的导航栏。

        【讨论】:

          【解决方案8】:

          2个UITableViews的组合是要走的路。

          UITableViewUIScrollView的子视图,所以它处理下面的事件

          -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
          {
          
          }
          

          获取位置后,只需使用以下方法将表格滚动到中心

          [myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
          

          希望这会有所帮助。

          【讨论】:

            猜你喜欢
            • 2012-01-09
            • 1970-01-01
            • 2012-12-05
            • 1970-01-01
            • 2013-09-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-17
            相关资源
            最近更新 更多