我們在做iOS應用時會有這么個需求:想對一個UIView視圖做部分裁減,使得被裁減部分顯示其子視圖部分,即其底圖。
我們一般可以通過讓美術人員做一個相同尺寸的圖,將裁減部分做成透明即可。另一種可以通過程序來做。下面我將介紹如何通過Cocoa Framework中的QuartzCore Framework來實現這個效果。
基本思路是,我們先通過Quartz2D畫一個視圖,先用alpha為1的像素填充所指定的矩形,然后用alpha為0的像素畫一個裁減圖形。最后,將繪制好的這個UIView對象的layer作為被裁減的視圖的layer的mask。
先看Quartz2D部分,這部分代碼定制了一個UIView類:
// // MyQuartzView.m // QuartzTest // // Created by zenny_chen on 12-2-21. // Copyright (c) 2012年 GreenGames Studio. All rights reserved. // #import "MyQuartzView.h" // Quartz2D以及Core Animation所需要的頭文件 #import <QuartzCore/QuartzCore.h> #import <CoreText/CoreText.h> @implementation MyQuartzView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code // 創建Quartz上下文 CGContextRef context = UIGraphicsGetCurrentContext(); // 先填充一個alpha只為1的白色矩形 CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); CGContextFillRect(context, CGRectMake(0.0f, 0.0f, self.frame.size.width, self.frame.size.height)); // 對於iOS坐標系,調整一下坐標系的表示,使得原點處於左下側 // 這樣與我們平時在數學中用的坐標系可取得一致 CGContextTranslateCTM(context, 0.0f, self.frame.size.height); CGContextScaleCTM(context, 1.0f, -1.0f); // 創建一個三角Path CGMutablePathRef path = CGPathCreateMutable(); // 調用CGPathMoveToPoint來開啟一個子Path CGPathMoveToPoint(path, &CGAffineTransformIdentity, 0.0f, self.frame.size.height); CGPathAddLineToPoint(path, &CGAffineTransformIdentity, 0.0f, 0.0f); CGPathAddLineToPoint(path, &CGAffineTransformIdentity, self.frame.size.width * 0.125f, 0.0f); CGPathAddLineToPoint(path, &CGAffineTransformIdentity, 0.0f, self.frame.size.height); CGPathCloseSubpath(path); // 設置Path的混合模式: // kCGBlendModeDestinationIn表示:如果alpha為0,那么采用目標像素 CGContextSetBlendMode(context, kCGBlendModeDestinationIn); // 這里主要設置該path的alpha值為0 CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f); // 添加Path並繪制該Path CGContextAddPath(context, path); CGContextFillPath(context); CGPathRelease(path); } @end
然后,我們再看看主控制器里面的代碼:
// // ViewController.m // QuartzTest // // Created by zenny_chen on 12-2-21. // Copyright (c) 2012年 GreenGames Studio. All rights reserved. // #import "ViewController.h" #import "MyQuartzView.h" #import <QuartzCore/QuartzCore.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 設置主視圖的背景色 self.view.backgroundColor = [UIColor colorWithRed:0.2f green:0.2f blue:0.2f alpha:1.0f]; // 創建一個紅色背景的矩形圖 UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 100.0f, 160.0f, 160.0f)]; aView.backgroundColor = [UIColor redColor]; [self.view addSubview:aView]; [aView release]; // 創建掩模視圖,其尺寸與所要裁減的視圖的尺寸一樣 MyQuartzView *myView = [[MyQuartzView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 160.0f, 160.0f)]; // 這里要注意的是,必須將掩模視圖的背景色的alpha值填充為0 myView.backgroundColor = [UIColor clearColor]; // 將掩模視圖的layer作為被裁減視圖的layer的mask aView.layer.mask = myView.layer; // 注意,這里的myView不能調release方法, // 因為aView.layer.mask = myView.layer這句並沒有將myView給retain住。 } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end