본문 바로가기
프로그래밍/iOS

Skinning a UIProgressView with drawRect and images

by 백룡화검 2012. 4. 25.

Here is an easy way that I’ve come up with to skin the default UIProgressView in an iOS application using just 2 images, and implementing the drawRect: method.

This is what the default progress view looks like:

…and here is our custom skinned version.

To achieve this you will need 2 images: one for the background, and one for the fill. The images that I’ve shown here were designed by Darran Morris so please give credit if you use them.

Update: You can download the images I’ve used here: progress-bar-bg.png, progress-bar-fill.png

Once you have your images created like mine above, create a new Objective-C class. In your header file make it a subclass of UIProgressView.

// CustomProgressView.h

#import <UIKit/UIKit.h>

@interface CustomProgressView : UIProgressView {

}

@end

Next in your implementation file we will create and use our images to draw the progress bar. Note that the images have to be “stretchable” in order to work correctly and to be able to render at different widths and heights.

// CustomProgressView.m

#import "CustomProgressView.h"

#define kCustomProgressViewFillOffsetX 1
#define kCustomProgressViewFillOffsetTopY 1
#define kCustomProgressViewFillOffsetBottomY 3

@implementation CustomProgressView

- (void)drawRect:(CGRect)rect {

    CGSize backgroundStretchPoints = {4, 9}, fillStretchPoints = {3, 8};
   
    // Initialize the stretchable images.
    UIImage *background = [[UIImage imageNamed:@"progress-bar-bg.png"] stretchableImageWithLeftCapWidth:backgroundStretchPoints.width
                                                                                           topCapHeight:backgroundStretchPoints.height];
   
    UIImage *fill = [[UIImage imageNamed:@"progress-bar-fill.png"] stretchableImageWithLeftCapWidth:fillStretchPoints.width
                                                                                       topCapHeight:fillStretchPoints.height]
   
    // Draw the background in the current rect
    [background drawInRect:rect];

    // Compute the max width in pixels for the fill.  Max width being how
    // wide the fill should be at 100% progress.
    NSInteger maxWidth = rect.size.width - (2 * kCustomProgressViewFillOffsetX);

    // Compute the width for the current progress value, 0.0 - 1.0 corresponding
    // to 0% and 100% respectively.
    NSInteger curWidth = floor([self progress] * maxWidth);
   
    // Create the rectangle for our fill image accounting for the position offsets,
    // 1 in the X direction and 1, 3 on the top and bottom for the Y.
    CGRect fillRect = CGRectMake(rect.origin.x + kCustomProgressViewFillOffsetX,
                                 rect.origin.y + kCustomProgressViewFillOffsetTopY,
                                 curWidth,
                                 rect.size.height - kCustomProgressViewFillOffsetBottomY);
   
    // Draw the fill
    [fill drawInRect:fillRect];
}

@end

That’s it! Now you can use this progress view like you would any other UIView by calling initWithFrame: and passing a CGRect – and since the images are stretchable you can make it any size you want.


출처 : http://goto11.net/skinning-a-uiprogressview-with-drawrect-and-images/