The MAF provides simple skinnable controls, such as Button, Label, Table View; and more complex controls, such as Tree View or Calendar Control. If you build your own complex control from the simple skinnable MAF controls, you can fully skin your control using the MAF skinning engine. To do so, your component logic must apply the runtime information from the MAF skinning engine.
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextMoveToPoint(context, 100, 100); CGContextAddLineToPoint(context, 150, 150); CGContextAddLineToPoint(context, 100, 200); CGContextAddLineToPoint(context, 50, 150); CGContextAddLineToPoint(context, 100, 100); CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); CGContextFillPath(context); }
This simple Quartz 2D code presents the following rectangle on your screen:
#import <UIKit/UIKit.h> #import "MAFStyling.h" @interface MyCustomControl : UIView <MAFStyling> @endThis is the public API provided by this protocol:
/** MAFStyling declares the methods and properties what a styleable control should support. */ @protocol MAFStyling /** The style name of the control defined in the styling xml. Default is nil which means to use the default style for the control. Setting this property automatically calls mafApplyStyle. */ @property (copy) NSString *mafStyleName; /** Applies the style on the control. Should be called if a new styling xml loaded in runtime. */ - (void) mafApplyStyle;
By implementing this protocol, you enable your own control to store the mafStyleName property. Use mafStyleName to set your custom skin’s key value when initializing an instance of your control. The other capability this protocol provides is the mafApplyStyle selector. MAF skinnable controls call this selector when a new instance is created from the control, thus applying the skin to itself.
#import "MyCustomControl.h" #import "MAFExtensions.h" #import <ObjC/runtime.h> #import "MAFUIStyleCatalog.h" @interface MyCustomControl() @property (strong) UIColor *rectFillColor; @end
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, self.rectBorderColor.CGColor); CGContextMoveToPoint(context, 100, 100); CGContextAddLineToPoint(context, 150, 150); CGContextAddLineToPoint(context, 100, 200); CGContextAddLineToPoint(context, 50, 150); CGContextAddLineToPoint(context, 100, 100); CGContextSetFillColorWithColor(context, self.rectFillColor.CGColor); CGContextFillPath(context); } To set the color value, define it in the styling XML: <Style Key="CustomControlBlueStyle" TargetType="Control" platform="ios"> <Setter Property="Background" Value="#000000"/> </Style>
The next step is to read out the style from the MAFStyleCatalog. You can do this by implementing the mafApplyStyle method of the MAFStylingProtocol.
- (void) mafApplyStyle{ MAFUIStyleCatalog* catalog = [MAFUIStyleCatalog uiStyleCatalog]; MAFUIStyle *customStyle = [catalog styleByName: self.mafStyleName]; self.rectFillColor = customStyle.getBorderColor; }To set and get the value of the mafStyleName, implement the following getter and setter:
#pragma mark - MAFStyling implementation - (NSString *)mafStyleName { //return [super mafStyleName]; return objc_getAssociatedObject(self, mafStyleNameKey); } - (void)setMafStyleName:(NSString *)mafStyleName{ //[super setMAFStyleName:mafStyleName]; objc_setAssociatedObject(self, mafStyleNameKey, mafStyleName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [self mafApplyStyle]; [self setNeedsDisplay]; }
The above code creates a public getter and setter method. The getter method returns the current value, and the setter method calls the mafApplyStyle method to change the internal value of the rectFillColor property, then notifies the system to redraw the view.
MyCustomControl *myControl = [[MyCustomControl alloc] initWithFrame:CGRectMake(0, 0, 320, 300)]; myControl.mafStyleName = @"CustomControlBlueStyle"; [self.view addSubview:myControl]; [myControl release];