--

利用 NSTextAttachment 製作包含圖片的字串-喜好探測機

這篇分享主要是用來跟大家說如何在Label中放入一些圖片,可以利用這個方式來做一些應用,例如用圖像表達一些字義,那麼我們先來看一下畫面。

常常可以看到一些軟體用兩個按鍵來表達喜歡與不喜歡,透過問題或圖片來讓使用者做選擇,並依據使用者一步一步的選擇最後給出答案,舉凡appstore上的交友軟體?!或一些心理測驗等一些需要闖關的方式,都可以利用這種方式來實現。

這個應用不用寫太多程式,就可以完成了!

參考教學

找素材

首先我們要找一些表情圖案,因為沒有背景,使用上比較方便,不需要考慮太多,如我們手機輸入時可以採用的表情符號emoji。

這次我所採用的素材網站只需要註冊,就可以免費下載到一些常用的emoji,大家可以參考看看。

下載解壓縮後,可以看到有不同大小和格式的emoji,所以就依照主題來挑選個幾張來做這個喜好探測機。

下載後可看到許多表情素材,本文是採用png/128

將圖片放入Xcode的Assets.xcassets

將圖片素材匯入至Xcode

main.storyboard建置畫面

透過拖拉方式將畫面建立完成

這個畫面應用了UIButton、LabelX2,一個Label用來顯示標題,一個用來顯示待會問題顯示的區塊,兩顆按鈕則是套上了一個like和unlink的圖案。

建立ViewController Class

這個畫面因為是問使用者問題,所以我沒有採用預設提供的ViewController Class,所以這步驟看個人。

新增UIViewController Class
指定main.storyboard的畫面 Class為我們新增的Class

建立IBOutlet

因為我們即將在程式中使用到Label來顯示問題,所以我們要將quesdtionLabel與viewController建立連結關係。

要問的問題很多,所以需要靠陣列和物件來儲存問題

新增一個swift file,並命名為question,也就是新增一個問題,需要遵循我所定義的資料架構,宣告了imageAttributeStr來存放中文字義,用imageSrc來定義圖片來源名稱,最後imageObj是用來宣告未來要放入Label所需要的物件格式-NSTextAttachment。

關於NSTextAttachment的解釋,要從NSMutableAttributedString開始說起:

目前只有 NSAttributedString 可以在文字區塊中加上圖片,普遍我們所認識的 String 無法,有這個物件,我們變成可以在文字的任何位置上放入圖片,有點類似Office Word中的文繞圖感覺。

init的func則是在建立這個物件時,會執行的func,有點類似我們所認識的建構子,而兩個參數則代表是物件初始化所需要的參數。

getNS則是回傳我們這次所需要的物件NSTextAttachment,利用方法image可以指定一個UIImage。

建立圖片物件

let questionObj = question(imageAttributeStr:”釣魚”,imageSrc:”fishing-pole”)

由於很多張圖片,為了能夠一個一個呈現給使用者,我們宣告了陣列來存放這些圖片。

將圖片顯示於畫面上

由於圖片顯示與切換是畫面載入時和點選like和unlike都要做的事情,所以為了方便維護起見,我們宣告了func來做圖片的顯示與處理。

signAsk:問號的圖示

//將問號的圖示指定其大小與位置

signAsk.getNS().bounds = CGRect(x: 0, y: -5, width: 30, height: 30)

開始使用NSMutableAttributedString

//宣告

let content = NSMutableAttributedString(string: “你喜歡”)

//將NSMutableAttributedString指定為questionLabel顯示內容

questionLabel.attributedText = content

//指定一個itemIndex來記錄目前顯示到第幾個,起始值為0

var itemIndex = 0

//並且判斷其陣列的圖片數量大於itemIndex

if questionAry.count > itemIndex{…}

將圖片加入content (NSMutableAttributedString)

//取得圖片NSTextAttachment物件

let questionOBj = questionAry[itemIndex]

//將上述物件記錄下來,是為了在按下按鈕時可以得知他點的物件是哪一個

currentImage = questionOBj

//使用append的方是加入NSAttributedString

content.append(NSAttributedString(attachment:questionOBj.getNS()))

//結束問題

content.append(NSAttributedString(string: “嗎”))

//加入問號

content.append(NSAttributedString(attachment:signAsk.getNS()))

//指定其content內容為label顯示內容

questionLabel.attributedText = content

若已經玩完了,代表itemIndex已經大於圖片數量時,顯示結果

//改變label文字大小

questionLabel.font = questionLabel.font.withSize(20)

//改變label顯示行數

questionLabel.numberOfLines = 20

//重新組出label內容,計算likeItem有多少物件,並append起來

let content = NSMutableAttributedString(string: “統計結果\n\n”)

for likeObj in likeItem{

//改變圖片物件內的表情符號大小與顯示位置

likeObj.getNS().bounds = CGRect(x: 0, y: -5, width: 20, height: 20)

content.append(NSAttributedString(string:”你喜歡”))

content.append(NSAttributedString(string:likeObj.imageAttributeStr))

content.append(NSAttributedString(attachment:likeObj.getNS()))

content.append(NSAttributedString(string: “\n”))

questionLabel.attributedText = content

}

//重新組出label內容,計算unlikeItem有多少物件,並append起來

for unlikeObj in unlikeItem{

//改變圖片物件內的表情符號大小與顯示位置

unlikeObj.getNS().bounds = CGRect(x: 0, y: -5, width: 20, height: 20)

content.append(NSAttributedString(string:”你不喜歡”))

content.append(NSAttributedString(string:unlikeObj.imageAttributeStr))

content.append(NSAttributedString(attachment:unlikeObj.getNS()))

content.append(NSAttributedString(string: “\n”))

questionLabel.attributedText = content

}

按鈕部分的操作

按鈕按下時,我們必須記錄使用者喜歡的這個物件是什麼,所以顯示時就已經將currentImage存放了目前畫面顯示的這個物件,所以也是宣告一個likeItem的陣列來存放使用者喜歡的物件,相反,不喜歡的做法也是,因為這個一個二選一,也就是只有喜歡與不喜歡兩種選擇!

於是我們需要將按鈕建立IBAction!

程式中我們就是判斷是否還有下一個問題,若有則是將itemIndex + 1且繼續呼叫showQuestion,同時記錄使用者喜歡這個運動。

成果分享

Github

--

--