开发者

How to change color of selected row in UIPickerView

Ok, maybe I'm missing something really simple and I apologize if that's the case, however, I've googled every permutation of the title and have not found! So this is simply what I want to do: change the background color of the label I'm using as the row view in a 2 component pickerview when that row has been selected. So I thought this would work:

if (row == [pickerview selectedRowForComponent])
    viewlabel.backgroundColor = redcolor;

but this doesn't work. It seems to arbitrarily choose which row to color and sometimes even give a bad access error. I've tried all different clauses to no effect! ANy suggestions would be greatly appreciated!!

Here's the full method:

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

    if (component == kNumberComponent) {


#define PICKER_LABEL_FONT_SIZE 24
#define PICKER_LABEL_ALPHA 1.0
        // UIFont *font = [UIFont boldSystemFontOfSize:PICKER_LABEL_FONT_SIZE];
        UIFont *font = [ UIFont fontWithName:@"AppleGothic"  size:24];
        UILabel *carsLabel =[ [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 75, 50) ]autorelease];
        //[picker selectRow:row inComponent:component animated:YES];
        NSStri开发者_运维百科ng *pickerText = [self.numbers objectAtIndex:(int)row];
        carsLabel.text = pickerText;
        carsLabel.textAlignment = UITextAlignmentCenter;
        NSLog(@"carsLabel = %@",carsLabel.text);
        //carsLabel.text = @"maybe because the string isn't long enough";
        carsLabel.textColor = [UIColor blackColor];
        carsLabel.font = font;





        carsLabel.opaque = YES;


        [view addSubview:carsLabel];

        return carsLabel;   
    } else {
        UIFont *font = [ UIFont fontWithName:@"AppleGothic"  size:18];

        UILabel *carsLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 225, 50)] autorelease];
        id fact = [self.facts objectAtIndex:(int)row];
        NSString *pickerText = @"Dictionary Entry";
        if ( [fact isKindOfClass:[NSString class]]) {


            pickerText = [self.facts objectAtIndex:(int)row];

        } 
        carsLabel.text = pickerText;
        carsLabel.textAlignment = UITextAlignmentCenter;
        NSLog(@"carsLabel = %@",carsLabel.text);
        //carsLabel.text = @"maybe because the string isn't long enough";
        carsLabel.textColor = [UIColor blackColor];
        carsLabel.font = font;
        if ( row == 0) {
        carsLabel.backgroundColor = [UIColor redColor];

        }
        //carsLabel.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blackboard.png"]];;
        carsLabel.opaque = YES;

        [view addSubview:carsLabel];

        return carsLabel;
    }


    return nil;
}


Normally, I use this method:

I use the custom view for show the row item

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

    UILabel *label = (id)view;

    if (!label)
    {

        label= [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [pickerView rowSizeForComponent:component].width, [pickerView rowSizeForComponent:component].height)];
        label.textAlignment = NSTextAlignmentCenter;
        label.textColor = [UIColor whiteColor];
        label.text = _arrayStringPicker[row];

    }  

    return label;

I change color of row selected with:

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

    UILabel *labelSelected = (UILabel*)[pickerView viewForRow:row forComponent:component];
    [labelSelected setTextColor:[UIColor redColor]];

}


Swift implementation

extension PickerViewController: UIPickerViewDelegate {
    func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
        var color: UIColor!
        if pickerView.selectedRowInComponent(component) == row {
            color = UIColor.redColor()
        } else {
            color = UIColor.blackColor()
        }

        let attributes: [String: AnyObject] = [
            NSForegroundColorAttributeName: color,
            NSFontAttributeName: UIFont.systemFontOfSize(15)
        ]

        return NSAttributedString(string: rows[row], attributes: attributes)
    }

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        //this will trigger attributedTitleForRow-method to be called
        pickerView.reloadAllComponents()
    }
}


The correct format for viewForPicker is:

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    UILabel *label = (UILabel*) view;
    if (label == nil)
    {
        label = [[UILabel alloc] init];
    }

    [label setText:@"Whatever"];

    // This part just colorizes everything, since you asked about that.

    [label setTextColor:[UIColor whiteColor]];
    [label setBackgroundColor:[UIColor blackColor]];
    CGSize rowSize = [pickerView rowSizeForComponent:component];
    CGRect labelRect = CGRectMake (0, 0, rowSize.width, rowSize.height);
    [label setFrame:labelRect];

    return label;
}

The problem with the code above is: it colorizes the labels, but not the picker, itself. So, when you roll to one end or the other, there's a blank spot where you can see the white background. Setting [myPicker setBackgroundColor...] doesn't do what one might hope.


// CGRectMake values for the frame we’d like

UIPickerView *myPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height)];

// add the UIPickerView to your viewcontroller [mainView addSubview:myPickerView];

// set the selectionindicator to none myPickerView.showsSelectionIndicator = NO;

// define the image that we would like to use

UIImage *selectorImage = [UIImage imageNamed:@"selectionIndicator.png"];

UIView *customSelector = [[UIImageView alloc] initWithImage:selectorImage];

// set the x and y values to the point on the UIPickerView where you want to place the image

// set the width and height values to the width and height of your image

customSelector.frame = CGRectMake(10,(myPickerView.bounds.size.height / 2) + 16, self.view.bounds.size.width – 10, 47);

// add the custom selectionIndicator also to the same viewcontroller

[mainView addSubview:customSelector];


Solved! Declare 2 instance variables: selectedView, and oldView. Then the following code does the trick:

if (self.oldView != nil)
        self.oldView.backgroundColor = [UIColor clearColor];

self.selectedView = [picker viewForRow:row forComponent:kNumberComponent];
        self.selectedView.backgroundColor = [UIColor redColor];
        [self.selectedView setNeedsDisplay];
        self.oldView = self.selectedView;


Call the UIPickerView instance's -viewForRow:forComponent: method to get the UIView * object. Then set that view's background UIColor.


Swift version of @alessandro-pirovano answer

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

    let rowSize = pickerView.rowSize(forComponent: component)
    let width = rowSize.width
    let height = rowSize.height
    let frame = CGRect(x: 0, y: 0, width: width, height: height)
    let label = UILabel(frame: frame)
    label.textAlignment = .center
    label.text = rows[row]

    return label
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    guard let label = pickerView.view(forRow: row, forComponent: component) as? UILabel else {
        return
    }
    label.backgroundColor = .orange
}


It's unclear where you are putting the above code. Is it in -pickerView:viewForRow:forComponent:reusingView:? This is where it should be. Are you sure that you are maintaining a pointer to the label for that particular view? The fact that you are crashing suggests you probably are not. A larger block of code, including where you have put it, would be helpful.


Here's what worked for me:

  1. Add a UIView as a subview to your UIPickerView
  2. Constrain it to be Y entered with your UIPickerView and the has the same width
  3. Give it height equal to the height of what returned in pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
  4. Make it semi transparent and color it the way you want

*the rest of the solutions (with custom views for row or attributed stringsfor row) were buggy when scrolling fast.


UIPickerView has delegate to set NSAttributeString for title at row and component we can set attribute color like below:

- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
    NSDictionary *attrs = @{NSForegroundColorAttributeName : [UIColor redColor]};
    NSString *title = @"title"
    return [[NSAttributedString alloc] initWithString:title attributes:attrs];

}


Expanding on Alessandro Pirovano's answer;

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

    UILabel *labelSelected = (UILabel*)[pickerView viewForRow:row forComponent:component];
    [labelSelected setTextColor:[UIColor redColor]];
    labelSelected.superview.backgroundColor = [UIColor yellowColor];
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