第九章 用原型單元格(prototype cell)自定義table view

QQ20151211-4@2x.png

我認為這是最好的建議:不斷的思考你怎樣才能把事情做得更好并且不斷的質(zhì)疑自己。
-Elon Musk,Tesla Motors

在前面一章,我們創(chuàng)建了一個簡單的基于表格的app來用基本的單元格形式演示餐廳的清單。這一章,我們將自定義表格單元格然后讓它看起來更時髦。我們將作出一些變化和增強功能:

  • 用UITableViewController代替UITableView來重構(gòu)app。
  • 給每個餐廳顯示獨特的圖片代替顯示同樣的縮略圖。
  • 設(shè)計自定義的table view單元格代替基本樣式的table view單元格。
    你可能想知道為什么我們要重構(gòu)同樣的app。做事情永遠不止一種辦法。以前,我們用UITableview來創(chuàng)建table view。在這章,我們將用UITableViewController來在Xcode里創(chuàng)建table view app。它更簡單嗎?是的。回憶一下,我們需要采用UITableViewDataSource和UITableViewDelegate協(xié)議,UITableViewController已經(jīng)采用了這些協(xié)議并且為我們建立聯(lián)系。除此之外,它有所有必須的布局約束。

Quick note: 我們正在構(gòu)建一個真正的app,所以我們給它一個更好的名字。

QQ20151211-2@2x.png

創(chuàng)建一個Xcode工程,選擇Main.storyboard然后跳到界面編輯器。Xcode會生成默認的視圖控制器。這次,我們不用默認的控制器。選擇視圖控制器,按delete鍵來刪除它。這個視圖編輯器是與ViewController.swift關(guān)聯(lián)的。我們也不需要它。在工程導(dǎo)航里,選擇文件然后點擊delete按鈕。選擇”Move to Trash”。這將完全的刪除文件。
回到界面編輯器,從對象庫里拖曳一個 Table View Controller(如 UITableViewController),然后放在 storyboard里。你必須指明這個控制器作為初始視圖控制器。這會告訴 iOS 這個table view 控制器是第一個被讀取的視圖控制器。你需要做的是選擇 Attributes inspector,然后檢查 Is Initial View Controller 選項。你會看到一個箭頭指向table view控制器。


QQ20151211-3@2x.png

我們還沒有插入任何數(shù)據(jù)到表格里。所以如果你編譯運行 app,你將會看到一個空白的表格。
默認情況下,table view 控制器與 UITableViewController 類關(guān)聯(lián)在一起。回到工程導(dǎo)航欄然后右擊 FoodPin文件夾。選擇“New Files”來創(chuàng)建一個新的文件。

QQ20151211-4@2x.png

選擇 Source(在 iOS分類下)> Cocoa Touch Class作為模板,然后點擊 Next。命名為新類 RestaurantTableViewController。因為我們用一個 table view 編輯器工作,改變“Subclass of”值到 UITableViewController。保持其他的值不變,點擊“Next”然后把它保存到工程文件夾。你應(yīng)該能看到 RestaurantTableViewController.swift文件在工程導(dǎo)航欄。


QQ20151211-5@2x.png

超類和子類

如果你是個編程新手,你可能想知道子類是什么。Swift 是一個面向?qū)ο螅∣OP)語言。在 OOP 里,一個類會被繼承到另一個類。在這個實例中,RestaurantTableViewController類繼承自 UITableViewController 類。它繼承 UITableViewController 類所有的狀態(tài)和方法。RestaurantTableViewController 類被稱作 UITableViewController 的子類。換句話說,UITableViewController 類作為超類(或者父類(parent class))被 RestaurantTableViewController 繼承。

storyboard 里的table view controller不知道 RestaurantTableViewController 類。所有我們必須分配給 table view controller新的自定義類。進到界面編輯器然后選擇 table view controller。在 Identity inspector 里,設(shè)置自定義類為 RestaurantTableViewController。現(xiàn)在我們給storyboard 里的 table view controller和新類建立了聯(lián)系。


QQ20151212-0@2x.png

