zoukankan      html  css  js  c++  java
  • 搭建微博编辑页面的表情键盘

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

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

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

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

  • 相关阅读:
    Codeforces Round #368 (Div. 2)D. Persistent Bookcase DFS
    POJ Sudoku 数独填数 DFS
    Memory
    UESTC 771 最大容积(前缀后缀和)
    【题解】P2916 [USACO08NOV]安慰奶牛Cheering up the Cow-C++
    Prim算法与Kruskal(没有代码)
    【题解】P1396 营救-C++
    【题解】Unit Fraction Partition-C++
    【题解】P2078 朋友-C++
    【题解】P1892 [BOI2003]团伙-C++
  • 原文地址:https://www.cnblogs.com/dsxniubility/p/4336210.html
Copyright © 2011-2022 走看看