IOS4 note 16 (5) Drawing a UIView

Drawing a UIView

 

The most flexible way to draw a UIView is to draw it yourself. Actually, you don’t draw a UIView; you subclass UIView and endow the subclass with the ability to draw itself.When a UIView needs drawing, its drawRect: method is called. Overriding that method is your chance to draw. At the time that drawRect: is called, the current graphics context has already been set to the view. You can use Core Graphics functions or UIKit convenience methods to draw into that context.

 

You should never call drawRect: yourself. If a view needs updating and you want its drawRect: called,  send  the view  the setNeedsDisplay message. This will cause drawRect: to be called at the next proper moment.

 

If you subclass a built-in UIView subclass, don’t override drawRect: unless  you  are  assured  that  this  is  legal. For example, it is not legal to override drawRect: in a subclass of UIImageView; you cannot combine your drawing with that of the UIImageView.

 

We’ll have a UIView subclass called MyView, in which we’ll do all our drawing. How this class gets instantiated, and how the instance gets into our view hierarchy, isn’t important. Here, I’ll do it in code as the app launches:

MyView* mv = [[MyView alloc] initWithFrame:CGRectMake(0, 0, self.window.bounds.size.width - 50, 150)];

 

 

mv.center = self.window.center;

[self.window addSubview: mv];

mv.opaque = NO;

[mv release];

 

The drawing action all takes place in MyView’s drawRect: method. At the time drawRect: is called, we are guaranteed that the current Core Graphics context is MyView itself, so we can obtain this if we need to with UIGraphicsGetCurrentContext, and then we can do here whatever we did in our earlier examples of drawing in a context. For example, we can draw two halves of Mars, one at each end of the view:

 

 

 

- (void)drawRect:(CGRect)rect {

    CGRect b = self.bounds;

    UIImage* mars = [UIImage imageNamed:@"Mars.png"];

    CGSize sz = [mars size];

    CGImageRef marsCG = [mars CGImage];

    CGSize szCG = CGSizeMake(CGImageGetWidth(marsCG), CGImageGetHeight(marsCG));

    CGImageRef marsLeft = CGImageCreateWithImageInRect(marsCG,

                           CGRectMake(0,0,szCG.width/2.0,szCG.height));

    CGImageRef marsRight = CGImageCreateWithImageInRect(marsCG,

                            CGRectMake(szCG.width/2.0,0,szCG.width/2.0,szCG.height));

    CGContextRef con = UIGraphicsGetCurrentContext();

    CGContextDrawImage(con, CGRectMake(0,0,sz.width/2.0,sz.height), flip(marsLeft));

    CGContextDrawImage(con, CGRectMake(b.size.width-sz.width/2.0, 0, sz.width/2.0,

sz.height), flip(marsRight));

    CGImageRelease(marsLeft); CGImageRelease(marsRight);

}

 

There  is no need  to call super, because  the  superclass here  is UIView, whose drawRect: does nothing.

The need to draw in real time, on demand, surprises some beginners, who worry that drawing may be a time-consuming operation. Equally surprising is the need to draw repeatedly; even if the drawing has not changed, you may be called upon to perform the same drawing again. Where drawing is extensive and can be compartmentalized into sections, you may be able to gain some efficiency by paying attention to the rect parameter passed  into drawRect:.  It designates  the  region of  the view’s bounds  that needs refreshing. The system knows this either because this  is the area that has just been exposed by the removal of some covering view or because you called setNeedsDisplayInRect:, specifying it. Thus, you could call setNeedsDisplayInRect: to tell your

drawRect: to redraw a subregion of the view; the rest of the view will be left alone.

In general, however, you should not optimize prematurely. What looks like a lengthy drawing operation may be extremely fast. And the iOS drawing system is efficient; it doesn’t  call  drawRect: unless it has to (or is told to, through a call to setNeedsDisplay), and once a view has drawn itself, the result is cached so that the cached drawing can be reused instead of repeating the drawing operation from scratch.

 

Making a View’s Background Transparent

If a view’s backgroundColor is nil (the default when creating a UIView in code) and its opaque is YES (ditto), it will be drawn with a black background; therefore, to make such a view’s background transparent, you must set its opaque to NO. This problem doesn’t arise with a view instantiated from a nib, because you can’t assign a view a nil backgroundColor in the nib; it always has some background color, even if it is what the nib calls Clear Color ([UIColor clearColor], or transparent black). Thus, assigning [UIColor clearColor] as a code-created view’s backgroundColor has the same apparent

effect, and you may encounter code that does this. But Apple warns that you should still set a transparent view’s opaque to NO, or incorrect drawing may occur.

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值