Swift學(xué)習(xí)筆記2 - Views

前言

這是斯坦福大學(xué)在線課程-Developing iOS 9 Apps with Swift 的學(xué)習(xí)內(nèi)容胡桨,在iTunes上就可以搜到,有興趣的小伙伴可以一起學(xué)習(xí)一起進步哈盼樟!這里我將一些我認(rèn)為的關(guān)鍵知識點摘錄在我的學(xué)習(xí)筆記系列中贫贝。之前用英文寫了幾篇,感覺沒什么人看乐设,其實個人認(rèn)為用英文學(xué)再用英文寫其實更簡單方便一些。

Demo

首先绎巨,是一張萌蠢的笑臉近尚,你要是看著不舒服,你可以從我的github中下載相應(yīng)代碼场勤,或者自己敲哈戈锻,讓它哭也成。

smile

Views

  • 先亂入一條(別打我)和媳,swift的命名規(guī)范:在swift中格遭,所有類型的名稱的首字母大寫。
    比如private enum Eye, private struct Ratios
  • 一個view(比如:UIView)表示的是一個矩形的區(qū)域留瞳,定義了一個坐標(biāo)空間拒迅。它可以用來畫圖(比如這個demo),也可以用來處理點擊事件她倘。
  • view在swift中是分級的璧微,也就是說
  • 一個view只能有一個superview, var superview: UIView?
  • 一個view可以有很多個subview, var subviews: [UIView]
  • subview的范圍甚至可以在他老爸view的范圍之外。
  • view是有順序之分的硬梁,后來者居上前硫。
  • UIWindow在view(分級)中處在非常高級的位置,在一個app中一般只有一個荧止。

初始化一個UIView

有兩種不同的方式:

  1. init(frame: CGRect) // 由代碼創(chuàng)建生成
  2. init(coder: NSCoder) // 由storyboard生成

如果你需要一個初始化程序屹电,那這兩種初始化都需要執(zhí)行:

func setup() { ... }

override init(frame: CGRect) { // a designed initializer
  super.init(frame: frame) 
  setup()
}

required init(coder aDecoder: NSCoder) { // a required initializer
  super.init(coder: aDecoder)
  setup()
}

另一個初始化方式:使用awakeFromNib(),這只能用于storyboard上創(chuàng)建的UIView罩息。注意這不是一個初始化器嗤详,它是“初始化完成之后立馬被調(diào)用”个扰。

坐標(biāo)系統(tǒng)數(shù)據(jù)結(jié)構(gòu)

  • CGFloat
    在UIView的坐標(biāo)系統(tǒng)中瓷炮,使用CGFloat類型的數(shù)據(jù)而不是Double或者Float。你可以將Double或者Float轉(zhuǎn)換成CGFloat, 比如: let cgf = CGFloat(aDouble)
  • CGPoint
    比如:var point = CGPoint(x: 37.0, y: 52.0)
    其實就是由兩個CGFloat類型的數(shù)組成的一個簡單結(jié)構(gòu)递宅。
  • CGSize
    和CGPoint差不多娘香,也是由兩個CGFloat類型的數(shù)組成的簡單結(jié)構(gòu)苍狰。
    比如:
var size = CGSize(width: 100.0, height: 50.0)
size.width += 10
size.height += 5
  • CGRect
    由CGPoint和CGSize組成的結(jié)構(gòu)
struct CGRect {
  var origin: CGPoint
  var size: CGSize
}
let rect = CGRect(origin: aCGPoint, size: aCGSize) //當(dāng)然可以用別的初始化方式

