18

I want to change the border color of a UIPickerView. I do not see a tint property for the UIPickerView. Is there any way this could be done? Or a workaround?

Thanks.

lostInTransit
  • 70,519
  • 61
  • 198
  • 274

9 Answers9

27

You could also mask the component. With a bit fiddeling you can get the size of the component and cut it out with following code:

CALayer* mask = [[CALayer alloc] init];
        [mask setBackgroundColor: [UIColor blackColor].CGColor];
        [mask setFrame:  CGRectMake(10.0f, 10.0f, 260.0f, 196.0f)];
        [mask setCornerRadius: 5.0f];
        [picker.layer setMask: mask];
        [mask release];

Don't forget

#import <QuartzCore/QuartzCore.h>
Quxflux
  • 3,133
  • 2
  • 26
  • 46
  • 5
    In XCode 4+, you need the frame: [mask setFrame: CGRectMake(10.0f, 10.0f, 260.0f, 196.0f)];, but otherwise very useful, and doesn't require using image overlays. – Shaun Jan 10 '12 at 11:47
  • 1
    Interesting. This *almost* works. Looks like it's not clipping all of the right side. http://screencast.com/t/MVyxOIj0mGRT ... Edit: wouldn't make more sense to calc insets from the picker.bounds ? –  Jun 15 '13 at 10:51
  • Code like 'CGRectMake(10.0f, 10.0f, 260.0f, 196.0f)' is very bad. – Dmitry Oct 01 '13 at 16:56
  • @Altaveron because it's hardcoded? Creating an image and overlaying components with it is worse. Maybe you can provide an improved solution? – Quxflux Oct 03 '13 at 08:55
  • Yes, I've added UIView under UIPickerView with the same frame. And a mask can be created with the same frame too. – Dmitry Oct 03 '13 at 09:04
18

If you just want a workaround, take a screen shot in the simulator, open it in photoshop, crop it to just the UIPickerView area, make the center transparent, apply whatever tint you want, add that image to your project, and add it as a UIImageView on top of the UIPickerView.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Ed Marty
  • 39,590
  • 19
  • 103
  • 156
  • Thanks. No other way we can change the tint? – lostInTransit Jun 08 '09 at 16:56
  • I believe the background is just an image anyway, so it's likely that even if you were able to find the element in the subviews, it wouldn't be tint-able. – Ed Marty Jun 09 '09 at 13:44
  • how to change whole background color of the UIPickerView ? I try customize the view use the method '- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view " although the row view was updated but the left content of the Picker still show original gray color ... how to solve it ? thanks... – iXcoder Mar 03 '10 at 14:08
14

My UIPickerView has 3 components. And no Selection Indicator.

This gives it 11 subviews. [[picker subviews] count]

Hiding the first and the last subview totally removes the background.

[(UIView*)[[picker subviews] objectAtIndex:0] setHidden:YES];
[(UIView*)[[picker subviews] objectAtIndex:10] setHidden:YES];

Hiding every third other subview (indexes 1, 4 and 7) hides the opaque background on the components. Giving quite a nice effect that I can skin as I desire.

Hope that helps someone :)

Shaggy Frog
  • 27,575
  • 16
  • 91
  • 128
