你的位置:首页 > 操作系统

[操作系统]浅析微博编辑页面的表情键盘


当下发状态和发评论已经渐渐成为不少软件的必备功能,这两者功能基本类似。但是有普通编辑和高级编辑之分,普通的评论只能发文本,一旦可以发送表情(非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表情)再完成数据分发

/// 自定义表情cellclass 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))  }

 

在撰写微博控制器里,接收到数据模型后能打印出来就证明前面的表情键盘都做好了。

如果你不是在董铂然博客园看到本文,请点击查看原文。

正在整理图文混排,有兴趣的可以关注