【问题标题】:Customizing UIPickerView (background and spacing)自定义 UIPickerView(背景和间距)
【发布时间】:2011-04-21 13:49:19
【问题描述】:

我想将 UIPickerView 中的白色背景更改为我自己的图像。

这可能吗?

另外,我设法让我的 UIPickerView 水平滚动而不是垂直滚动。现在,我想知道是否有任何方法可以调整选择器视图两行之间的间距?

我附上了一张图片来说明我的意思。

这是我的代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    arrayDays = [[NSMutableArray alloc] init];
    [arrayDays addObject:@"ONSDAG"];
    [arrayDays addObject:@"TORSDAG"];
    [arrayDays addObject:@"FREDAG"];
    [arrayDays addObject:@"LØRDAG"];

    arrayDates = [[NSMutableArray alloc] init];
    [arrayDates addObject:@"29. JUNI"];
    [arrayDates addObject:@"30. JUNI"];
    [arrayDates addObject:@"1. JULI"];
    [arrayDates addObject:@"2. JULI"];

    pickerViewDay = [[UIPickerView alloc] initWithFrame:CGRectZero];
    [pickerViewDay setDelegate:self];
    [pickerViewDay setShowsSelectionIndicator:NO];
    CGAffineTransform rotate = CGAffineTransformMakeRotation(-M_PI/2);
    rotate = CGAffineTransformScale(rotate, 0.25, 2.0);
    [pickerViewDay setTransform:rotate];
    [pickerViewDay setCenter:CGPointMake(self.view.frame.size.width/2, (pickerViewDay.frame.size.height/2)-3)];
    [self.view addSubview:pickerViewDay];

    // Adding selection indicator to pickerview
    UIImage *selectorImage = [UIImage imageNamed:@"DayPickerView_SelectionIndicator.png"];
    UIView *customSelector = [[UIImageView alloc] initWithImage:selectorImage];
    [customSelector setFrame:CGRectMake(0, 0, 120, 74)];
    [customSelector setCenter:CGPointMake(self.view.frame.size.width/2, customSelector.frame.size.height/2)];
    [self.view addSubview:customSelector];
    [customSelector release];

    // Adding background to pickerview
    UIImage *backgroundImage = [UIImage imageNamed:@"DayPickerView_Background.png"];
    UIView *custombackground = [[UIImageView alloc] initWithImage:backgroundImage];
    [custombackground setFrame:CGRectMake(0, 0, 320, 74)];
    // [self.view addSubview:custombackground];
    [custombackground release];
}

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
    UIView *viewRow = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 80)];

    CGAffineTransform rotate = CGAffineTransformMakeRotation(3.14/2);
    rotate = CGAffineTransformScale(rotate, 0.25, 2.0);

    // Date
    CGRect rectDate = CGRectMake(30, 0, 150, 80);
    UILabel *date = [[UILabel alloc]initWithFrame:rectDate];
    [date setTransform:rotate];
    [date setText:[arrayDates objectAtIndex:row]];
    [date setFont:[UIFont fontWithName:@"Arial-BoldMT" size:37.0]];
    [date setShadowColor:[UIColor whiteColor]];
    [date setShadowOffset:CGSizeMake(0, -1)];
    [date setTextAlignment:UITextAlignmentCenter];
    [date setBackgroundColor:[UIColor clearColor]];
    [date setClipsToBounds:YES];
    [viewRow addSubview:date];

    // Day
    CGRect rectDay = CGRectMake(-30, 0, 150, 80);
    UILabel *day = [[UILabel alloc]initWithFrame:rectDay];
    [day setTransform:rotate];
    [day setText:[arrayDays objectAtIndex:row]];
    [day setFont:[UIFont fontWithName:@"Arial-BoldMT" size:21.0]];
    [day setTextColor:[UIColor colorWithRed:0.35 green:0.35 blue:0.35 alpha:1]];
    [day setTextAlignment:UITextAlignmentCenter];
    [day setBackgroundColor:[UIColor clearColor]];
    [day setClipsToBounds:YES];
    [viewRow addSubview:day];

    return viewRow;
}

- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    return [arrayDays objectAtIndex:row];
}

- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
    return [arrayDays count];
}

编辑 1

对于 RickiG(在背景上):

编辑 2

对于瑞奇:

【问题讨论】:

    标签: iphone sdk background uipickerview


    【解决方案1】:

    嗨 没有直接的方法来改变背景。您可以做的是让您在 viewForRow 中返回的视图具有自己的背景(如果需要,然后在每一侧添加阴影)。你也可以去寻找 viewWithTag: 但这绝不是一个好主意,因为这可能会在未来的 iOS 版本中改变。

    您同时实现 viewForRow 和 TitleForRow 是否有特殊原因?我通常只是在这个委托方法中填充 viewForRow 的标签。

    viewForRow 能够重用 Picker 中的视图,就像 UITableView 一样,您应该测试“reusingView:(UIView *)view”是否为 nil,如果不是,则无需再次绘制所有内容。只需填充标签。

    我通常从不自定义选择器,如果我需要一些不完全自定义的东西,我将 UITableView 子类化,它更加灵活,并且可以实现 Picker 的功能以及更多功能。

    对于间距,您可以使用行的“高度”,选择器会将您在 viewForRow 中返回的视图居中,然后确保:

    - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
    

    返回一个比您的视图更大的值。

    举行 og lykke;)

    【讨论】:

    • 非常感谢您提供有关间距的提示。那很完美!我似乎无法按照您提到的方式设置背景,因为背景的视图之间会有差距。我相信这是由于间距。而且背景看起来很奇怪(它有两个“阴影”,应该只有一个在顶部)查看我的第一篇文章。
    • 好吧,如果您的背景图片不适合组件的大小,则会出现间隙。您可以使背景与组件大小相同,也可以使用 stretchableImage 使 UIImage 适合组件。
    • 你是对的。我玩了标签的宽度,视图和图像而不是视图的背景都很好。不过,我在选择器视图的每一侧都有一个间隙。你知道有没有办法在那里设置背景?对于阴影效果,我可以将图像放在pickerview 的顶部。那将是完美的,但我仍然需要背景本身。查看我的第一篇文章中的图片。
    • 这就是我推荐 UITableView 的原因,pickerView 是定制的噩梦。我想你必须在每一端都用一个空组件填充你的数据,然后检查是否选择了该组件,如果选择了最后一个组件,是否选择了 [pickerView selectRow:row-1 inComponent:0 animated:YES]和 selectedRow:row+1 用于第一个组件。如果用户选择第一个或最后一个组件(填充),则选择器将弹回或弹回一个有效组件。挖掘背景的替代方案是危险的,并且对 iOS 变化很敏感,这种情况经常发生。
    【解决方案2】:

    我刚刚弄清楚如何在选择器视图中应用背景颜色或图像。希望它可以帮助某人。

    只需在您希望选择器视图的文件中定义一个类别,如下所示:

    @implementation UIPickerView(Extension)
    
    -(void)drawRect:(CGRect)rect
    {
    
        NSArray* subviews = [self subviews];
        for(UIView* view in subviews)
        {
            if([view isKindOfClass:[UITableView class]])
            {
                view.backgroundColor = appColor;
            }
        }
        [super drawRect:rect];
    }
    
    @end
    

    您可以进一步查看subviews 以获得更多自定义。

    【讨论】:

      【解决方案3】:

      看起来这是一个旧线程,但在 iOS 7 中(可能更早,我不确定),UIPickerViews 有一个背景颜色属性,所以设置背景颜色很简单:

      [pickerView setBackgroundColor:[UIColor whiteColor]];

      借助 [UIColor colorWithPatternImage:],设置背景图像同样简单。 (请注意,如果图像小于 UIPickerView,图案将平铺。)

      [pickerView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"someBackgroundImage.png"]]];
      

      要修改组件宽度,您可以实现委托方法 widthForComponent 以便为每个组件设置各种宽度。理论上,您应该能够添加一个空组件并使用它的空白宽度来创建间距,但我还没有尝试过。

      - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
      

      我还没有找到一种方法来更改组件之间的填充,这似乎是修改间距的更好方法,并且还允许您删除组件之间的 ~5 px 间距,但如果我能够找到一个我会更新我的答案。

      【讨论】:

        【解决方案4】:

        在标签右侧添加一个空视图怎么样?对于背景,您可能应该使用insertSubview:aboveView: 方法,并将默认背景视图作为第二个参数(如果您可以访问它)。

        【讨论】:

        • 这似乎有点冒险。由于视图是堆叠的,直到对象被添加到 UIPickerView,子视图的数量为零。如果您有更确切的方法,请告诉我。我似乎无法正常工作。