Swift 3 cell展开/闭合动画小示例

先看示例图

demo.gif

提前声明:这个demo是仿照之前某个人用Objective-C写的示例,点击圆圈手指效果是用的一个第三方,可在demo中查看

核心技巧:

  • 灰色文字点击变成黑色,并且cell文字展开: cell上添加两个一模一样的label,一个显示灰色,一个显示黑色,点击刷新tableView,用UIView动画,使一个label的alpha为1,一个label的alpha为0

由于没有复杂逻辑,直接贴代码了

1.控制器

import UIKit
class ViewController: UIViewController {
    
    var modelArray : [DXCellModel] = []
    lazy var tableView: UITableView = {
       let table = UITableView.init(frame: CGRect.init(x: 0, y: 20, width: kScreenW, height: kScreenH-20), style: .plain)
        table.sectionHeaderHeight = 0
        table.sectionFooterHeight = 0
        table.dataSource = self
        table.delegate = self
        table.separatorStyle = .none
        return table
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let strings = ["AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of the Foundation URL Loading System, extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac. Choose AFNetworking for your next project, or migrate over your existing projects—you'll be happy you did!",
        
        "欢迎使用 iPhone SE,迄今最高性能的 4 英寸 iPhone。在打造这款手机时,我们在深得人心的 4 英寸设计基础上,从里到外重新构想。它所采用的 A9 芯片,正是在 iPhone 6s 上使用的先进芯片。1200 万像素的摄像头能拍出令人叹为观止的精彩照片和 4K 视频,而 Live Photos 则会让你的照片栩栩如生。这一切,成就了一款外形小巧却异常强大的 iPhone。",
        
        "★タクシー代がなかったので、家まで歩いて帰った。★もし事故が発生した场所、このレバーを引いて列车を止めてください。(丁)为了清楚地表示出一个短语或句节,其后须标逗号。如:★この薬を、夜寝る前に一度、朝起きてからもう一度、饮んでください。★私は、空を飞ぶ鸟のように、自由に生きて行きたいと思った。*****为了清楚地表示词语与词语间的关系,须标逗号。标注位置不同,有时会使句子的意思发生变化。如:★その人は大きな音にびっくりして、横から飞び出した子供にぶつかった。★その人は、大きな音にびっくりして横から飞び出した子供に、ぶつかった。",
        
        "Two roads diverged in a yellow wood, And sorry I could not travel both And be one traveler, long I stood And looked down one as far as I could To where it bent in the undergrowth; Then took the other, as just as fair, And having perhaps the better claim, Because it was grassy and wanted wear; Though as for that the passing there Had worn them really about the same, And both that morning equally lay In leaves no step had trodden black. Oh, I kept the first for another day! Yet knowing how way leads on to way, I doubted if I should ever come back. I shall be telling this with a sigh Somewhere ages and ages hence: Two roads diverged in a wood, and I- I took the one less traveled by, And that has made all the difference. ",
        
        "Star \"https://github.com/boai\" :)",
        "AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of the Foundation URL Loading System, extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac. Choose AFNetworking for your next project, or migrate over your existing projects—you'll be happy you did!",
        
        "欢迎使用 iPhone SE,迄今最高性能的 4 英寸 iPhone。在打造这款手机时,我们在深得人心的 4 英寸设计基础上,从里到外重新构想。它所采用的 A9 芯片,正是在 iPhone 6s 上使用的先进芯片。1200 万像素的摄像头能拍出令人叹为观止的精彩照片和 4K 视频,而 Live Photos 则会让你的照片栩栩如生。这一切,成就了一款外形小巧却异常强大的 iPhone。",
        
        "★タクシー代がなかったので、家まで歩いて帰った。★もし事故が発生した场所、このレバーを引いて列车を止めてください。(丁)为了清楚地表示出一个短语或句节,其后须标逗号。如:★この薬を、夜寝る前に一度、朝起きてからもう一度、饮んでください。★私は、空を飞ぶ鸟のように、自由に生きて行きたいと思った。*****为了清楚地表示词语与词语间的关系,须标逗号。标注位置不同,有时会使句子的意思发生变化。如:★その人は大きな音にびっくりして、横から飞び出した子供にぶつかった。★その人は、大きな音にびっくりして横から飞び出した子供に、ぶつかった。",
        
        "Two roads diverged in a yellow wood, And sorry I could not travel both And be one traveler, long I stood And looked down one as far as I could To where it bent in the undergrowth; Then took the other, as just as fair, And having perhaps the better claim, Because it was grassy and wanted wear; Though as for that the passing there Had worn them really about the same, And both that morning equally lay In leaves no step had trodden black. Oh, I kept the first for another day! Yet knowing how way leads on to way, I doubted if I should ever come back. I shall be telling this with a sigh Somewhere ages and ages hence: Two roads diverged in a wood, and I- I took the one less traveled by, And that has made all the difference. ",
        
        "Star \"https://github.com/boai\" :)"];
        
        for i in 0..<strings.count {
            let model = DXCellModel(contentStr : strings[i])
            modelArray.append(model)
        }
        view.addSubview(self.tableView)
    }
    
}

extension ViewController : UITableViewDataSource,UITableViewDelegate {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.modelArray.count
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return self.modelArray[indexPath.row].cellHeigh
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = DXTableCell.cellWithTableView(tableView: tableView)
        cell.model = modelArray[indexPath.row] 
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath) as! DXTableCell
        cell.clickCell()
    }
}

2.自定义cell

import UIKit
enum DXShowCellTextType {
    case normal
    case expand
}

class DXTableCell: UITableViewCell {
    
