有了view的子類,只要重載一個方法drawRect
-(void)drawRect:(CGRect)aRect;
它的參數(shù)是個矩形,這個矩形就是你要重繪的區(qū)域,你可以忽略參數(shù),它只是為了性能優(yōu)化,只在固定的區(qū)域繪圖.
注意!!!
永遠不要去調(diào)用drawRect,因為drawRect不是讓你調(diào)用的,而是系統(tǒng)會去調(diào)用的.
那怎么去告訴系統(tǒng)需要重繪呢?
你發(fā)送兩個消息,setNeedsDisplay和setNeedsDisplayInRect.
-(void)setNeedsDisplay;
-(void)setNeedsDisplayInRect:(CGRect)aRect;
你們可以認為初始化的時候的設(shè)置是一個點,然后晚些系統(tǒng)查看所有需要重繪的東西,
然后把它們按順序排列,因為有些東西可能會重疊,然后再非常高效的把需要的東西繪制出來.
這樣做有兩個好處,一是讓系統(tǒng)依據(jù)層的情況最優(yōu)化性能,
二是如果你的PRoperty有一些setter,當(dāng)你設(shè)置的時候需要重繪,這種情況也被最優(yōu)化了.
所以你所有的setter都會調(diào)用self的setNeedsDisplay來重繪.
如果有人用了你的view,然后調(diào)用了好幾個這樣的setter,只需要重繪一次.
每個setNeedsDisplay都被一起傳過去,然后一次性畫出來.而不是每次都重繪.
環(huán)境(Context)決定了你在哪繪圖,所以你創(chuàng)建環(huán)境的方法決定了要在哪繪圖.
關(guān)于這個環(huán)境要注意的有一點,每次調(diào)用drawRect環(huán)境都是不一樣的,所以不要把它保存起來,而是每次都去獲取新的,
CGContextRef context = UIGraphicsGetCurrentContext();
這就是調(diào)用的方法,這也幾乎是每個drawRect的第一行.
CGContextRef 是個cookie,不知道到底是什么,它不是個對象,因為沒有*
當(dāng)你有了環(huán)境,就可以用它來建立軌跡了,
這里就演示一個軌跡的例子,用CGContextBeginPath(context)來傳遞剛剛得到的環(huán)境,
然后就可以進行移動、添加直線弧線之類的了,
下面的幾行代碼就創(chuàng)建了右邊的那個軌跡,
CGContextMoveToPoint(context , 75 , 10);
CGContextAddLineToPoint(context , 160 ,150);
CGContextAddLineToPoint(context , 10 ,150);
再說一次左上角是(0 , 0),畫軌跡而不是縮放,
還有CGContextClosePath(context); 它會畫條線回到起始點來封閉圖形,
封閉圖形不是必須的,你可以畫個開放的.
上面做的這些看起來像是在繪畫,但是只有上面幾行代碼的話其實什么也沒畫,雖然軌跡被創(chuàng)建了,但是沒有真的畫到屏幕上,
為什么會這樣呢?因為你需要 描邊(stroke) 或者 填充(fill) 來顯示軌跡,
在描邊或設(shè)置填充之前,還可以設(shè)置圖形屬性,這里用了UIColor設(shè)置顏色.
[ [ UIColor greenColor] setFill];
[ [ UIColor redColor] setStroke];
注意在用這個UIColor的時候不需要指出它的環(huán)境,當(dāng)你在使用對象的時候,事實上你只用到UIColor,UIFont,NSString.
這里你使用對象的時候不用指出它的環(huán)境,它會假設(shè)你用的是當(dāng)前環(huán)境,只要在前面的CGContext表面環(huán)境就可以了.
但是這里設(shè)置了描邊和填充,還是什么都沒畫,還需要調(diào)用CGContextDrawPath
CGContextDrawPath(context , kCGPathFillStroke);
這個參數(shù)kCGPathFillStroke是常量標(biāo)志,表示描邊和填充還是僅描邊或僅填充.
其實還可以建立一個軌跡,保存到一個軌跡變量CGPath,使用完之后還能交給其他環(huán)境繼續(xù)用,
更多功能,需要去查看文檔來使用.
Graphics State
圖形狀態(tài),你用的最主要的是顏色,但你可以用一些復(fù)雜的,比如線寬、圖案填充等,
CGContextSetLineWidth(context , 1.0);
CGContextSetFillPattern(context , (CGPatternRef)pattern , (CGFloat [] )components );
圖形狀態(tài)有一點要小心的就是子程序(subroutines),因為比如我有了一個新環(huán)境然后設(shè)置它的圖形狀態(tài),
那么這時候我調(diào)用的子程序會怎么樣呢?
子程序里面也有自己的圖形狀態(tài),這就和我的設(shè)置沖突了,
所以對此有個機制叫push和pop環(huán)境,
UIGraphicsPopContext();
所以我就對開始的那個環(huán)境入棧,然后再做我要做的繪圖,
然后在出棧回到調(diào)用子程序之前的環(huán)境,
在drawRect里面繪制圖片
UIImage *image="";
[image drawAtPoint:(CGPoint) p ];//按原大小繪圖
[image drawInRect:(CGRect) r ];//會縮放圖片
[image drawaspatternInRect:(CGRect) pathRect];//會重復(fù)繪圖以填滿指定的矩形區(qū)域
你還可以用PNG或者JPG格式的二進制數(shù)據(jù)來表示圖片:
新聞熱點
疑難解答