WeiChat项目总结

该项目Demo是模仿微信的好友聊天列表Demo

首先看一下当前的demo实现的功能以及效果图:


WeiChat.gif

从功能效果上面来看,实现的功能点主要有一下几点:
1 启动页轮播图
2 登陆页面数据信息验证以及点击事件
3 好友列表展示页
4 聊天页面
4.1 消息页面的布局展示效果,
4.2 消息气泡的拉伸效果,
4.3 输入框的自动化布局效果,
4.4 键盘弹出后的动态效果,
4.5 消息发出后消息页面的动态效果。

针对上面不能的功能点进行分析和开发

1 首页启动轮播图思想就是检查当前系统是否为第一次安装该软件或者当前的版本号与系统存得版本号是否一致。

// Override point for customization after application launch.
        // 得到当前应用的版本号
        let infoDictionary = NSBundle.mainBundle().infoDictionary
        let currentAppVersion = infoDictionary!["CFBundleShortVersionString"] as! String
        //取出之前保存的版本号
        let userDefaults = NSUserDefaults.standardUserDefaults()
        let appVersion = userDefaults.stringForKey("appVersion")
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        
        // 如果appVersion为nil说明是第一次启动;如果appVersion不等于currentAppVersion说明是更新的图片
  if appVersion == nil || appVersion != currentAppVersion {
            //将用户阅读引导信息存储下来
            userDefaults.setValue(currentAppVersion, forKey: "appVersion")
            
            let guideViewController = storyboard.instantiateViewControllerWithIdentifier("GuideViewController") as! GuideViewController
            self.window?.rootViewController = guideViewController
        }

轮播图的实现方式就更加简单了,设计思想在当前的View上层平铺一个scrollView视图(该视图只能左右滑动),视图的长是View的N倍,这里的N表示我们轮播图个数,并且加入pageController进行位置定位控制。

        let frame = self.view.bounds     
        scrollView = UIScrollView(frame: frame)
        // default NO. if YES, stop on multiples of view bounds
        scrollView.pagingEnabled = true
        // default YES. show indicator while we are tracking. fades out after tracking
        //Horizontal水平方向上的平移标尺
        //Vertical垂直方向上的平移标尺
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        // 跟上面的标示一致的,点击放回顶部
        scrollView.scrollsToTop = false
        //A Boolean value that controls whether the scroll view bounces past the edge of content and back again
        //回弹的动态效果
        scrollView.bounces = false
        //The point at which the origin of the content view is offset from the origin of the scroll view.
        //The default value is CGPointZero.
        //相当于偏移量
        scrollView.contentOffset = CGPointZero
        //将scrollview的contentSize设为屏幕宽度的3倍
        scrollView.contentSize = CGSize(width: frame.size.width * CGFloat(numOfPages), height: frame.size.height)
        scrollView.delegate = self
        for index in 0 ..< numOfPages {
            let imageView = UIImageView(image: UIImage(named: "famliy\(index + 1)"))
            imageView.frame = CGRect(x: frame.size.width * CGFloat(index), y: 0, width: frame.size.width, height: frame.size.height)
            scrollView.addSubview(imageView)
        }
        self.view.insertSubview(scrollView, atIndex: 0)

其中还有一个就是按钮的设计思想就是在没有显示到最后一页时候,button都是隐藏的并且是disabled的状态。只有在滑动到最后一页的情况下菜恢复它的透明度。
2 好友列表以及消息气泡设计思想:重新设计UItableViewCell结构,可以根据当前的需求重新定义一个公用的UItableViewCell来满足我们。

