自定义UIPickerView,带有三个组件,每个组件在选择指示器上显示标签

时间:2013-05-24 12:05:50

标签: iphone ios object uipickerview uipicker

在我的应用中,我正在尝试制作一个包含三个组件(天,小时和分钟)的自定义UIPickerView。我已经使用三个组件制作了自定义选取器。现在我被困在如何将标签添加到选择指示器中,该指示器显示哪些组件是天,小时或分钟。

我已经浏览过本网站上发布的每一个链接或问题,但没有人帮助过我。

我正在尝试实现类似这样的图像

Real timer

任何人都可以建议我如何实现这一目标?

2 个答案:

答案 0 :(得分:4)

多数民众赞成我如何实现这一目标....我已经在我发现的一些代码的帮助下制作了我的自定义PickerView ......

在.h文件中:

//  LabeledPickerView.h
//  LabeledPickerView

#import <UIKit/UIKit.h>

@interface LabeledPickerView : UIPickerView

{
    NSMutableDictionary *labels;
}

/** Adds the label for the given component. */
-(void)addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString;
@end

并在.m文件中...

//  LabeledPickerView.m
//  LabeledPickerView

#import "LabeledPickerView.h"

@implementation LabeledPickerView

/** loading programmatically */
- (id)initWithFrame:(CGRect)aRect {
    if (self = [super initWithFrame:aRect]) {
        labels = [[NSMutableDictionary alloc] initWithCapacity:3];
    }
    return self;
}

/** loading from nib */
- (id)initWithCoder:(NSCoder *)coder {
    if (self = [super initWithCoder:coder]) {
        labels = [[NSMutableDictionary alloc] initWithCapacity:3];
    }
    return self;
}

- (void) dealloc
{
    [labels release];
    [super dealloc];
}

#pragma mark Labels

// Add labelText to our array but also add what will be the longest label we will use in updateLabel
// If you do not plan to update label then the longestString should be the same as the labelText
// This way we can initially size our label to the longest width and we get the same effect Apple uses

-(void)addLabel:(NSString *)labeltext forComponent:(NSUInteger)component forLongestString:(NSString *)longestString {
    [labels setObject:labeltext forKey:[NSNumber numberWithInt:component]];

    NSString *keyName = [NSString stringWithFormat:@"%@_%@", @"longestString", [NSNumber numberWithInt:component]];

    if(!longestString) {
        longestString = labeltext;
    }

    [labels setObject:longestString forKey:keyName];
}

//
- (void) updateLabel:(NSString *)labeltext forComponent:(NSUInteger)component {

    UILabel *theLabel = (UILabel*)[self viewWithTag:component + 1];

    // Update label if it doesn’t match current label
    if (![theLabel.text isEqualToString:labeltext]) {

        NSString *keyName = [NSString stringWithFormat:@"%@_%@", @"longestString", [NSNumber numberWithInt:component]];
        NSString *longestString = [labels objectForKey:keyName];

        // Update label array with our new string value
        [self addLabel:labeltext forComponent:component forLongestString:longestString];

        // change label during fade out/in
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.75];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        theLabel.alpha = 0.00;
        theLabel.text = labeltext;
        theLabel.alpha = 1.00;
        [UIView commitAnimations];
    }

}

/**
 Adds the labels to the view, below the selection indicator glass-thingy.
 The labels are aligned to the right side of the wheel.
 The delegate is responsible for providing enough width for both the value and the label.
 */
- (void)didMoveToWindow {
    // exit if view is removed from the window or there are no labels.
    if (!self.window || [labels count] == 0)
        return;

    UIFont *labelfont = [UIFont boldSystemFontOfSize:15];

    // find the width of all the wheels combined
    CGFloat widthofwheels = 0;
    for (int i=0; i<self.numberOfComponents; i++) {
        widthofwheels += [self rowSizeForComponent:i].width;
    }

    // find the left side of the first wheel.
    // seems like a misnomer, but that will soon be corrected.
    CGFloat rightsideofwheel = (self.frame.size.width - widthofwheels) / 2;

    // cycle through all wheels
    for (int component=0; component<self.numberOfComponents; component++) {
        // find the right side of the wheel
        rightsideofwheel += [self rowSizeForComponent:component].width;

        // get the text for the label.
        // move on to the next if there is no label for this wheel.
        NSString *text = [labels objectForKey:[NSNumber numberWithInt:component]];
        if (text) {

            // set up the frame for the label using our longestString length
            NSString *keyName = [NSString stringWithFormat:@"%@_%@", [NSString stringWithString:@"longestString"], [NSNumber numberWithInt:component]];
            NSString *longestString = [labels objectForKey:keyName];
            CGRect frame;
            frame.size = [longestString sizeWithFont:labelfont];

            // center it vertically
            frame.origin.y = (self.frame.size.height / 2) - (frame.size.height / 2) - 0.5;

            // align it to the right side of the wheel, with a margin.
            // use a smaller margin for the rightmost wheel.
            frame.origin.x = rightsideofwheel - frame.size.width -
            (component == self.numberOfComponents - 1 ? 5 : 7);

            // set up the label. If label already exists, just get a reference to it
            BOOL addlabelView = NO;
            UILabel *label = (UILabel*)[self viewWithTag:component + 1];
            if(!label) {
                label = [[[UILabel alloc] initWithFrame:frame] autorelease];
                addlabelView = YES;
            }

            label.text = text;
            label.font = labelfont;
            label.backgroundColor = [UIColor clearColor];
            label.shadowColor = [UIColor whiteColor];
            label.shadowOffset = CGSizeMake(0,1);

            // Tag cannot be 0 so just increment component number to esnure we get a positive
            // NB update/remove Label methods are aware of this incrementation!
            label.tag = component + 1;

            if(addlabelView) {
                /*
                 and now for the tricky bit: adding the label to the view.
                 kind of a hack to be honest, might stop working if Apple decides to
                 change the inner workings of the UIPickerView.
                 */
                if (self.showsSelectionIndicator) {
                    // if this is the last wheel, add label as the third view from the top
                    if (component==self.numberOfComponents-1)
                        [self insertSubview:label atIndex:[self.subviews count]-3];
                    // otherwise add label as the 5th, 10th, 15th etc view from the top
                    else
                        [self insertSubview:label aboveSubview:[self.subviews objectAtIndex:5*(component+1)]];
                } else
                    // there is no selection indicator, so just add it to the top
                    [self addSubview:label];

            }

            if ([self.delegate respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)])
                [self.delegate pickerView:self didSelectRow:[self selectedRowInComponent:component] inComponent:component];
        }

    }

}

并使用标签文本和组件标记调用此addLabel:方法,就是这样.. !!

答案 1 :(得分:-3)

下载自定义UIPickerView Control的源代码。

Custom UiPickerView.

希望它有助于你:)