自定义View相关
實現自定義View的關鍵是重載UIView的drawRect: 方法,因為主要是通過重載這個方法,來改變view的外觀。
例如:
?
- (void)drawRect:(CGRect)rect{
// 繪圖
CGRect bounds = [self bounds];
// Where is its center?
CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0;
// From the center how far out to a corner?
float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;
// Get the context being drawn upon
CGContextRef context = UIGraphicsGetCurrentContext();
// All lines will be drawn 10 points wide
CGContextSetLineWidth(context, 10);
// Set the stroke color to light gray
[[UIColor lightGrayColor] setStroke];
// Draw concentric circles from the outside in
for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20)
{
CGContextAddArc(context, center.x, center.y,
currentRadius, 0.0, M_PI * 2.0, YES);
CGContextStrokePath(context);
}
// 繪文字
NSString *text = @"Hello,World!";
// Get a font to draw it in
UIFont *font = [UIFont boldSystemFontOfSize:28];
// Where am I going to draw it?
CGRect textRect;
textRect.size = [text sizeWithFont:font];
textRect.origin.x = center.x - textRect.size.width / 2.0;
textRect.origin.y = center.y - textRect.size.height / 2.0;
// Set the fill color of the current context to black
[[UIColor blackColor] setFill];
// Set the shadow to be offset 4 points right, 3 points down,
// dark gray and with a blur radius of 2 points
CGSize offset = CGSizeMake(4, 3);
CGColorRef color = [[UIColor darkGrayColor] CGColor];
CGContextSetShadowWithColor(context, offset, 2.0, color);
// Draw the string
[text drawInRect:textRect
withFont:font]; }
再說明一下重繪,重繪操作仍然在drawRect方法中完成,但是蘋果不建議直接調用drawRect方法,當然如果你強直直接調用此方法,當然是沒有效果的。
蘋果要求我們調用UIView類中的setNeedsDisplay方法,則程序會自動調用drawRect方法進行重繪。(調用setNeedsDisplay會自動調用drawRect)
在UIView中,重寫drawRect: (CGRect) aRect方法,可以自己定義想要畫的圖案.且此方法一般情況下只會畫一次.也就是說這個drawRect方法一般情況下只會被掉用一次.?當某些情況下想要手動重畫這個View,只需要掉用[self setNeedsDisplay]方法即可.
drawRect調是在Controller->loadView, Controller->viewDidLoad 兩方法之后調用的.所以不用擔心在控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設置一些值給View(如果這些View draw的時候需要用到某些變量值).
1.如果在UIView初始化時沒有設置rect大小,將直接導致drawRect不被自動調用。2.該方法在調用sizeThatFits后被調用,所以可以先調用sizeToFit計算出size。然后系統自動調用drawRect:方法。
3.通過設置contentMode屬性值為UIViewContentModeRedraw。那么將在每次設置或更改frame的時候自動調用drawRect:。
4.直接調用setNeedsDisplay,或者setNeedsDisplayInRect:觸發drawRect:,但是有個前提條件是rect不能為0.
以上1,2推薦;而3,4不提倡
1、若使用UIView繪圖,只能在drawRect:方法中獲取相應的contextRef并繪圖。如果在其他方法中獲取將獲取到一個invalidate的ref并且不能用于畫圖。drawRect:方法不能手動顯示調用,必須通過調用setNeedsDisplay 或者 setNeedsDisplayInRect ,讓系統自動調該方法。
2、若使用calayer繪圖,只能在drawInContext: 中(類似于drawRect)繪制,或者在delegate中的相應方法繪制。同樣也是調用setNeedDisplay等間接調用以上方法。
3、若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實時刷新屏幕
附高人對UIView的drawRect: 和 - (void)setNeedsDisplay 的一些理解
在UIView中,
1、自定義畫圖,類似android的onDraw()
- (void)drawRect:(CGRect)rect;
?is invoked automaticall,never call it directly!!2、刷新視圖,類似android的invalidate()
- (void)setNeedsDisplay;
When a view needs to be redrawn,use:?
3、在非主線程中調用,需使用如下方法:
????? - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait
?? ?? - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
4、setNeedsDisplay是不阻塞的,
?? ? 需要自己制造阻塞,
?? ? setNeedsDisplay我理解就是告訴系統,等會幫哥把這塊重新畫一下。
???? 系統就知道了,等系統有空了,他就一起畫了,
?? ? 如果想立即畫出來,可能要用setNeedsLayout,
?? ? 或者不用drawInRect系列的方式,直接改view.image或者文字,加動畫等方式實現吧。
5、setNeedsDisplay和layoutSubViews
???? 首先兩個方法都是異步執行的。而setNeedsDisplay會調用自動調用drawRect方法,這樣可以拿到UIGraphicsGetCurrentContext,就可以畫畫了。而setNeedsLayout會默認調? 用layoutSubViews,就可以處理子視圖中的一些數據。
綜上所訴,setNeedsDisplay方便繪圖,而layoutSubViews方便出來數據。
轉載于:https://www.cnblogs.com/ranger-jlu/p/3957096.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: 操作系统之内存管理:4、基本地址变换机构
- 下一篇: 数据结构之串:串的模式匹配