adam
  • 22,404
  • 20
  • 87
  • 119
  • Clever. Although Apple might not like it. – Moshe Aug 07 '11 at 22:05
  • Apple will most likely not know any different, it is not using any private APIs that their analyzer will flag. – adam Aug 11 '11 at 10:28
  • 6
    The picker will not have subviews until it is fully loaded. If you try to do this in the viewDidLoad or viewWillAppear it will not work. However, I moved mine into one of the UIPickerView protocol methods and it worked.- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { . – Matt Hudson Mar 09 '12 at 18:23
  • my friend's made an app which has custom picker view, the apple rejected it... now i'm being confuse is this a correct way or not... please tell me !! – TheTiger Jun 01 '12 at 07:20
  • did we get a ruling on whether this was legal? – Grymjack Jan 15 '13 at 13:12
  • Have done this on many released apps. That's no absolute guarantee, but it appears fine. – adam Jan 15 '13 at 13:36
  • Since number of objects can vary and the background is always the first and last object couldn't you do `[(UIView*)[[pickerView subviews] lastObject] setHidden:YES];` – Alex Reynolds Jan 19 '13 at 01:35
5

The picker will not have subviews until it is fully loaded. If you try to do this:

[(UIView*)[[picker subviews] objectAtIndex:0] setHidden:YES];
[(UIView*)[[picker subviews] objectAtIndex:10] setHidden:YES];

in the viewDidLoad or viewWillAppear it will not work. However, I moved mine into one of the UIPickerView protocol methods and it removed the background frame.

- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    if (self.pickerBackgroundNotHidden)
    {
        self.pickerBackgroundNotHidden = false;
        [(UIView*)[[tempPicker subviews] objectAtIndex:0] setHidden:YES];
        [(UIView*)[[tempPicker subviews] objectAtIndex:7] setHidden:YES];
        [(UIView*)[[tempPicker subviews] objectAtIndex:8] setHidden:YES];
    }
    return [arrayColors objectAtIndex:row];
}

You could probably subclass the picker to do this a little more efficiently, but I prefer to avoid subclassing.

Oh, also, this is probably obvious, but if your picker doesn't have any items in it, the code above will not delete the sub views.

Matt Hudson
  • 7,329
  • 5
  • 49
  • 66
4

Here is a modern, pixel-perfect version w/ ARC of @Lukas 's answer, because some questions never go out of style:

#import <QuartzCore/QuartzCore.h>

// . . .

CALayer* mask = [[CALayer alloc] init];
         mask.backgroundColor = [UIColor blackColor].CGColor;
         mask.frame = CGRectInset(picker.bounds, 10.0f, 10.0f);
         mask.cornerRadius = 5.0f;
         picker.layer.mask = mask;

This answer works for ANY size of picker b/c the layer dimensions are calculated on-the-fly.

                                                                 enter image description here

2

You can change background color by completely replacing the background image with one of your choice using IXPickerOverlayView available on GitHub (the repo contains an illustrated example of using this class).

Note that you'll have to draw out the (rectangular) background yourself from scratch but unlike any of the workarounds mentioned here this approach is fully dynamic: the control will look correctly even if you change the number of picker wheels and their sizes in runtime (like UIDatePicker does when you change your system locale setting).

Once you have your background image, using IXPickerOverlayView is as simple as adding a IXPickerOverlayView instance on top of your Picker view and assigning hostPickerView property.

Leon Deriglazov
  • 1,132
  • 9
  • 13
1

Actualy to correct you, you actualy can put a .png ontop of the UIPickerview and still use the Picker View, just make sure the middle is transparent or you won't see the rows.

Jab
  • 26,853
  • 21
  • 75
  • 114
0

Simply add this line to one of your UIPickerView methods:

[[[MyPicker subviews] objectAtIndex:4] setBackgroundColor: [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"image.png"]]];
Guntis Treulands
  • 4,764
  • 2
  • 50
  • 72
Houtan
  • 1
0

You can do the following:

set the picker view background colour by wizard or by code as follow:

Picker1.backgroundColor = [UIColor someColor];// clearColor for transparent

Set alpha value for the picker view subviews numbered 0, 1 and 3. (Don't know why there is subview 2 thought). Do it by code after the first load data for the picker view as follow (it will throw an exception if you do this in the DidViewLoad).

[(UIView*)[[Picker1 subviews] objectAtIndex:0] setAlpha:someValue];// 0.0f for transparent
[(UIView*)[[Picker1 subviews] objectAtIndex:1] setAlpha:someValue];
[(UIView*)[[Picker1 subviews] objectAtIndex:3] setAlpha:someValue];

Don't forget to clear background color for the label you are sending to the picker view in the viewForRow method.

lbl.backgroundColor = [UIColor someColor];// could be clearColor
hasan
  • 23,815
  • 10
  • 63
  • 101