這結(jié)構(gòu)里自帶了很多好東西:

  • var minX: CGFloat //最小的x

  • var midY: CGFloat //中間點的y

  • intersects(CGRect) -> Bool //判斷和別的CGRect有沒有相交

  • intersect(CGRect) //返回相交的部分

  • contains(CGRect) -> Bool //判斷是否包含了另一個CGRect

  • View的坐標(biāo)系統(tǒng)

  • 左上是初始點。如下圖:


  • 烘绽!注意淋昭,單位是,不是像素安接,點不是像素翔忽,點等于幾個像素。比如在6 plus上盏檐,每個點有3個像素歇式;有些手機則是2個像素一個點。
    你可以通過這條語句知道你的設(shè)備一個點有多少像素胡野,var contentScaleFactor: CGFloat

  • 當(dāng)你需要畫圖的時候材失,使用var bounds: CGRect,這是一個包含了你自己的坐標(biāo)系統(tǒng)的畫圖空間的矩形硫豆,也就是說龙巨,它在你自己的畫圖空間里,由你在view中的代碼實現(xiàn)來定義bounds.origin熊响。

  • 那么UIView在哪里旨别?

var center: CGPoint // UIView的中心坐標(biāo)(在它的superview的坐標(biāo)系統(tǒng)中)
var frame: CGRect // 包含UIView的矩形(在它的superview的坐標(biāo)系統(tǒng)中)

。 frame指的是你的view在superview中的位置汗茄,也就是說這是放在superview的坐標(biāo)系統(tǒng)中的昼榛,而不是你的畫圖坐標(biāo)系統(tǒng)中。
剔难。 center相應(yīng)的胆屿,也是指的superview中的center,和你的畫圖空間并沒有毛線關(guān)系~當(dāng)你畫圖的時候用bounds就好啦偶宫》羌#看代碼理解也許會比較清晰一點,可以以上面提到的demo為例纯趋,
憎兽。 frame和bounds的寬高也不同,因為view可以旋轉(zhuǎn)吵冒。

創(chuàng)建一個view

在上面提到的demo中纯命,我們做的是一個笑臉,而iOS并沒有smileview這個東西痹栖,所以我們要自己建亿汞。我們使用的是一般view(generic view),就當(dāng)是一般類吧揪阿,可以拿來隨意發(fā)揮疗我。
你可以在object library里輕松找到它咆畏,或者搜“view“
e.g.

// 假設(shè)這段代碼在UIViewController中
let labelRect = CGRect(x: 20, y: 20, width: 10, height: 10)
let label = UILabel(frame: labelRect) // UILabel是UIView的子類,所以那些UILabel中的那些字也是一筆一畫畫出來的吴裤。旧找。
label.text = "hello"
view.addSubview(label)

自定義Views

  • 何時需要自定義UIView的子類

  • 我想自定義繪圖

  • 我想以一些特殊的方式處理點擊事件(這里不同于button或者slider)

  • 至于畫圖,只需要創(chuàng)建一個UIView的子類麦牺,然后override drawRect:

  • override func drawRect(regionThatNeedsToBeDrawn: CGRect)

  • 如之前所說钮蛛,你可以畫在regionThatNeedsToBeDrawn的范圍之外。
    - UIView的邊界定義了我們整個畫圖區(qū)域剖膳,region只是一個子區(qū)域

  • !!!絕對不能直接調(diào)用drawRect愿卒,它是系統(tǒng)的專屬天使。但是當(dāng)你需要畫圖怎么辦呢潮秘?告訴系統(tǒng)琼开,你要用這個方法了,用以下的語句:

setNeedsDisplay()
setNeedsDisplayInRect(regionThatNeedsToBeRedrawn: CGRect)

iOS會在一個適當(dāng)?shù)臅r機調(diào)用drawRect枕荞,比如你的破事全部決定了之后柜候,一次性將要重畫(redraw)的東西全部drawRect。

  • 那么我怎么實現(xiàn)drawRect呢躏精?

  • 你可以使用一個類C的API(不是面向?qū)ο蟮模┰ⅲ蠧ore Graphics,swift是完全面相對象的矗烛,摻和進來這玩意應(yīng)該不是好事吧 ==

  • 你還可以使用面向?qū)ο蟮念悾璘IBezierPath辅柴,這也是我們在demo中所使用的。

  • Core Graphics的一些基本概念

  1. 使用UIGraphicsGetCurrentContext()來獲取一些能在drawRect中使用的文本內(nèi)容(context瞭吃,打印的碌嘀,屏幕外的緩存中的, etc.)
  2. 創(chuàng)建路徑(線,圓)
  3. 設(shè)定一些相關(guān)屬性歪架,比如顏色股冗,字體,線寬之類的和蚪。
  4. stroke或者fill以上創(chuàng)建的路徑止状。
  • UIBezierPath
    和上面那個家伙差不多,只是UIBezierPath自動知道context攒霹。

  • 定義一個路徑

  • 創(chuàng)建一個UIBezierPath