還要做一件事來給 table view 進行設(shè)置。選擇原型單元格。在 Attributes inspector 里,改變格式為 Basic 然后設(shè)定 identifier 為 Cell。這和我們前一章做的很像。
OKay,用戶界面準備好了。我們?nèi)ゴa字。在工程導(dǎo)航欄里選擇 RestaurantTableViewController.swift文件然后聲明一個實例變量,用來放置表格內(nèi)容。

var restaurantNames = [“Cafe Deadend", "Homei", "Teakha", "Cafe Loisl", "Petite Oyster", "For Kee Restauran”,“ "Po's Atelier", "Bourke Street Bakery", "Haigh's Chocolate", "Palomino Espresso", "Upstate", "Traif", "Graham Avenue Meats", "Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia", "Royal Oak", "Thai Cafe”]

像之前說的,UITableViewController 類已經(jīng)添加了 UITableViewDataSource 和 UITableViewDelegate 協(xié)議。作為 UITableViewController 的子集,RestaurantTableViewController 也添加了這些協(xié)議。
如果你沒忘記,我們需要實現(xiàn)下面 UITableViewDataSource 協(xié)議要求的方法來提供表格內(nèi)容:

  • tableView(_:numberOfRowsInSection:)
  • tableView(_:cellForRowAtIndexPath:)

UITableViewController 類為這兩個方法提供了一個默認的執(zhí)行。通常,這些默認的方法在我們的 app 里并不合適。我們需要重寫默認的方法然后提供我們自己的執(zhí)行。在 RestaurantTableViewController.swift 里插入以下的代碼:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cellIdentifier = “Cell”
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
//配置單元格
cell.textLabel?.text = restaurantNames[indexPath.row]
cell.imageView?.image = UIImage(named: “restaurant.jpg”)
return cell
}

在 Swift 里,為了重寫一個超類的方法,我們在方法的開頭簡單的增加 override 關(guān)鍵詞。以上的代碼和前一章一樣,我不再復(fù)述細節(jié)了。
下一步,在 RestaurantTableViewController里改變下面的代碼片段。這些代碼是當生成了類文件時 Xcode 自動創(chuàng)建的。默認情況下,章節(jié)數(shù)和章節(jié)行數(shù)都返回0值。換句話說,它告訴 table view說 table view 里面沒有數(shù)據(jù)。這不是我們想要的,所以我們必須把代碼改成這樣:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section:Int) ->Int {
return restaurantNames.count
}

這里我們告訴table view這里只有一章然后在數(shù)組里保存返回餐廳的數(shù)量。作為附注,numberOfSectionsInTableView 方法是可選的。如果你移動它,table view 仍然會工作,因為章節(jié)數(shù)默認設(shè)置成1。
最后,下載圖片然后拖曳所有圖片到 Assets.xcassets文件夾。現(xiàn)在,點擊“Run”按鈕然后你的 FoodPin app 看起來和我們之前構(gòu)建的一樣。


QQ20151212-3@2x.png

現(xiàn)在你應(yīng)該理解怎樣在一個 table view 里顯示數(shù)據(jù)。我已經(jīng)給你展示了兩個辦法:
1、用 UITableView 和 View Controller。
2、用 UITableViewController。
你可能想知道你應(yīng)該用哪個辦法。大體來說,2#辦法更好。UITableViewController 為你配置了所有事情。你可以簡單的重寫一些方法來提供表格數(shù)據(jù)。但是這樣失去了靈活性。嵌入在 UITableViewController 里的 table view 是固定的,你不能改變它。如果你想要用 table view布局一個更復(fù)雜的 UI,1#方法將會更合適。

演示不同的縮略圖

你做了前面章節(jié)的練習(xí)嗎?我希望你已經(jīng)用功了。有很多方法來演示不同的縮略圖對應(yīng)每個表格行。我會給你展示最直白的方法。首先,下載圖片包。添加所有的圖片到 Assets.xcasset。如果你喜歡,你可以使用你自己的圖片。


QQ20151212-1@2x.png

在我們改變代碼之前,讓我們重溫在表格行里顯示縮略行的代碼。

cell.imageView?.image = UIImage(named: “restaurant.jpg”)

