Thursday, September 16, 2010

Colored RGB sliders, without a XIB

The next step of my refactoring was to modify the Colored View sliders so that they are independent of a .xib file so that I can place them into any view.  This gives me a lot of flexibility and reduces some of the dependance of a xib in a dependent library.  
In addition I found that when I programmatically created the sliders I could change the height and make it look somewhat nicer.

I revised the creation code so that it creates 4 sliders programmatically spaced within a passed in view.  It sets up callbacks in the current routine.

When a color changes it calls a delegate with the changes.

- (void) loadView : (UIView *)viewToUse
    NSLog(@"In loadView for ColorEditor");
    // Don't use a nib.
    int labelWidth=74;
    int labelHeight=21;
    viewToUse.backgroundColor=[UIColor cyanColor];
    if (currentColorSpace==nil)
        currentColorSpace = CGColorSpaceCreateDeviceRGB();
    NSArray *sliderLabels=      [NSArray arrayWithObjects:NSLocalizedString(@"Red", @"Red"), NSLocalizedString(@"Green", @"Green"), NSLocalizedString(@"Blue", @"Blue"),NSLocalizedString(@"Transparency","Transparency"), nil];
    NSLog(@"view height %f, width %f x %f, y %f",viewToUse.frame.size.height,viewToUse.frame.size.width,viewToUse.frame.origin.x,viewToUse.frame.origin.y);
    int sliderHeight=(viewToUse.frame.size.height)/4-spacing;
    NSLog(@"SliderHeight %d",sliderHeight);
    for (int i=0;i<4;i++)
        CGRect labelFrame=CGRectMake(0, (sliderHeight+spacing)*i+sliderHeight/2-labelHeight/2, labelWidth, labelHeight);
        UILabel *label=[[UILabel alloc] initWithFrame:labelFrame];
        label.text=[sliderLabels objectAtIndex:i];
        [viewToUse addSubview:label];
        CGRect areaFrame=CGRectMake(leftMargin+labelWidth, (sliderHeight+spacing)*i,viewToUse.bounds.size.width-leftMargin-rightMargin-labelWidth, sliderHeight);
        sliders[i]=[[UISlider alloc]init];
        [sliders[i] addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
        sliders[i].accessibilityLabel=[sliderLabels objectAtIndex:i];
        NSLog(@"Y is %d",(sliderHeight+spacing)*i);
        [viewToUse addSubview:sliders[i]];
    [self calcColors];

and the calc colors is:
- (void) calcColors
    for (int index=0;index<4;index++)
        [self setSlider:sliders[index] colorIndex:index];
    currentColor=[UIColor colorWithRed:colors[0] green:colors[1] blue:colors[2] alpha:colors[3]];

    for (int index=0;index<4;index++)
        // numeric fields are not implemented.      
        //     textFields[index].text=[NSString stringWithFormat:@"%d",(int)  (colors[index]*255)];
    if (delegate!=nil)
        [delegate colorChanged:currentColor];
This looks like:

Note that the sliders (the area in blue) is the only thing the code does.  The rest is a custom frame done in a .nib.  This enables me to embed the sliders in a view:

The .nib in interface builder looks like this:

Note that I have an image view under a label.  This allows me to change the label and show what it looks like under the label.

The yellow area is my current color for the slider view.  I set it to a unique color so that I can watch what is going on.

I'm allowing the font and background color to be set using the tab bar.  This is not standard behavior for a tab bar, but it is allowable in a modal dialog.   I have a 3rd tab that will eventually be used for a font choice.

The code for this is:
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];    
    colorEditor=[[ColorEditor alloc]init];
    self.view.backgroundColor=[UIColor colorWithRed:0 green:0 blue:0 alpha:0];

- (void) initColors:(UIColor*) fColor background:(UIColor*) back text:(NSString*) textValue image:(UIImage*)background {
    [colorEditor loadView:actionView];
    [colorEditor setCurrentColor:label.textColor];

- (void) colorChanged:(UIColor*) newColor
    if (isFont)
    // Tell our delegate that we have our font colors changed.
    [delegate styleChanged:label.textColor background:label.backgroundColor];


- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item // called when a new view is selected by the user (but not programatically)
    if (item==fontColor)
        [colorEditor setCurrentColor:label.textColor];
             [colorEditor setCurrentColor:label.backgroundColor];
    if (label !=nil)


I can now change the color editor and use it to set both the background and foreground color of a font.

And the header for this defines another protocol that allows the foreground and background color to be set.

@protocol StyleChanged

- (void) styleChanged:(UIColor*) fontColor background:(UIColor*) backColor;

@interface ColorEdit : UIViewController<UITabBarDelegate,ColorListener> {
    IBOutlet UILabel *label;
    IBOutlet UIView  *actionView;
    IBOutlet UIImageView *backImage;
    ColorEditor *colorEditor;
    IBOutlet UITabBarItem *fontColor;
    IBOutlet UITabBarItem *backColor;
    bool isFont;
    id<StyleChanged> delegate;
@property (nonatomic,retain) IBOutlet UIImageView *backImage;
@property (nonatomic,retain) IBOutlet UILabel *label;
@property (nonatomic,retain) IBOutlet UIView *actionView;
@property (nonatomic,retain) ColorEditor *colorEditor;
@property (nonatomic,retain) IBOutlet UITabBarItem *fontColor;
@property (nonatomic,retainIBOutlet UITabBarItem *backColor;
@property (nonatomic,retain) id delegate;
- (void) initColors : (UIColor*) fontColor background:(UIColor*) back text:(NSString*) textValue image:(UIImage*)background ;

No comments:

Post a Comment