Custom iOS UIDatepicker using UIAppearance

人走茶凉 提交于 2020-01-08 19:41:28

问题


UNIQLO's new alarm app has a custom UIDatePicker:

And I want to create my own custom UIDatePicker.

I tried to change the appearance of the DatePicker, but looking for UI_APPEARANCE_SELECTOR in the UIDatePicker returns nothing.

Meaning that its not possible to change any values, as per the docs:

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

How can change my UIDatePicker's appearance?


回答1:


The API does not provide a way to do this. You can make a pretty convincing replica yourself using a UIPickerView rather than using UIDatePicker.

As the UIDatePicker or UIPickerView don't have the UI_APPEARANCE_SELECTOR and even you can't change UIDatePicker contents' appearance as its UIControl and not having any delegate so it has its native appearance whereas in case of UIPickerView you can change its contents' appearance similar as in 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;
}

Check this out.




回答2:


add this method in your implementation file

-(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);
    }];
}

when you run your app it will display all the subviews of the datePicker on your console, just choose any index and modify them one by one

modify the viewDidLoad and insert this code

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];

In this case i change the background color of index "0", "4", "11"




回答3:


With iOS 5 the UIAppearance protocol was introduced, which lets you customize several UI elements. UIDatePicker happens to conform this protocol, so that is probably the easiest way to do this. That is, if you're willing to support only iOS 5 users. Matthew's option would probably the next best thing, which should also work with older iOS versions.




回答4:


It appears to be quite difficult to change the way a UIDatePicker appears.

The example you provided, in my opinion, is a sophisticated customization of a simple UIPickerView with two columns and probably a simulated infinite scroll (as Apple does in the date picker, and it's quite simple to realize).

You can change little of the UIDatePicker through the UIAppearance proxy, as seen in this example:

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];

Using this piece of code at the start of the application (just try it) you can change the aspect of only a couple of the main components of the date picker.

Labels are impossible to customize (and this test code proves it); apparently they are changed in aspect every time you rotate a column, since they are put inside a custom UITableView controller.

To fully change these appearances you should probably work with private APIs from Apple, that will eventually result in your app being rejected.

If you just need a custom hour-minute picker (as shown in your screenshot), the full customization of appearance is reachable only extending the UIPickerView class or assigning an appropriate delegate to a UIPickerView instance.

Through the

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

method on the delegate you can make the single element of the picker view appear the way you want. Then you will have to appropriately handle the data source to make the two components of the picker virtually infinite.




回答5:


You can implement one yourself using two UIScrollViews, one for hours and one for minutes. You would just need to figure out the contentOffset of each scrollview when it has stopped moving, which off the top of my head would look like this:

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

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
  // also get the offset here
}

Take the value of the content offset and translate it into the hour value and minute value, probably by dividing the y position of the content offset by the 24 or 60 respectively. You will need to make the custom artwork yourself.




回答6:


To change date picker color:

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

And to change font the only way I know is:

Create category UIFont+System and place this code inside

#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

This will set as well fonts in another places in your app (replacing system font by your font).




回答7:


You should go through the UICatalog by Apple. It has all the methods in which a UIDatePicker can be used including the custom date picker method . Study this link developer.apple.com/library/ios/samplecode/UICatalog/ . Also they have implemented a standard switch and the navigation bar which is given in the latter.




回答8:


A combination of 2 UITableViews is the way to go.

UITableView is a subview of UIScrollView, so it handles the following event

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

}

and on getting the position, just scroll the table to the center using the following method

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

Hope this helps.



来源:https://stackoverflow.com/questions/10844675/custom-ios-uidatepicker-using-uiappearance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!