let path = UIBezierPath()
  • 加幾條線怯疤,或者圓弧
path.moveToPoint(CGPoint(x: 80, y: 50))
path.addLineToPoint(CGPoint(x:140, y: 150))
path.addLineToPoint(CGPoint(x: 10, y: 150))
  • 可以閉合路徑
path.closePath()

此時就已經(jīng)得到了一個可愛的三角形。但是并沒有畫出來

  • 注意催束, 你僅僅將上面創(chuàng)建的線條放在drawRect中集峦,并不會顯示什么。必須要設(shè)置相應(yīng)的屬性(顏色,線寬等等)少梁,然后strokefill,才能在屏幕上顯示出來矫付。
UIColor.greenColor().setFill() // 注意這是UIColor中的方法
UIColor.redColor().setStroke() // 注意這是UIColor中的方法
path.lineWidth = 3.0 // 這是UIBezierPath中的屬性
path.fill() // UIBezierPath中的方法
path.stroke() // UIBezierPath中的方法
  • 你也可以用UIBezierPath畫很多其它類型的圖凯沪,比如:
let roundRect = UIBezierPath(roundedRect: CGRect, cornerRadius: CGFloat)
let oval = UIBezierPath(ovalInRect: aCGRect)
  • 也可以圓滑夾角,就是給每個角增加一個弧度买优。使用addClip()
  • 也可以進行碰撞監(jiān)測妨马,就是檢測一個點是不是在閉合路徑里面。
func containsPoint(CGPoint) -> Bool

UIColor

  • 對于很多普通顏色來講杀赢,有很多類方法可以使用烘跺,比如let green = UIColor.greenColor(),可以用RGB, HSB, 甚至可以使用某些樣式(比如圖片)脂崔。
  • UIView的背景色滤淳,var backgroundColor: UIColor
  • 顏色可以有alpha,可以設(shè)置透明度
let transparentYellow = UIColor.yellowColor().colorWithAlphaComponent(0.5) // 這是個instance method, 不是type method

alpha: 0.0(完全透明) - 1.0(完全不透明)

  • 如果想要在程序中設(shè)置顏色的透明度砌左,必須設(shè)置var opaque = false脖咐, 來讓系統(tǒng)知道這些都不是不透明的,也就是你要開始設(shè)置透明度了汇歹。

  • 也可以設(shè)置整個UIView的透明度

var alpha: CGFloat

通過alpha屁擅,可是設(shè)計一個漸出(慢慢消失)的動畫。

  • 也可以隱藏一個view产弹,通過var hidden: Bool

顯示(畫)文本

  • 一般我們使用UILabel來顯示文本派歌,但我們有時候還是需要在drawRect中直接顯示文本
  • 在drawRect中,可以使用NSAttributedString
    AttributedString就是每個string中的字符痰哨,都有一個字典存儲相應(yīng)的每個字符的屬性信息胶果,比如顏色,字體等斤斧。
let text = NSAttributedString("hello")
text.drawAtPoint(aCGPoint)
let textSize: CGSize = text.size //這個字符串需要多少空間
  • NSAttributedString的兩個弊端
  1. 我們知道稽物,var具有可變性(mutability),let沒有折欠。但是在NSAttributedString中贝或,不管是var還是let,都是不可變的(immutable)锐秦。因為這是個objective-c的類咪奖,所以swift中還是有點缺陷。要想做到可變形酱床,你可以使用另一個類羊赵,NSMutableAttributedString,如下語句:
let mutableString = NSMutableAttributedString("some text")