class FriendCell: UITableViewCell {
    var cellBackgroundView: UIView
    var avatar: UIImageView
    var nameLabel: UILabel
    //设计cell的元素体
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        self.cellBackgroundView = UIView(frame: CGRect(x: 0, y: 1, width: UIScreen.mainScreen().bounds.width, height: 55))
class MessageCell: UITableViewCell {
    var avatar: UIImageView
    var messageLabel: UILabel
    var messageBackground: UIImageView
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        self.avatar = UIImageView()
        self.messageLabel = UILabel()
        self.messageBackground = UIImageView()

再设计Message气泡页面的效果时,需要注意一点就是message要随着当前文字的多少进行调整行宽间距等。
首先

class func heightForCell(message:Message) -> CGFloat {
        let screanRect = UIScreen.mainScreen().bounds
        //获取该文字在限定宽的情况下,高度是多少,然后与我们当前的cell高度进行对比,并且更新avatarSize.height值。
        let labelSize: CGSize = UILabel.sizeOfString(message.message, font: UIFont.systemFontOfSize(16), maxWidth: screanRect.width - 10 - 20 - avatarSize.width * 2)
        if labelSize.height < avatarSize.height + 10{
            return avatarSize.height + 10
        }else{
            return labelSize.height + 5
        }
    }

这里面还有一个地方需要重视就是在我们直接使用UITableViewCell的时候它的cell一些背景色以及它其中一些元素的颜色很难调整,那么需要我们在代码中直接去控制。之前的Uber项目中就是直接使用的UITableViewCell原生态的cell,可是里面的元素的颜色确实浪费了我不少的时间。解决办法就是在代码中逐个进行控制。
3 现在就剩下TextField自适应高度的问题。TextField不支持多行,因此需要使用UITextView这个控件来做
继续调整TextView自适应高度的问题
1 通过调试,以及对布局的计算,大致知道该如何去设置这个高度自动变换的问题了,就是通过NSNotificationCenter获取到TextView的变化,然后随时进行监控。

NSNotificationCenter.defaultCenter().addObserver(self, selector: "textViewFrameWillChange:", name: UITextViewTextDidChangeNotification, object: nil)

2 通过自己布局的方式发现,非常的复杂(每次需要对里面所有的控件进行配置才行),不方便使用,因此需要使用第三方控件来进行关联绑定

if height > textHeigth{
            UIView.animateWithDuration(0.3, animations: { () -> Void in
                let textFieldFrame = self.inputToolbar.frame
                print(textFieldFrame.origin.y)
                self.inputToolbar.frame = CGRectMake(0, textFieldFrame.origin.y - 10 , UIScreen.mainScreen().bounds.width, textFieldFrame.height + 10)
                self.inputToolbar.backgroundImageView.frame = CGRectMake(0, 0, self.inputToolbar.frame.width, self.inputToolbar.frame.height + 10)
                self.inputToolbar.textFieldBackground.frame = CGRectMake(44, 0, UIScreen.mainScreen().bounds.width - 34 - 10 - 34 - 10, self.inputToolbar.frame.height + 5)
                self.inputToolbar.textField.frame = CGRectMake(44, 0, self.inputToolbar.textFieldBackground.frame.width, self.inputToolbar.frame.height + 5)
                }) { (Bool) -> Void in
                    print(true)
            }

3 还有就是之前用的TextField输入框,然后点击return后会返回提交状态,但是如果使用了TextView作为输入框时,就需要使用这个方法func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool进行实时监控,他是针对输入框中的每一个单词进行对比的。

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
        if text == "\n" {
            self.onLeftBtnTapped(self.rightBtn)
            return false
        }else{
            return true
        }       
    }

4 这里设计一个工具类主要作用是为了辅助调整布局的。
boundingRectWithSize根据当前一段输入的文字的特征来获取到它的size属性。从而能够判断出这个文字的在限定长度的情况下,它的高度是多少。

extension UIImage{
    //拉伸图片的方法
    class func resizableImage(name: String) -> UIImage {
        let image = UIImage(named: name)!        
        let top: CGFloat = image.size.height * 0.6
        let bottom: CGFloat = image.size.height * 0.5
        let lAndr: CGFloat = image.size.height * 0.5
        return image.resizableImageWithCapInsets(UIEdgeInsets(top: top, left: lAndr, bottom: bottom, right: lAndr))
    }
}
extension UILabel{
    //主要是获取输入信息的高度
    class func sizeOfString(string: NSString,font: UIFont,maxWidth:CGFloat) ->CGSize {
        //boundingRectWithSize()方法
        //需要自己去了解,了解
        let size: CGSize = string.boundingRectWithSize(CGSize(width: maxWidth, height: 999), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil).size
        return CGSize(width: size.width + 15, height: size.height + 20)
    }
}

5 键盘弹出的动画效果设计思想:添加键盘监听方法,获取到键盘的运动时间,曲线,间隔等数据,再将输入框按照这种方式来做同样的动作即可。如果你的键盘上面的组件不是Autolayer自动布局的(依赖关系)的,那么就需要你取调整每一个组建的动作会很复杂和麻烦,当然我就是后者,这里没有用到SnapKit,所以很麻烦啊,这里就不贴出来丢人了。

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 青春是安静享受,或是欢笑,或是奔跑,或是拍照。公园闺蜜照,给您不一样色彩,不一样约拍,记录真实自己。多年后翻开想起...
    摄影师才才阅读 228评论 0 0