新闻App通常是有个新闻的列表,这个列表一般都用TableView来做,每个Cell显示一条新闻,如下图:
在我做的时候,开始Cell是直接从控件库拖到StoryBoard里面,配置了一点东西就OK了:当Cell的Style设成subtilte时,标题、副标题、以及图像都是可用的,在cellForRowAtIndexPath里直接配置就行了:
但这样做了之后出现一个问题:新闻配图是从网络获取的,长宽比和大小并不固定。在这种做法中,图像是以高度而不是宽度统一对齐的,也就是经过缩放后变成统一的高度适配当前Cell,再显示出来。这样一来,每个Cell里的图像宽度就参差不齐,很难看。我尝试了很久也没能解决这个问题,看起来无论怎么对Cell.image进行配置,也是无效的。折中的办法是事先修改图像的长宽比,但这不是我想要的效果。于是,只好尝试TableViewCell的自定义了。
你看到的是非授权版本!爬虫凶猛,请尊重知识产权!
转载请注明出处:http://conanwhf.github.io/2016/01/21/newsreader-8/
访问原文「从打造新闻app学到的(8):自定义TableViewCell」获取最佳阅读体验并参与讨论
不光是TableViewCell,所有控件的自定义都是如出一辙的套路:先继承一个控件的类,再在StoryBoard里面把对应的Custom Class修改成自己继承的那个类,就可以随意修改了。在这里,先把Style设回custom,把Title, image这些在自己的初始化函数里生成:
class ListTableViewCell: UITableViewCell {
var img:UIImageView!
var title:UILabel!
var info:UILabel!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let temp = self.layout()//我自己写的函数,忽略
title = UILabel(frame: temp.1)
info = UILabel(frame: temp.2)
img = UIImageView(frame: temp.0)
self.addSubview(title)
self.addSubview(info)
self.addSubview(img)
}
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)!
}
}
同时,在cellForRowAtIndexPath中添加初始化:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> ListTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("newsList", forIndexPath: indexPath) as? ListTableViewCell
if cell==nil {
cell = ListTableViewCell(style: .Default, reuseIdentifier: "newsList")
}
//TODO: something config
return cell!
}
接下来问题来了:初始化的时候,根本跑不到我自己定义的初始化函数里去!在cell==nil的判断里,cell每次都已经存在,而不是初始生成一些,之后再重用的模式。我查了很多资料,怎么看也没什么问题,别人都是这么写的。上stackoverflow找,有类似问题的人也很少,有个回答说如果这样写,是不应该会有问题的,除非是别的什么地方出错了。我抓狂了很久,突然想到了一个地方—之前在StoryBoard里面配置的ID(上图我已经标出来了)!果然,把这里去掉之后,终于可以Call到自定义的初始化函数了。所以,如果在StoryBoard里设置了Cell id,则系统会自动处理TableViewCell的初始化和重用,不会调用自定义部分。
这个问题解决后,又出现了两个小问题,一是Cell触发的转场不起作用了,二是在StoryBoard里面Config的Cell高度也失效了。综合上面的问题,应该是在StoryBoard里面取消定义Cell ID之后,系统找不到对应的Cell了,也就无法把config和Cell联系起来。高度定义只要自己在代码中重新写一下就好,转场嘛,在didSelectRowAtIndexPath中手动调用也是一样的:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
self.performSegueWithIdentifier("ShowPost", sender: self)
return indexPath
}
这两周基本上在荒废,这篇文章离写代码的时间也是拖了有半个月,有些细节都快忘了,每天没做什么正事,有点浑浑噩噩的感觉……拖延症加重了?要振作一点!