注意,NSAttributedString不是String昧捷,也不是NSString.

  1. swift的string是unicode的闲昭,比oc的強大太多,所以它們的string也不一樣靡挥,在NSAttributedString中序矩,需要使用NSRange,注意這不是Range跋破,這是oc里的NSRange簸淀。所以在使用的時候,需要將range轉(zhuǎn)換成NSRange(可自動完成)毒返,然后才能在NSAttributedString中用NSRange租幕。
func setAttributes(attributes: Dictionary, range: NSRange)
func addAttributes(attributes: Dictionary, range: NSRange)

在Attributes中可以放以下這些dictionary:
NSForegroundColorAttributeName: UIColor
NSStrokeWidthAttributeName: UIFloat
NSFontAttributeName: UIFont

字體

字體在蘋果的產(chǎn)品中占有非常重要的地位,畢竟藝術(shù)品拧簸。

  • 使用字體的最好的方式
  • 對于文本內(nèi)容劲绪,采用preferred font
static func preferredFontForTextStyle(UIFontTextStyle) -> UIFont
UIFontTextStyle.Headline
UIFontTextStyle.Body
UIFontTextStyle.Footnote
  • 對于按鈕之類的,使用系統(tǒng)字體(system fonts)
static func systemFontOfSize(pointSize: CGFloat) -> UIFont
static func boldSystemFontOfSize(pointSize: CGFloat) -> UIFont

在用戶的文本信息中盆赤,不要使用這些系統(tǒng)字體

  • 其它方式:UIFont和UIFontDescriptor

顯示圖片

有個UILabel相類似的類珠叔,UIImageView,當(dāng)然你還是有可能想在drawRect中直接顯示圖片的弟劲,那么祷安。。兔乞。

  • 創(chuàng)建UIImage - let image: UIImage? = UIImage(named: "foo")汇鞭,optional是因為有可能沒有圖片
  • 從系統(tǒng)文件中創(chuàng)建(files in the file system)
let image: UIImage?  = UIImage(contentsOfFile: aString)
let image: UIImage?  = UIImage(data: anNSData) // jpg, png, tiff, etc.
  • 開始畫
let image: UIImage = ...
image.drawAtPoint(aCGPoint) // 圖片的左上角
image.drawInRect(aCGRect) // 將圖片按比例擴充到aCGRect中
image.drawAsPatternInRect(aCGRect) //將圖片平鋪到aCGRect中

歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處庸追。訪問我的個人主頁霍骄,了解更多。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淡溯,一起剝皮案震驚了整個濱河市读整,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咱娶,老刑警劉巖米间,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膘侮,居然都是意外死亡屈糊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門琼了,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逻锐,“玉大人,你說我怎么就攤上這事∶劣眨” “怎么了晓淀?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盏档。 經(jīng)常有香客問我凶掰,道長,這世上最難降的妖魔是什么妆丘? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任锄俄,我火速辦了婚禮局劲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鱼填。我一直安慰自己药有,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布苹丸。 她就那樣靜靜地躺著愤惰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赘理。 梳的紋絲不亂的頭發(fā)上宦言,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音商模,去河邊找鬼奠旺。 笑死,一個胖子當(dāng)著我的面吹牛施流,可吹牛的內(nèi)容都是我干的响疚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瞪醋,長吁一口氣:“原來是場噩夢啊……” “哼忿晕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起银受,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤践盼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宾巍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宏侍,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年蜀漆,在試婚紗的時候發(fā)現(xiàn)自己被綠了谅河。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绷耍,靈堂內(nèi)的尸體忽然破棺而出吐限,到底是詐尸還是另有隱情,我是刑警寧澤褂始,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布诸典,位于F島的核電站,受9級特大地震影響崎苗,放射性物質(zhì)發(fā)生泄漏狐粱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一胆数、第九天 我趴在偏房一處隱蔽的房頂上張望肌蜻。 院中可真熱鬧,春花似錦必尼、人聲如沸蒋搜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豆挽。三九已至,卻和暖如春券盅,著一層夾襖步出監(jiān)牢的瞬間帮哈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工锰镀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留娘侍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓互站,卻偏偏與公主長得像私蕾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子胡桃,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容