上面那行代碼tableView(_:cellForRowAtIndexPath:) 方法指導(dǎo) UITableView 來在每個單元格里演示 restaurant.jpg。為了顯示不同的圖片,我們需要更改代碼行。
像之前解釋的那樣,iOS 每次調(diào)用這個方法,特殊的表格行將會顯示出來。正確的行數(shù)被嵌入到 indexPath 參數(shù)。你可以簡單的使用 indexPath.rou 來找出哪一行正在處理。
因此,為了在每行顯示不同的圖片,我們需要做的是添加一個新的數(shù)組來儲存縮略圖的文件名。我們把這個數(shù)組命名為 restaurantImages。插入下面這行代碼到 RestaurantTableViewController 類:

var restaurantImages = ["cafedeadend.jpg", "homei.jpg", "teakha.jpg", "cafeloisl.jpg", "petiteoyster.jpg", "forkeerestaurant.jpg", "posatelier.jpg", "bourkestreetbakery.jpg", "haighschocolate.jpg", "palominoespresso.jpg", "upstate.jpg", "traif.jpg", "grahamavenuemeats.jpg", "wafflewolf.jpg", "fiveleaves.jpg", "cafelore.jpg", "confessional.jpg", "barrafina.jpg", "donostia.jpg", "royaloak.jpg", "thaicafe.jpg”]

在上面的代碼里,我們用一個圖片文件名清單初始化了 restaurantImages 數(shù)組。圖片的順序與 restaurantNames 保持一致。
為了讀取相應(yīng)的餐廳圖片,把 tableview(_:cellForRowAtIndexPath:)方法的代碼行改成:
cell.imageView?.image = UIImage(named:restaurantImages[indexPath.row])
保存所有改變以后,嘗試再次運行你的 app。每個餐廳有它自己圖片。


QQ20151213-0@2x.png

自定義 table view 單元格

app 是不是看起來更好了?我們用自定單元格來讓它變得更好。到目前為止我們利用的是默認的 table view 單位格。縮略圖的位置和大小都是固定的。如果你想要:

  • 改變單元格的高度。
  • 把縮略圖變大一點。
  • 顯示更多餐廳的信息,比如位置和類型。
  • 改變字體類型和大小。
  • 顯示圓形的圖片來代替方形的圖片。

為了讓你更好的理解單元格是怎樣自定義的,看下圖,單元格看起來很酷,對吧?

QQ20151213-1@2x.png

在界面編輯器里設(shè)計原型單元格(prototype cell)

prototype cell的美妙之處在于,它允許開發(fā)者在 table view controller 里來自定義單元格。
我們先來改變單元格的樣式。當它設(shè)置成 Basic 樣式的適合你不能自定義單元格。在 Attributes inspector 里選擇原型單元格然后把樣式從 Basic 變成 Custom。


QQ20151213-2@2x.png

為了容納更大的縮略圖,我們必須把單元格也變大一點。你需要改變table view 和原型單元格的行高。選擇 table view 然后把行高變成80。

QQ20151213-3@2x.png

然后選擇prototype cell,進入 Size inspector。檢查 custom 復(fù)選框然后把行高變成80。

QQ20151213-4@2x.png

變更行高之后,從對象庫里拖一個 Image View 到prototype cell。選擇 image view,點擊“Size”inspector,改變“X”,“Y”,“Width”和“height”的屬性。

QQ20151213-5@2x.png

接下來,我們添加三個標簽到prototype cell:

  • Name - 餐廳名字
  • Lcation - 餐廳地址(如:紐約)
  • Type - 餐廳形式(如:茶館)

為了添加一個標簽,從對象庫里拖曳一個 Label 對象到單元格。給第一個標簽命名為“Name”。我們用一個文本樣式(text style)來代替標簽的系統(tǒng)字體。下一章我會給你解釋固定字體和文本樣式的區(qū)別。現(xiàn)在,進入 Attributes inspector,把字體改成 Txet Style - Headline。

QQ20151213-6@2x.png

拖曳另一個標簽到單元格然后把它命名為 Location。把字體樣式改成 Light 然后設(shè)置字體大小為14。同樣的設(shè)置字體顏色為 Dark Gray。最后,創(chuàng)造另一個標簽命名為 Type。同樣的,把字體形式改成 Light 然后設(shè)置字體大小為13。
我已經(jīng)在第六章介紹過 stack views。你不僅僅可以在 view controller 里用 stack view,你同樣在 prototype cell 里使用 stack views 來布局約束。因此,我們將用 stack views 來管理標簽和圖片視圖,而不是定義布局約束。首先,按住 command 鍵,選擇三個標簽。點擊布局欄里的 stack 按鈕來把他們嵌入到垂直的 stack view 里。進入到 Attributes inspector,把 stack view 的間距從0改成1。這會在標簽之間添加一個約束。

QQ20151213-7@2x.png

現(xiàn)在選擇我們剛創(chuàng)建的 image view 和 stack view。點擊 Stack 按鈕,界面編輯器將把它們嵌入到一個水平 stack view。默認情況下,image view 和“Label”stack view 之間沒有間距。你可以到 Attributes inspector 里把 spcing 選項從0改成10。很酷,對嗎?你可以嵌套堆棧視圖來創(chuàng)建一些復(fù)雜的布局。


QQ20151213-8@2x.png

但是,這不意味著你不需要用 auto layout。我們?nèi)匀恍枰獮?stack view 來定義布局約束。下圖描述了單元格的布局要求。

