本文翻譯自http://nshipster.com辨泳,如有錯(cuò)漏婆咸,歡迎斧正谈截。
首先來(lái)了解一下iOS和OS X的繪制系統(tǒng):
1.CGPoint筷屡,是一個(gè)結(jié)構(gòu)體,表示了二維坐標(biāo)系統(tǒng)中的一個(gè)點(diǎn)簸喂,iOS中原點(diǎn)是左上角毙死,X軸和Y軸的值分別是向右和向下增加。OS X中原點(diǎn)是左下角娘赴,相反地规哲,X軸和Y軸的值分別是向右和向上增加。
2.CGSize诽表,也是一個(gè)結(jié)構(gòu)體唉锌,表示了包括寬度(width)和高度(height)的尺寸。
3.CGRect竿奏,仍然是一個(gè)結(jié)構(gòu)體袄简,包含了CGPoint(代表原點(diǎn))和CGSize(代表尺寸),表示了一個(gè)長(zhǎng)方形泛啸,從原點(diǎn)開(kāi)始按照寬度和長(zhǎng)度的尺寸繪制绿语。
因?yàn)镃GRect代表了出現(xiàn)在屏幕上的每一個(gè)view的frame,所以一個(gè)程序員的圖形編程能力取決于能否熟練地使用長(zhǎng)方形幾何。幸運(yùn)的是吕粹,Quartz有很多有用的功能种柑,可以省去我們很多的計(jì)算功夫,雖然圖形編程在iOS中十分重要匹耕,但是Quartz有很多功能可以說(shuō)是鮮為人知聚请。
轉(zhuǎn)換功能
rectByOffsetting/CGRectOffset:返回一個(gè)相對(duì)于原長(zhǎng)方形原點(diǎn)偏移了的長(zhǎng)方形。
CGRect CGRectOffset(
CGRect rect,
CGFloat dx,
CGFloat dy
)
? 設(shè)想一下每當(dāng)你要改變一個(gè)長(zhǎng)方形的原點(diǎn)就可以使用稳其,不單是省去了很多行代碼驶赏,更重要的是這比改變?cè)c(diǎn)在語(yǔ)言上更加直觀。
? rectByInsetting/CGRectInSet:返回一個(gè)相對(duì)于原長(zhǎng)方形更大或者更小既鞠,但是同一個(gè)中心點(diǎn)的長(zhǎng)方形煤傍。
CGRect CGRectInset(
CGRect rect,
CGFloat dx,
CGFloat dy
)
希望漂亮地在一個(gè)view的基礎(chǔ)上再創(chuàng)建一個(gè)view?用CGRectInset并傳入10的值嘱蛋,那么就會(huì)返回一個(gè)比原長(zhǎng)方形左右以及上下都增加了10的長(zhǎng)方形蚯姆。
integerRect/CGRectInteger:返回一個(gè)相對(duì)于原長(zhǎng)方形所有值取整的長(zhǎng)方形。
CGRect CGRectIntegral (
CGRect rect
)
? 值得注意的是浑槽,CGRect所有的值都會(huì)被四舍五入取最接近的整數(shù)蒋失,分?jǐn)?shù)值會(huì)導(dǎo)致在像素邊緣繪制。因?yàn)橄袼厥亲罨镜睦L制單位桐玻,所以分?jǐn)?shù)值就會(huì)導(dǎo)致繪制平均地繪制到下一像素篙挽,由此就會(huì)導(dǎo)致模糊。對(duì)于原點(diǎn)的值會(huì)取小于或等于原值的整數(shù)镊靴,對(duì)于尺寸的值則會(huì)去大于或等于原值的整數(shù)铣卡。所以作為經(jīng)驗(yàn)之談,如果有一些可能會(huì)導(dǎo)致出現(xiàn)分?jǐn)?shù)值的操作偏竟,最好使用此函數(shù)取整煮落,重設(shè)view的frame。
? 技術(shù)性提醒踊谋,由于坐標(biāo)系統(tǒng)通常是用點(diǎn)(point)表示蝉仇,對(duì)于視網(wǎng)膜屏,一個(gè)點(diǎn)有四個(gè)像素殖蚕,所以在視網(wǎng)膜繪制的時(shí)候轿衔,可以有0.5的分?jǐn)?shù)值取奇數(shù)個(gè)像素,而不會(huì)導(dǎo)致模糊睦疫。
取值功能
CGRectGet[Min|Mid|Max][X|Y]
[objc] view plain copy print?
CGRectGetMinX
CGRectGetMinY
CGRectGetMidX
CGRectGetMidY
CGRectGetMaxX
CGRectGetMaxY
上述六個(gè)函數(shù)分別對(duì)一個(gè)長(zhǎng)方形的X值或Y值取最小值害驹、中間值、最大值:
CGFloat CGRectGet[Min|Mid|Max][X|Y] (
CGRect rect
)
? 這幾個(gè)函數(shù)以十分簡(jiǎn)潔易懂的方式代替了諸如frame.size.x + frame.size.width這樣的代碼蛤育。
CGRectGet[Width|Height]
// Returns the height of a rectangle.
CGFloat CGRectGetHeight (
CGRect rect
)
// Returns the width of a rectangle.
CGFloat CGRectGetWidth (
CGRect rect
)
這兩個(gè)函數(shù)顧名思義宛官,返回長(zhǎng)方形的寬或高葫松。
特點(diǎn)
CGRectZero, CGRectNull, & CGRectInfinite
這是長(zhǎng)方形的值中三個(gè)特殊值,每一個(gè)都有自己獨(dú)特的屬性:
[objc] view plain copy print?
CGRect.zeroRect/const CGRect CGRectZero: 零長(zhǎng)方形底洗,一個(gè)長(zhǎng)方形常量腋么,原點(diǎn)是(0,0),寬和高也是0亥揖。
CGRect.nullRect/const CGRect CGRectNull:null長(zhǎng)方形党晋,兩個(gè)不連貫的長(zhǎng)方形返回的值,不等同于零長(zhǎng)方形徐块。
CGRect.infiniteRect/const CGRect CGRectInfinite: 擁有無(wú)限尺寸大小的長(zhǎng)方形。
CGRectZero應(yīng)該是最有用的特殊值了灾而,初始化子視圖的時(shí)候胡控,其frame經(jīng)常是CGRectZero,frame的設(shè)置則延遲到-layoutsubViews.
CGRectNull不同于 CGRectZero旁趟,盡管有很多暗示null == 0昼激。這個(gè)值其實(shí)更接近于NSNotFound,代表了值的缺省锡搜。需要注意什么樣的函數(shù)可以返回CGRectNull橙困,并正確地操作。
CGRectInfinite可以說(shuō)是最迷人耕餐、最有趣的特殊值凡傅。它和所有的點(diǎn)和長(zhǎng)方形相交,包含所有的長(zhǎng)方形肠缔,
關(guān)系
從一個(gè)長(zhǎng)方形移動(dòng)到另一個(gè)長(zhǎng)方形夏跷,兩個(gè)長(zhǎng)方形可以通過(guò)相交或合并來(lái)創(chuàng)建新的長(zhǎng)方形
CGRectIntersection
[objc] view plain copy print?
rectByIntersecting/CGRectIntersection: 返回兩個(gè)長(zhǎng)方形的相交部分。
CGRect CGRectIntersection (
CGRect rect1,
CGRect rect2
)
這是找出兩個(gè)view重疊部分的一個(gè)快捷方式明未,如果兩個(gè)長(zhǎng)方形不相交槽华,則返回null長(zhǎng)方形。
CGRectUnion
rectByUnion/CGRectUnion: 返回一個(gè)包含兩個(gè)長(zhǎng)方形的長(zhǎng)方形趟妥。
CGRect CGRectUnion (
CGRect rect1,
CGRect rect2
)
返回一個(gè)包含兩個(gè)傳入長(zhǎng)方形的長(zhǎng)方形猫态,很方便地創(chuàng)建一個(gè)長(zhǎng)方形包含兩個(gè)單獨(dú)的view,以上方法還可以組合使用:
CGRect combinedRect = CGRectInset(CGRectUnion(imageRect, textRect), -10, -10);
以上就創(chuàng)建了一個(gè)包含imageRect和textRect的長(zhǎng)方形披摄,并且上下左右各增加10的值亲雪,新創(chuàng)建的長(zhǎng)方形不會(huì)和包含的長(zhǎng)方形重疊。
最后
前方高能預(yù)警行疏,前方是最費(fèi)解匆光、最易誤解、最有用的CGGeometry函數(shù):CGRectDivide酿联。
CGRectDivide
CGRectDivide: 將一個(gè)長(zhǎng)方形分割成單獨(dú)的兩個(gè)長(zhǎng)方形终息。
void CGRectDivide(
CGRect rect,
CGRect *slice,
CGRect *remainder,
CGFloat amount,
CGRectEdge edge
)
CGRectDivide的操作步驟如下:
1.選取一個(gè)長(zhǎng)方形并選定其中一邊(上下左右)
2.度量出距離選取邊的一定距離夺巩。
3.選取邊至度量距離之間的值會(huì)存儲(chǔ)在slice里面
4.原長(zhǎng)方形的其余值則存儲(chǔ)在reminder里面
edge是一個(gè)枚舉值CGRectEdge:
enum CGRectEdge {
CGRectMinXEdge,
CGRectMinYEdge,
CGRectMaxXEdge,
CGRectMaxYEdge
}
這個(gè)方法十分適合于在view之間分離出可用的空間,通過(guò)組合使用可以在多于兩個(gè)view之間操作周崭。