5

Our UIPickerView has a dark background and the selection lines are incredibly hard to see. Is there anyway to change them to a colour of my choosing?

Update: I'm talking about the --- above and below the "Panda" item.

    Cat
    Dog
  Elephant
-----------
   Panda
-----------
   Bear
  Giraffe
cjhill
  • 1,004
  • 2
  • 9
  • 31
  • This answer worked a while ago. Less the release code and hopefully should still work: http://stackoverflow.com/questions/1466346/how-to-change-the-color-of-uipickerview-selector – App Dev Guy Dec 02 '14 at 05:35

7 Answers7

11

Swift 4.2

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {

        pickerView.subviews[1].backgroundColor = UIColor.white
        pickerView.subviews[2].backgroundColor = UIColor.white

        return view
    }

This works for me!

Dian
  • 115
  • 3
  • 12
  • Thanks a lot! In my case, I set .clear color do hide this separator lines 'pickerView.subviews.forEach { $0.backgroundColor = .clear }' – Alex Kolovatov Jul 06 '20 at 08:13
  • In iOS 14 I used a variation of this to get rid of the grey highlight background color for the selection: (safe is an operator that does range changing and returns nil if out of range): pickerView.subviews[safe:1]?.backgroundColor = UIColor.clear – Andy Weinstein Sep 30 '20 at 15:41
3

This has been answered here: How to change the color of UIPickerView Selector

Basically:

pickerView.subviews[1].backgroundColor = UIColor.whiteColor()
pickerView.subviews[2].backgroundColor = UIColor.whiteColor()
DeyaEldeen
  • 10,847
  • 10
  • 42
  • 75
ObjectiveTC
  • 2,477
  • 30
  • 22
  • @DeyaEldeen It still works, though you have to remember that the picker subview hierarchy might not be fully constructed by the time you have created the object, hence you might need to defer the calls to e.g. the time when your datasource is queried. – DrMickeyLauer Oct 23 '18 at 07:07
  • 1
    @DeyaEldeen either put the code in `titleForRow` or use a subclass, e.g. -(void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; self.backgroundColor = [LTPickerView appearance].backgroundColor; } -(void)didAddSubview:(UIView *)subview { [super didAddSubview:subview]; if ( subview.bounds.size.height <= 1.0 ) { UIColor* appearanceTintColor = [LTPickerView appearance].tintColor; if ( appearanceTintColor ) { subview.backgroundColor = appearanceTintColor; } } } – DrMickeyLauer Oct 25 '18 at 09:13
2

The best solution I can offer is to place 2 UIImages on top of your picker wheel at the width of 1 and length set to your preference. This is how I overcame this.

It does not work well if you require multiple size views so programatically doing it to cater for your size changes would be the next best solution. To programatically change the size using if statements:

How to resize the image programmatically in objective-c in iphone

If you change the size based on orientation add an if statement that handles orientation like so:

 if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
     // code for landscape orientation      
}
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
     // code for Portrait orientation       
}

Kind regards

Community
  • 1
  • 1
App Dev Guy
  • 5,396
  • 4
  • 31
  • 54
  • Not an ideal solution as I imagine it would be quite delicate, but it would do the job. Also best to set `showsSelectionIndicator` to `NO` if you do try this. – cjhill Dec 02 '14 at 10:07
  • I fully agree regarding being "not ideal", hence why I including the need to to calculate any future or past size alterations and orientation as I have had to in a few of my apps, I was just hoping that there was a newer solution not unlike yourself, but sadly there is not. While the iOS framework is quite powerful it's limited in many aspects and this is one of them. Fortunately as they move towards Swift and more web code like styling and coding, the flexibility should also increase. Glad I could help though. – App Dev Guy Dec 02 '14 at 12:26
2

Add this to your UIPickerView's viewForRow, titleForRow or attributedTitleForRow:

for lineSubview in pickerView.subviews {
  if lineSubview.frame.height < 1 {
    lineSubview.backgroundColor = UIColor.white.withAlphaComponent(0.15)
  }
}

This should be a little bit safer to use because we are looking for subviews that should be very short in height. If Apple changes the view hierarchy it most probably won't mess up anything :)

budiDino
  • 13,044
  • 8
  • 95
  • 91
1

Try something like this:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

    //On Selecting the component row
    if (component == 0) {

    } else if (component == 1) {

        [quantityPickerDelegate didChangeLabelText:[pickerArray objectAtIndex:row]];// delegate passing the selected value
        [pickerView reloadComponent:component]; //This will cause your viewForComp to hit
    }
}

- (UIView *)viewForRow:(NSInteger)row forComponent:(NSInteger)component
 {
 //...
 //Your usual code
  pickerLabel.textColor = defaultColor;

 if([self.pickerView selectedRowInComponent:component] == row) //this is the selected one, change its color
 {
        pickerLabel.textColor = [UIColor colorWithRed:0.0745 green:0.357 blue:1.0 alpha:1];
 } 
}
  • 1
    Thanks, @rodrigo-carrilho, however that would just change the text colour. What I really needed was the lines above and below the selected item. I've updated my question to give a little more guidance on my problem. – cjhill Nov 28 '14 at 08:06
1

You can change picker view selection line color using private headers of UIPickerView. Just set color for _magnifierLineColor key

pickerView.setValue(UIColor.red, forKey: "_magnifierLineColor")
0

This is how I did it in Swift 4.2

private let pickerSelectionIndicatorHeight: CGFloat = 62.0

    let pickerSelectionIndicatorTopLine = UIView()
    let pickerSelectionIndicatorBottomLine = UIView()

    pickerSelectionIndicatorTopLine.backgroundColor = UIColor.white
    pickerSelectionIndicatorBottomLine.backgroundColor = UIColor.white

    picker.addSubview(pickerSelectionIndicatorTopLine)
    picker.addSubview(pickerSelectionIndicatorBottomLine)

    pickerSelectionIndicatorTopLine.translatesAutoresizingMaskIntoConstraints = false
    pickerSelectionIndicatorTopLine.leadingAnchor.constraint(equalTo: picker.leadingAnchor, constant: 0).isActive = true
    pickerSelectionIndicatorTopLine.trailingAnchor.constraint(equalTo: picker.trailingAnchor, constant: 0).isActive = true
    pickerSelectionIndicatorTopLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
    pickerSelectionIndicatorTopLine.centerYAnchor.constraint(equalTo: picker.centerYAnchor, constant: -(pickerSelectionIndicatorHeight / 2 + 1.0)).isActive = true

    pickerSelectionIndicatorBottomLine.translatesAutoresizingMaskIntoConstraints = false
    pickerSelectionIndicatorBottomLine.leadingAnchor.constraint(equalTo: picker.leadingAnchor, constant: 0).isActive = true
    pickerSelectionIndicatorBottomLine.trailingAnchor.constraint(equalTo: picker.trailingAnchor, constant: 0).isActive = true
    pickerSelectionIndicatorBottomLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
    pickerSelectionIndicatorBottomLine.centerYAnchor.constraint(equalTo: picker.centerYAnchor, constant: (pickerSelectionIndicatorHeight / 2 + 1.0)).isActive = true

this code can of course be encapsulated in extension if needed.

zgorawski
  • 2,597
  • 4
  • 30
  • 43