搭建微博編輯頁面的表情鍵盤

weixin_33831673發表於2015-03-18

當下髮狀態和發評論已經漸漸成為不少軟體的必備功能,這兩者功能基本類似。但是有普通編輯和高階編輯之分,普通的評論只能發文字,一旦可以傳送表情(非emoji表情)就需要用到圖文混排。並且系統只能提供emoji表情,要用到其他自定義表情需要自行新增表情鍵盤。

因為表情鍵盤和圖文混排寫在一起太長了分為兩期。本期以新浪微博的發微博頁面為例,整理新增表情鍵盤的步驟,下期會總結自己在編寫圖文混排中遇到的種種問題和解決方案。基本的頁面類似於這樣,有部分細節沒做不過也無關大雅了。編寫的語言用的是swift

如果你不是在董鉑然部落格園看到本文,請點選檢視原文

我表情鍵盤的做法是,在釋出微博控制器頁面底部新增一個toolbar 然後底部的約束拖一根線到控制器裡,可以根據監聽鍵盤的彈出動態修改。

下面的表情鍵盤是新建一個xib或者storyboard 建一個普通控制器,上面放collectionView,下面放一個view或者toolbar顯示錶情的種類。

collectionViewCell內部放一個imageView 和 一個Label。因為emoji表情是需要用label顯示的。

下圖是兩個設計介面

左邊的撰寫微博控制器和上面的效果截圖有些不同。因為設定了導航欄的顏色主題是黃色。裡面灰色的placeholder請釋出微博是用程式碼新增的設定為textView的子控制元件。上面的設定可以自行腦補在此不作過多贅述了,本文主要是總結表情鍵盤和圖文混排

右邊的表情鍵盤控制器也是可以清楚地看到cell裡有imgView和label

這裡記得要在撰寫微博控制器裡設定,點選小圓臉就設定第一響應者,並且把彈出鍵盤的inputView設定成我們自定義的這個表情鍵盤控制器。

然後就是裡面cell的流水佈局,把控制器裡的佈局拖到控制器中修改

 override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        setupLayout()
    }
    func setupLayout(){
        
        let row:CGFloat = 3
        let col:CGFloat = 7
        let m:CGFloat = 10
        
        let screenSize = self.collectionView.bounds.size
        let w = (screenSize.width - (col + 1) * m) / col
        
        layout.itemSize = CGSizeMake(w, w)
        layout.minimumInteritemSpacing = m
        layout.minimumLineSpacing = m
        
        /// 每一組之間的邊距
        layout.sectionInset = UIEdgeInsetsMake(m, m, m, m)
        
        layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
        
        collectionView.pagingEnabled = true
    }

 之所以寫在ViewDidLayoutSubViews方法中,是為了等前面的佈局完全載入好。

佈局完畢後應該就是可以看到此效果。

然後就是載入表情圖片,把表情圖片依次填到這些方框中

表情圖片的載入方法:

1.下載個新浪微博的ipa解壓,在裡面能夠找到所有的表情包都是裝在一個emticons資料夾裡

2.資料夾中有個emoticons.plist檔案,裡面是一個陣列,裡面包含四個字典分別是四種表情的各項引數。和四個資料夾裡裝著四種表情

3.每一種表情的資料夾裡還有一個info.plist檔案,這個檔案裡是個字典包含幾個自己表情引數和一個陣列,裡面裝的是本類別的所有表情

4.這裡面的引數目測應該就能看懂分別是幹什麼的 如圖 

 

5.這裡載入表情圖片時要注意不能直接使用第三方框架字典轉模型,因為字典轉模型之後的模型陣列內值都是連續的,但是每頁的右下角還需要新增一個刪除按鈕,所以產生矛盾

6.所以載入表情圖片的基本思路是,手寫方法一層一層載入,先把emoticons.plist轉模型,再通過裡面的path可以取到每一個info.plist再轉模型。

7.然後info.plist中有一個陣列裡裝著所有的表情,每一個表情又是一個字典再給他轉模型。並設定個模型陣列

8.前面設定collectionView的佈局是3*7,這裡就設定collectionView的Section每組21個,除去一個刪除按鈕正好是每頁20個表情。

9.把模型和模型陣列整理好,該addObject的就addObject。

 

最後在資料來源方法中載入:

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        /// 返回有幾種表情
        return emoticonSection?.count ?? 0
    }
    
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        /// 返回每個種類中的表情數量
        return emoticonSection![section].emoticons.count
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("EmoticonsCell", forIndexPath: indexPath) as! EmoticonCell
        /// 屬性賦值
        cell.emoticon = emoticonSection![indexPath.section].emoticons[indexPath.item]
        
        return cell
    }

 至於cellForItem裡的屬性賦值,是在自定義的EmoticonCell裡設定didSet判斷模型的種類(是否是emoji表情)再完成資料分發

/// 自定義表情cell
class EmoticonCell: UICollectionViewCell {
    @IBOutlet weak var iconView: UIImageView!
    @IBOutlet weak var emojiLabel: UILabel!
    
    var emoticon: Emoticon? {
        /// 賦值完成後呼叫
        didSet {
            if let path = emoticon?.imagePath {
                iconView.image = UIImage(contentsOfFile: path)
            } else {
                iconView.image = nil
            }
            
            emojiLabel.text = emoticon?.emoji
            
            // 是否是刪除按鈕
            if emoticon!.isDeleteButton {
                iconView.image = UIImage(named: "compose_emotion_delete_highlighted")
            }
        }
    }
}

 之後表情鍵盤就可以如圖的顯示了。

 

然後就是監聽每個按鈕表情的點選事件。這裡需要用到代理。

定義一個協議協議裡有個方法點選時把自己(表情控制器)和點中的表情模型傳過去

再在collectioView的代理方法中設定didSelected觸發

協議:

protocol EmoticonsViewControllerDelegate: NSObjectProtocol {
    /// 選中了某一個表情
    func emoticonsViewControllerDidSelectEmoticon(vc:SXEmoticonsViewController, emoticon: Emoticon)
}

 代理方法:

    /// 根據 indexPath 返回表情資料
    func emoticon(indexPath: NSIndexPath) -> Emoticon {
        return emoticonSection![indexPath.section].emoticons[indexPath.item]
    }
    
    /// cell 被選中
    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        // 使用 ? 不需要判斷代理是否實現方法
        delegate?.emoticonsViewControllerDidSelectEmoticon(self, emoticon: emoticon(indexPath))
    }

 

在撰寫微博控制器裡,接收到資料模型後能列印出來就證明前面的表情鍵盤都做好了。

如果你不是在董鉑然部落格園看到本文,請點選檢視原文

正在整理圖文混排,有興趣的可以關注

相關文章