QQ20151213-9@2x.png

簡而言之,我們希望單元格內(nèi)容(如 stack view)受限于單元格的可視區(qū)域。這是為什么我們要為每邊的 stack view定義間距約束。除此之外,image view 的大小應(yīng)該固定在60X60。
現(xiàn)在選擇 stack view,點擊布局欄里的 Pin 按鈕。分別設(shè)置上,左,下,右的值為2,6,1.5和0


QQ20151213-10@2x.png

一旦你添加了4個約束,stack view 會自動調(diào)整大小。下一步,在文件大綱里,水平拖曳 image view。在彈出的菜單里,按住 shift 鍵選擇“width”和“height”選項。這個內(nèi)嵌視圖的大小就固定了。

QQ20151213-11@2x.png

Cool!你已經(jīng)完成了 prototype cell 的布局。我們繼續(xù)寫一些代碼。

為自定義單元格創(chuàng)造一個類

到目前為止,我們設(shè)計了單元格。但是我們怎樣改變標簽的 prototype cell 值?這些值應(yīng)該是動態(tài)的。默認情況下,prototype cell 應(yīng)該是和 UITableViewCell 類相關(guān)聯(lián)的。為了更新單元格數(shù)據(jù),我們將為 prototype cell創(chuàng)建一個新的類,這個類繼承自UITableViewCell。這個類代表了自定義單元格的底層數(shù)據(jù)模型。像往常一樣,在工程導(dǎo)航欄右擊“FoodPin”文件夾然后選擇“New File…”。
在選擇這個選項之后,Xcode 提示你來選擇一個模型。我們準備為自定義 table view 單元格創(chuàng)建一個新的類,選擇“Cocoa Touch Class”然后點擊“Next”。填入 RestaurantTableViewCell 作為類名然后設(shè)置“Subclass of”的值為 UITableViewCell。

QQ20151213-12@2x.png

點擊“Next”然后把文件保存到 FoodPin 工程文件里。Xcode 應(yīng)該在工程導(dǎo)航欄里創(chuàng)建一個文件叫做 RestaurantTableViewCell.swift。
下一步,在 RestaurantTableViewCell 類里聲明下列 outlet 變量:

@IBOutlet var nameLabel: UILabel!
@IBOutlet var locationLabel: UILabel!
@IBOutlet var typelabel:UILabel!
@IBOutlet var thumnailImageView: UIImageView!

RestaurantTableViewCell 類為自定義單位各的數(shù)據(jù)模型服務(wù)。在單元格里,我們有4個屬性是可變的:

  • 縮略圖圖片視圖
  • 名字標簽
  • 位置標簽
  • 類型標簽
    數(shù)據(jù)模型儲存和提供單元格的值來顯示。它們都是必須的,用來在界面編輯器里連接響應(yīng)的用戶界面對象。通過 UI 對象來連接源代碼,我們可以改變 UI 對象的動態(tài)值。
    這是在 iOS 編程里很重要的一個概念。在 storyboard 里,你的 UI 和代碼是分開的。你在界面編輯器里創(chuàng)建 UI,然后在 Swift 里寫你的代碼。如果你要改變數(shù)值或者 UI 元素(如 label)的屬性,你必須給它們建立聯(lián)系,這樣你代碼里的對象可以獲得一個引用到storyboard 里定義的對象。在 Swift 里,你用@IBOutlet關(guān)鍵詞來表明一個類的屬性,那樣可以解除到界面構(gòu)建器(Interface Builder)。為了給 IBOutlet 關(guān)鍵字注釋屬性,我們叫它 outlets。
    所以在上面的代碼里,我們聲明了4個 outlets。每個 outlet都將聯(lián)系與它相關(guān)的 UI 對象。下圖描述了它們之間的關(guān)系。
