我們在做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
