用Swift实现表情发送

      苹果官方一直大力推行Swift,Swift的简洁跟高新能得到不少人的青睐,貌似Swift将要成为ios开发的主流。那么Swift跟OC有何不同呢,或者你用OC实现过不少炫酷的功能,但那些功能,你能用Swift实现吗?答案是肯定的,只要你稍微努力一下,我觉得,你肯定可以做到。 

      今天我分享一个Swift做的小案例,希望能给学习Swift带来一点点,一丢丢帮助。由于工作比较紧,所以,这个案例我会分两次发。

      首先创建一个Swift的项目,跟OC创建一样,只要把下图选为Swift即可

这里演示的纯代码的方式,所以我把Main.stourboard删除了,顺带要把Info.plist的Main删除,如下图:

要在AppDelegate.swift里面添加如下代码:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

window = UIWindow(frame: UIScreen.mainScreen().bounds)

let rootViewController = ViewController()

window?.rootViewController = rootViewController

window?.makeKeyAndVisible()

return true

}

这样就可以加载到ViewController了。因为我们都是点聊天的导航栏跳出键盘,再点击表情,发送表情的。所以,我们需要在view的最下面,添加一个toolBar。因为主要实现表情发送,所以,我只建立了一个UIBarButton。然后点击该UIBarButton,就可以弹出选择表情的collectionCell,可以滑动可以选择。现在送上全部代码。只建立了三个文件:


ViewController的代码如下:


import UIKit

class ViewController: UIViewController {

/// 懒加载一个文本输入框

lazy var textView: UITextView = UITextView()

/// 模拟聊天,创建表情工具栏

lazy var toolBar: UIToolbar = UIToolbar()

/// 是否添加动画

var isShowAnimation: Bool = true

/// 表情键盘

lazy var emotionKeyboard: EmotionKeyboard = EmotionKeyboard(frame: CGRectMake(0,0,UIScreen.mainScreen().bounds.width,271))

/// 是否是自定义键盘

var isEmotionKeyboard: Bool = false

override func viewDidLoad() {

super.viewDidLoad()

view.backgroundColor = UIColor.whiteColor()

setUpUI()

//监听系统的键盘弹出

NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChanged:", name: UIKeyboardWillChangeFrameNotification, object: nil)

}

deinit {

NSNotificationCenter.defaultCenter().removeObserver(self)

}

}

extension ViewController {

func setUpUI() {

setUpUIToolBar()

setUpTextView()

}

func setUpTextView() {

view.addSubview(textView)

textView.font = UIFont.systemFontOfSize(14)

textView.backgroundColor = UIColor.greenColor()

textView.delegate = self

textView.snp_makeConstraints { (make) -> Void in

make.top.equalTo(view).offset(20)

make.left.equalTo(view)

make.right.equalTo(view)

make.bottom.equalTo(toolBar.snp_top)

}

}

func setUpUIToolBar() {

view.addSubview(toolBar)

/// 创建表情按钮

let button = UIButton()

button.setImage(UIImage(named: "smile_normal"), forState: .Normal)

button.setImage(UIImage(named: "smile_highlighted"), forState: .Highlighted)

/// 添加点击事件

button.addTarget(self, action: "emotionKeyboard:", forControlEvents: .TouchUpInside)

// 不少新手会容易忽略这一步,少了它,表情按钮就不显示了

button.sizeToFit()

let item = UIBarButtonItem(customView: button)

toolBar.items = [UIBarButtonItem]()

toolBar.items?.append(item)

toolBar.backgroundColor = UIColor.redColor()

toolBar.snp_makeConstraints { (make) -> Void in

make.height.equalTo(44)

make.bottom.equalTo(view)

make.left.equalTo(view)

make.right.equalTo(view)

}

}

}

extension ViewController: UITextViewDelegate {

}

/// 系统键盘弹出时,读取系统键盘的origin.y的值,以便自定义的toolBar随着系统弹起

