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.
self.leftMargin=10;
self.rightMargin=10;
self.spacing=5;
self.fontSize=10;
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.adjustsFontSizeToFitWidth=true;
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].tag=i;
sliders[i].accessibilityLabel=[sliderLabels objectAtIndex:i];
NSLog(@"Y is %d",(sliderHeight+spacing)*i);
sliders[i].frame=areaFrame;
[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];
isFont=true;
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.delegate=self;
label.textColor=fColor;
label.backgroundColor=back;
label.text=textValue;
[colorEditor setCurrentColor:label.textColor];
backImage.contentMode=UIViewContentModeScaleAspectFit;
backImage.image=background;
}
- (void) colorChanged:(UIColor*) newColor
{
if (isFont)
label.textColor=newColor;
else
label.backgroundColor=newColor;
// 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)
{
isFont=true;
[colorEditor setCurrentColor:label.textColor];
}
else
{
isFont=false;
[colorEditor setCurrentColor:label.backgroundColor];
}
if (label !=nil)
{
label.text=item.title;
}
}
@end
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;
@end
@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,retain) IBOutlet UITabBarItem *backColor;
@property (nonatomic,retain) id delegate;
- (void) initColors : (UIColor*) fontColor background:(UIColor*) back text:(NSString*) textValue image:(UIImage*)background ;