QQ20151213-13@2x.png

@IBAction vs @IBOutlet

在 HelloWorld app里我們曾經(jīng)用@IBAction來表明動作的方法。@IBAction和@IBOutlet之間有什么區(qū)別?@IBOutlet 用來表示一個屬性,這個屬性與 storyboard 里的視圖對象連接。例如,如果 outlet 與一個按鈕相連,你可以用 outlet 來改變按鈕的顏色或者標題。另一方面,@IBAction 用來表明一個動作的方法,這個方法可以被確定的事件所引發(fā)。例如,當用戶點擊按鈕,它可以引發(fā)一個動作的方法來做一些事。

在我們建立CustomTableViewCell 類的 outlets 和界面構(gòu)建器里的 prototype cell 之間的聯(lián)系之前,我們必須先設(shè)置 custom class。

QQ20151213-14@2x.png

默認情況下,prototype cell 與默認的 UITableViewCell 類相連。為了用 custom class 分配 prototype,選擇 storyboard 里的單元格。在 Identifier inspector 里,設(shè)置 custom class 為 CustomTableViewCell。

建立聯(lián)系

接下來,我們建立 outlets 和在 prototype cell 里的 UI 對象之間的聯(lián)系。在界面構(gòu)建器里,右擊文檔大綱視圖里的 cell 來彈出 Outlets inspector。拖曳圓環(huán)(thumdnailImageView邊上)到prototype 單元格 UIImageView 對象(看下圖)。當你松開按鈕時,Xcode 會自動建立聯(lián)系。

QQ20151214-0@2x.png

為下面的 outlets重復(fù)上面的步驟:

  • locationLabel - 連接地址標簽單元格
  • nameLabel - 連接名字標簽單元格
  • typeLabel - 連接類型標簽單元格
    在你做完所有的連接之后,UI 應(yīng)該看起來像下圖一樣。
QQ20151214-1@2x.png

寫 table view controller 的代碼

最后,我們來到改變的最后一部分。在 RestaurantTableViewController 類里,我們依然使用 UITableViewCell(如默認單元格)來顯示內(nèi)容。我們需要修改一行代碼來使用自定義單元格。如果你觀察 tableView(_:cellForRowAtIndexPath:)方法現(xiàn)在的執(zhí)行。第二行代碼是:

let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, for IndexPath: indexPath)

我已經(jīng)在之前的章節(jié)解釋過 dequeueReusableCellWithIdentifier 方法的意思。它足夠靈活從隊列里返回任何單元格格式。默認情況下,它返回一個 UITableViewCell 類型的泛型單元格。為了使用 RestaurantTableViewCell 類,“轉(zhuǎn)換”dequeueReusableCellWithIdentfier 返回的對象到 RestaurantTableViewCell 是我們的責(zé)任。這個轉(zhuǎn)換過程被稱作向下類型轉(zhuǎn)換。在 Swift 里,我們使用 as!關(guān)鍵詞來執(zhí)行強制轉(zhuǎn)換。因此,把上面的代碼行改變?yōu)椋?/p>

let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! RestaurantTableViewCell

as!和as?