extension ViewController {

@objc private func keyboardWillChanged(notification: NSNotification) {

if isShowAnimation == true {

//弹出键盘时,Y的偏移量

let keyboardOriginY = (notification.userInfo!["UIKeyboardFrameEndUserInfoKey"] as! NSValue).CGRectValue().origin.y

let duration = notification.userInfo!["UIKeyboardAnimationDurationUserInfoKey"] as! NSTimeInterval

let offset = keyboardOriginY - view.bounds.size.height

toolBar.snp_updateConstraints(closure: { (make) -> Void in

make.bottom.equalTo(view).offset(offset)

})

UIView.animateWithDuration(duration, animations: { () -> Void in

self.view.layoutIfNeeded()

})

}

}

/// 实现表情按钮的点击事件,切换系统键盘跟自定义键盘

@objc private func emotionKeyboard(button: UIButton) {

// 收起系统键盘

isShowAnimation = false

textView.resignFirstResponder()

isShowAnimation = true

if isEmotionKeyboard == false {

textView.inputView = emotionKeyboard

isEmotionKeyboard = true

}else {

// 切换回系统键盘

textView.inputView = nil

isEmotionKeyboard = false

}

textView.becomeFirstResponder()

}

}

自定义的表情键盘EmotionKeyboard的代码如下

import UIKit

private let cellIdentifier = "cellIdentifier"

let labelTag = 9527

private class EmotionCellLayout: UICollectionViewFlowLayout {

override func prepareLayout() {

super.prepareLayout()

minimumInteritemSpacing = 0

minimumLineSpacing = 0

scrollDirection = .Horizontal

itemSize = CGSizeMake(UIScreen.mainScreen().bounds.width, 234)

}

}

class EmotionKeyboard: UIView {

/// 懒加载存放表情的CollectionView

lazy var emotionCollectionView: UICollectionView = {

let collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: EmotionCellLayout())

collectionView.delegate = self

collectionView.dataSource = self

collectionView.pagingEnabled = true

collectionView.showsHorizontalScrollIndicator = false

collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: cellIdentifier)

collectionView.bounces = false

return collectionView

}()

/// 懒加载跳转表情类型的导航条

lazy var toolBar: EmotionToolBar = {

let toolBar = EmotionToolBar(frame: CGRectZero)

toolBar.toolBarDelegate = self

return toolBar

}()

override init(frame: CGRect) {

super.init(frame: frame)

setUpUI()

}

required init?(coder aDecoder: NSCoder) {

fatalError("init(coder:) has not been implemented")

}

}

extension EmotionKeyboard {

func setUpUI() {

/// 添加,设置,自动布局子控件

addSubview(emotionCollectionView)

addSubview(toolBar)

backgroundColor = UIColor.orangeColor()

emotionCollectionView.snp_makeConstraints { (make) -> Void in

make.left.equalTo(self)

make.right.equalTo(self)

make.top.equalTo(self)

make.height.equalTo(234)

//make.bottom.equalTo(self.snp_bottom).offset(-42)

}

toolBar.snp_makeConstraints { (make) -> Void in

make.top.equalTo(emotionCollectionView.snp_bottom)

make.left.equalTo(self)

make.right.equalTo(self)

make.height.equalTo(37)

// make.bottom.equalTo(self.snp_bottom).offset(-50)

}

print("=============\(self.bounds)")

}

}

extension EmotionKeyboard: UICollectionViewDataSource {

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {

return 4

}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

return 4

}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellIdentifier, forIndexPath: indexPath)

cell.contentView.viewWithTag(labelTag)?.removeFromSuperview()

let titleLabel = UILabel(frame: CGRectMake(20,20,300,100))

titleLabel.tag = labelTag

titleLabel.text = "我是第\(indexPath.section)组\n我是第\(indexPath.item)行"

titleLabel.numberOfLines = 0

titleLabel.font = UIFont.systemFontOfSize(25)

titleLabel.textAlignment = .Left

titleLabel.textColor = UIColor.blackColor()

cell.contentView.addSubview(titleLabel)

cell.backgroundColor = self.randomColor()