    var normalLabel: UILabel!
    var expandLabel: UILabel!
    var superTableView: UITableView!
    var cellType : DXShowCellTextType
    
    static let identify = "cell"
    
    class func cellWithTableView(tableView : UITableView) -> DXTableCell {
        
        var cell = tableView.dequeueReusableCell(withIdentifier: identify) as? DXTableCell
        if cell == nil {
            cell = DXTableCell.init(style: .default, reuseIdentifier: identify)
            cell?.superTableView = tableView
        }
        return cell!
    }
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        self.cellType = .normal
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.selectionStyle = UITableViewCellSelectionStyle.none
        setupContentView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
   fileprivate func setupContentView() {
        normalLabel = UILabel.init(frame: CGRect.init(x: 10, y: 10, width: kScreenW-20, height: 0))
        expandLabel = UILabel.init(frame: CGRect.init(x: 10, y: 10, width: kScreenW-20, height: 0))
        
        normalLabel?.textColor = UIColor.gray
        expandLabel?.textColor = UIColor.black
        
        normalLabel?.font = UIFont.systemFont(ofSize: 14)
        expandLabel?.font = UIFont.systemFont(ofSize: 14)
        
        normalLabel?.numberOfLines = 4
        expandLabel?.numberOfLines = 0
        
        normalLabel?.alpha = 1
        expandLabel?.alpha = 0
        
        self.contentView.addSubview(normalLabel)
        self.contentView.addSubview(expandLabel)
    }
    
    var model : DXCellModel? {
        didSet{
            self.cellType = (model?.cellType)!
            if model?.cellType == .expand {
                normalLabel.alpha = 0
                expandLabel.alpha = 1
                normalLabel.frame = CGRect.init(x: 10, y: 10, width: kScreenW-20, height: 10)
                expandLabel.frame = CGRect.init(x: 10, y: 10, width: kScreenW-20, height: 10)
            }else{
                normalLabel.alpha = 1
                expandLabel.alpha = 0
                normalLabel.frame = CGRect.init(x: 10, y: 10, width: kScreenW-20, height: 10)
                expandLabel.frame = CGRect.init(x: 10, y: 10, width: kScreenW-20, height: 10)
            }
            normalLabel.text = model?.contentStr
            expandLabel.text = model?.contentStr
            
            normalLabel.sizeToFit()
            expandLabel.sizeToFit()
        }
    }
    
   open func clickCell() {
        
        switch cellType {
        case .normal:
            self.cellType = .expand
            self.model?.cellType = .expand
            self.model?.cellHeigh = (self.model?.expandHeigh)!
            cellAnimate(cellType: .normal)
            self.superTableView.beginUpdates()
            self.superTableView.endUpdates()
        case .expand:
            self.cellType = .normal
            self.model?.cellType = .normal
            self.model?.cellHeigh = (self.model?.normalHeigh)!
            cellAnimate(cellType: .expand)
            self.superTableView.beginUpdates()
            self.superTableView.endUpdates()
        default:
            break
        }
    }
    
    func cellAnimate(cellType : DXShowCellTextType){
        if cellType == .normal {
            UIView.animate(withDuration: 0.35, animations: { 
                self.expandLabel.alpha = 1
                self.normalLabel.alpha = 0
            })
        }else{
            UIView.animate(withDuration: 0.35, animations: {
                self.expandLabel.alpha = 0
                self.normalLabel.alpha = 1
            })
        }
    }

}

3.模型

import UIKit
public let kScreenW = UIScreen.main.bounds.size.width
public let kScreenH = UIScreen.main.bounds.size.height

class DXCellModel: NSObject {

    var contentStr : String?
    var cellHeigh : CGFloat = 0.0
    var normalHeigh : CGFloat = 0.0
    var expandHeigh : CGFloat = 0.0
    var cellType : DXShowCellTextType!
    
    
    init(contentStr : String) {
        
        self.contentStr = contentStr
        self.cellType = DXShowCellTextType.normal
        
        let height1 = DXCellModel.getSpaceLabelHeight(text: contentStr, font: 14, width: kScreenW-20.0)
        let height2 = DXCellModel.getSpaceLabelHeight(text: "one", font: 14, width: kScreenW-20.0)
        self.expandHeigh = height1 + 20.0
        
        let normalTextHeight = height1 >= 4*height2 ? 4*height2 : height1
        self.normalHeigh = normalTextHeight + 20
        self.cellHeigh = self.normalHeigh
    }
    
    //MARK: --计算文字的高度
     fileprivate class func getSpaceLabelHeight(text:String,font:CGFloat,width:CGFloat) -> CGFloat {
        
        let paraDic:[String : Any] = [NSFontAttributeName:UIFont.systemFont(ofSize: font)]
        let size = text.boundingRect(with: CGSize(width:width,height:CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: paraDic, context: nil)
        return size.height;
    }
   
}

demo下载地址

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 导读: 在开始阅读《穷爸爸富爸爸》这本书后,写过第一篇阅读笔记《穷人为钱工作,富人让钱为自己工作》 在阅读《穷爸爸...
    2018知行合一阅读 610评论 0 0
  • 1.块级元素与行内元素分别有哪些?动手测试并列出4条以上的特性区别 块状元素列表 行内元素列表 可变元素列表 块级...
    草鞋弟阅读 836评论 0 0
  • 我愿意 携一抹晨光 追寻你的背影 走在 你曾经的足迹上 品位 那不一样的静谧心境
    海姆达尔阅读 133评论 2 1
  • 示例在创建button的时候经常需要在button上添加图片和按钮,而且一般情况下我们需要的都是图片在上、标题在下...
    MrFire_阅读 48,155评论 46 144