向下類型轉(zhuǎn)換允許你將一個類的值轉(zhuǎn)換到它的派生類。例如,RestaurantTableViewCell是一個 UITableViewCell 的子類。dequeueReusableCellWithIdentifier 方法總是返回一個 UITableViewCell 對象。如果用自定義單元格,這個對象可以被轉(zhuǎn)換成特定的單元格形式(如 RestaurantTableViewCell)。Swift1.2 之前,你僅僅能夠用“as”向下類型運算符。然而,有時對象不能轉(zhuǎn)換成制定的類型。因此,從 Swift1.2之后,Apple 介紹了另外2個運算符:as! 和 as?。如果你想當確定向下類型轉(zhuǎn)化能夠正確的執(zhí)行,使用“as!”來執(zhí)行轉(zhuǎn)換。一旦你不確定一種類型的值能轉(zhuǎn)換成另一種,使用“as?”來執(zhí)行一個可選的向下類型轉(zhuǎn)換。你需要執(zhí)行額外的檢查來看向下類型轉(zhuǎn)化是否成功。
我知道你已經(jīng)等不及來測試 app 了,但是我們需要改變更多的一些代碼行。下面這些代碼行設(shè)置餐廳名字和圖片的值:

// 配置單元格...
cell.textLabl?.text = restaurantNames[indexPath.row]
cell.imageView?.image = UIImage(named: restaurantImages[indexPath.row])

textLabel 和 imageView 都是 UITableViewCell 類的默認屬性。因為我們現(xiàn)在使用自己的 RestaurantTableViewCell,我們需要使用自定義類的屬性。把上面的代碼行改成這樣:

//配置單元格...
cell.namelabel.text = restaurantNames[indexPath.row]
cell.thumbnailImageView.image = UIImage(named: restaurantImages[indexPath.row])

現(xiàn)在你已經(jīng)準備好了。點擊 Run 按鈕來測試 app。你的 app 應(yīng)該看起來像下圖顯示的。試著旋轉(zhuǎn)模擬器。app在橫向情況下同樣可以工作。

QQ20151214-2@2x.png

與前一版的 app 相比這是一個巨大的進步。我們繼續(xù)把縮略圖變成圓形,讓它看起來更好。

圓形圖片

自從iOS7發(fā)布后,相比于方形圖片,iOS 更喜歡圓形圖片。你可以在內(nèi)置 app里找到圓形圖標或者圖片,如聯(lián)系人和電話。把所有的餐廳圖片變成圓形會更好嗎?你不需要 PS 來調(diào)整圖片。你需要的僅僅是兩行代碼。CALayer 類的實例支持UIKit 里的每個視圖(如UIView,UIImageView)。設(shè)計層(layer)對象來管理支持存儲視圖和處理與視圖相關(guān)的動畫。
layer 對象提供各種屬性,可以設(shè)置成控制圖像的可視化內(nèi)容例如:

  • 背景色
  • 邊界和邊界寬度
  • 陰影顏色,寬度,等等
  • 不透明度
  • 圓角半徑
    圓角半徑是我們用來畫圓角的屬性。Xcode 提供兩個方法來編輯 layer 屬性。你可以直接通過代碼更新它的屬性。這行代碼用來改變image view 的角度:

cell.thumbnailImageView.layer.cornerRadius = 30.0
cell.thumbnailImageView.clipsToBounds = true

一個更簡單的方法是通過界面構(gòu)建器來改變。首先,在 stack view 里選擇 image view。進入 Identifier inspector,點擊User Defined Runtime Attributes 左下角的 Add 按鈕(+),一個新的運行時屬性編輯器出現(xiàn)在編輯器中。雙擊在 Key Path 文件下的新屬性來為屬性編輯新的路徑。給 layer.cornerRadius 設(shè)置新的值然后點擊 Return 來確定。點擊 Type 屬性然后選擇 Number。最后,把值設(shè)置成30.把方形的圖片變成圓形的圖片,半徑設(shè)置成圖片高度的一半。這里,方形圖片的寬度是60,所以角度半徑設(shè)置成30.

QQ20151214-3@2x.png

當初始化 image view 時,運行時屬性將自動讀取成圓角。在圓形圖片正確工作之前還有一件事你必須配置。選擇 image view 然后進入 Attributes inspector。在 Drawing 部分里,使用 Clip Subview 選項。這會省略內(nèi)容成圓角。

QQ20151214-4@2x.png

現(xiàn)在編譯運行 app。UI 看起來更棒了對嗎?沒有寫一行代碼,我們把方形圖片變成了圓形。

QQ20151214-5@2x.png

你可以隨意改變角度值。試著把corner radius 變成10然后看看你會得到什么。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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