return cell

}

}

extension EmotionKeyboard: UICollectionViewDelegate {

func scrollViewDidScroll(scrollView: UIScrollView) {

let offsetX = scrollView.contentOffset.x

var indexPath = NSIndexPath(forItem: 0, inSection: 0)

let cells = emotionCollectionView.visibleCells()

if cells.count > 1 {

//第一个cell

let firstCell = cells[0]

let firstCellIndex = emotionCollectionView.indexPathForCell(firstCell)

let firstCellOriginX = firstCell.frame.origin.x

let firstCellRegion = abs(offsetX - firstCellOriginX)

//第二个cell

let nextCell = cells[1]

let nextCellIndex = emotionCollectionView.indexPathForCell(nextCell)

let nextCellOriginX = nextCell.frame.origin.x

let nextCellRegion = abs(offsetX - nextCellOriginX)

//判断那个cell显示的区域大,就用那个cell的section

indexPath = (firstCellRegion > nextCellRegion ? nextCellIndex : firstCellIndex)!

toolBar.selectedIndex = indexPath.section

}

}

}

extension EmotionKeyboard: EmotionToolBarDelegate {

func changEmotionKeyboardType(buttonIndex: Int) {

let indexPath = NSIndexPath(forItem: 0, inSection: buttonIndex)

emotionCollectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredHorizontally, animated: false)

}

}

extension EmotionKeyboard {

func randomColor() -> UIColor {

let r = CGFloat(random() % 255)

let g = CGFloat(random() % 255)

let b = CGFloat(random() % 255)

let color = UIColor(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: 1.0)

return color

}

}

自定义的EmotionToolBar的代码如下:

import UIKit

protocol EmotionToolBarDelegate: NSObjectProtocol {

func changEmotionKeyboardType(buttonIndex: Int)

}

class EmotionToolBar: UIStackView {

weak var toolBarDelegate: EmotionToolBarDelegate?

var selectedButton: UIButton?

var selectedIndex: Int = 0 {

didSet {

selectedButton?.selected = false

let button = viewWithTag(selectedIndex+labelTag) as! UIButton

button.selected = true

print(selectedIndex)

selectedButton = button

}

}

override init(frame: CGRect) {

super.init(frame: frame)

axis = .Horizontal

distribution = .FillEqually

setUpUI()

}

required init?(coder aDecoder: NSCoder) {

fatalError("init(coder:) has not been implemented")

}

}

extension EmotionToolBar {

func setUpUI() {

///暂时先创建四个表情button

createToolBarButton("最近", tag: 0)

createToolBarButton("A号", tag: 1)

createToolBarButton("B号", tag: 2)

createToolBarButton("C号", tag: 3)

}

func createToolBarButton (title: String, tag: Int ) {

let button = UIButton()

button.setTitle(title, forState: .Normal)

button.backgroundImageForState(.Normal)

button.setTitleColor(UIColor.whiteColor(), forState: .Normal)

button.setTitleColor(UIColor.blackColor(), forState: .Selected)

button.addTarget(self, action: "changEmotionType:", forControlEvents: .TouchUpInside)

button.tag = tag+labelTag

addArrangedSubview(button)

if tag == 0  {

button.selected = true

selectedButton = button

}

}

}

extension EmotionToolBar {

@objc private func changEmotionType(button:UIButton) {

selectedButton?.selected = false

button.selected = true

selectedButton = button

toolBarDelegate?.changEmotionKeyboardType(button.tag-labelTag)

}

}

这样实现表情栏的滚动与选择了。效果如下图:


下一篇,会在collectionCell里面添加表情,后续表情的添加,请留意后续更新。

现在代码里饱含了几种属性的定义,方法的创建,分类的添加,协议的定义,方法的重写与调用,基本数据类型,数组,字典的定义,希望看客们好好理解一下。细心的看客们肯定已经发现,代码里有很多“?”与“!”,这里涉及到可选值的问题,会在后面作详细的解析。

 最后 ,谢谢光临。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容