随着路由设计模式的使用,所有按钮及tableview的点击事件都由服务器端决定,固定UI已经无法满足需求,固定的UI限制了当前路由设计的灵活性,所以为了使UI可以像点击事件一样灵活,我们定义了差不多30种常见的UI展示样式,开发中最常用的就是tableview,所以我们让每一种展示样式都作为一个新的cell,通过当前数据的show_type来决定使用哪一种cell来展示当前数据。
UI部分仿制路由设计模式,点击事件的处理方式都由路由中心决定,在UI处理中我们同样需要一个视图中心来根据不同的show_type来产生不通的视图,就好像一个工厂一样,我给你一个标识符,你返回一个我需要的视图,这里我新建了一个ViewProducter来处理视图,ViewProducter中实现了tableview的数据源方法及代理方法。
存储不同show_type所使用的model
/*
1. banner 轮播图 img_ratio
2 icons 小图下方带文字 colunms
3 images 一行多个图片均分 colunms,img_ratio
4 scroll 一行多个图片滚动 img_ratio,固定宽度
5 labels 一行多个文字带圆角边框 colunms,color
6 manage 一行通栏文字样式 -
7 search 搜索样式 orders,filters
8 list_material 资料列表 -
9 list_topic 论坛列表 用ontop决定是否是置顶
10 list_meal 套餐列表 -
11 list_course 课程列表 -
12 list_news 资讯列表 -
13 list_teacher 导师列表
14 ad_round 左边圆图广告
15 ad_square 左边方图广告
*/
private let listClassMap = [
"icons":"HSMutPicModel", //1
"images":"HSMutPicModel",//2
"scroll":"HSMutPicModel",//3
"labels":"HSMutPicModel",//4
"banner":"HSMutPicModel",//5
"list_material":"HSMaterilCellModel",//6
"list_meal":"HSClasslCellModel",//7
"list_course":"HSClasslCellModel",//8
"list_news":"HSListNewsCellModel",//9
"list_topic":"HSListTopicCellModel",//10
"list_ontop":"HSListTopicCellModel",//1
"manage":"HSManageTipsModel",//12
"ad_round":"HSAdvertiseModelNew",//13
"ad_square":"HSAdvertiseModelNew",//14
"list_teacher":"HSTeacherListCellModel",//15
"search":"HSSearchStyleCellModel",//16
"video":"HSVideoSectionModel",
"list_pack":"HSClasslCellModel",
"list_order":"HSOrderModel",
"list_video":"HSClasslCellModel",
"list_goods":"HSClasslCellModel",
"ad_corner":"HSAdvertiseModelNew",
"attach":"HSAttachModel",
"texts":"HSTextsModel",
"blocks":"HSBlockModel",
"marquee":"HSMarqueeModel",
"across":"HSAcrossModel",
"collect":"HSCollectModel",
"list_discover":"HSDiscoverModel",
"square":"HSSquareModel",
"word":"FilterConModel"
];
实现tableview返回cell的方法,根据不同的show_type返回不同的cell
class func processCell(mutiModel:HSAllKindsCellModel,tableView:UITableView) -> UITableViewCell {
let show_type = mutiModel.show_type
switch show_type {
case "icons":
let cell:HSIconsCell = HSIconsCell.createCell(tableView: tableView)
cell.selectionStyle = .none
cell.cellModel = mutiModel
return cell
case "images":
let cell:HSImagesCell = HSImagesCell.createCell(tableView: tableView)
cell.cellModel = mutiModel
cell.selectionStyle = .none
return cell
case "scroll":
let cell:HSScrollCell = HSScrollCell.createCell(tableView: tableView)
cell.cellModel = mutiModel
cell.selectionStyle = .none
return cell
case "labels":
let cell:HSLablesCell = HSLablesCell.createCell(tableView: tableView);
cell.cellModel = mutiModel
cell.selectionStyle = .none
return cell
case "banner":
let cell:HSBannerCell = HSBannerCell.createCell(tableView: tableView);
cell.cellModel = mutiModel
cell.selectionStyle = .none
return cell
case "list_material":
let cell:HSMaterialTableViewCell = HSMaterialTableViewCell.createCell(tableView)
//cell.topic_url = (mutiModel.cellModel as!HSMaterilCellModel).topic_url
cell.model = mutiModel.cellModel as?HSMaterilCellModel
cell.selectionStyle = .none
return cell;
case "list_news":
let newmodel = mutiModel.cellModel as? HSListNewsCellModel
if newmodel!.ontop == true {
let cell:HSTopicTopCell = HSTopicTopCell.createCell(tableView: tableView)
let topmodel = HSListTopicCellModel()
topmodel.title = (newmodel?.title)!
cell.cellModel = topmodel
cell.selectionStyle = .none
return cell
}
else
{
let cell:HSNewsListCell = HSNewsListCell.createCell(tableView: tableView)
cell.cellModel = mutiModel.cellModel as? HSListNewsCellModel
cell.selectionStyle = .none
return cell
}
case "list_topic":
let topicModel:HSListTopicCellModel = (mutiModel.cellModel as? HSListTopicCellModel)!
if topicModel.ontop==true {
let cell:HSTopicTopCell = HSTopicTopCell.createCell(tableView: tableView)
cell.cellModel = topicModel
cell.selectionStyle = .none
return cell
}
else
{
let cell:HSTopicsContentCell = HSTopicsContentCell.createCell(tableView)
cell.model = topicModel
cell.selectionStyle = .none
return cell
}
case "manage":
let cell:HSManageCell = HSManageCell.createCell(tableView: tableView)
cell.cellModel = mutiModel.cellModel as? HSManageTipsModel
cell.selectionStyle = .none
return cell;
case "ad_square":
let cell:HSAdvertiseCell = HSAdvertiseCell.dashabicell(with: tableView)
cell.celllModel = (mutiModel.cellModel as? HSAdvertiseModelNew)?.data_list![0]
cell.selectionStyle = .none
return cell;
case "ad_round":
let cell:HSAdvertiseCircleImageCell = HSAdvertiseCircleImageCell.dashabicell(with: tableView)
cell.cellModel = (mutiModel.cellModel as? HSAdvertiseModelNew)?.data_list![0]
cell.selectionStyle = .none
return cell;
case "list_teacher":
let cell:HSTeacherListCell = HSTeacherListCell.createCell(tableView: tableView)
cell.cellModel = mutiModel.cellModel as? HSTeacherListCellModel
cell.selectionStyle = .none
return cell;
case "search":
let cell:HVSearchCell = HVSearchCell.createCell(tableView: tableView)
cell.cellModel = mutiModel.cellModel as? HSSearchStyleCellModel
cell.selectionStyle = .none
return cell
case "list_course","list_meal","list_pack","list_video","list_goods":
let cell:HSClassCell = HSClassCell.createCell(tableView: tableView);
cell.isRelate = false;
let cellModel = mutiModel.cellModel as? HSClasslCellModel
cell.showType = show_type
if show_type == "list_goods" {
cell.GoodsModel = cellModel
}
else
{
cell.CourseModel = cellModel
}
mutiModel.cellHeight = cell.cellHeight
cell.selectionStyle = .none
return cell
case "video":
let cell:HSVideoListCell = HSVideoListCell.createCell(tableView: tableView);
let cellModel = mutiModel.cellModel as? HSVideoSectionModel
cell.cellModel = cellModel;
cell.selectionStyle = .none
return cell
case "list_order":
let cell:HSOrderCell = (tableView.dequeueReusableCell(withIdentifier: "HSOrderCell") as? HSOrderCell)!
let cellModel = mutiModel.cellModel as? HSOrderModel
cell.cellModel = cellModel
cell.selectionStyle = .none;
return cell
case "ad_corner":
let cell:HSAdCornerCell = (tableView.dequeueReusableCell(withIdentifier: "HSAdCornerCell") as? HSAdCornerCell)!
let cellModel = (mutiModel.cellModel as? HSAdvertiseModelNew)?.data_list?.first
cell.cellModel = cellModel;
cell.selectionStyle = .none
return cell
case "attach":
let cell:HSAttentTableViewCell = (tableView.dequeueReusableCell(withIdentifier: "HSAttentTableViewCell") as? HSAttentTableViewCell)!
let cellModel = mutiModel.cellModel as? HSAttachModel
if !hs_isEmptyString(cellModel?.image) {
cell.imageimageView.sd_setImage(with: URL.init(string: cellModel!.image!), placeholderImage: DefultImage)
}
cell.titletitleLabel.text = cellModel?.title
cell.nameLabel.text = cellModel?.name
cell.messageLabel.text = cellModel?.message
cell.selectionStyle = .none
return cell
case "texts":
let cell:HSTextsCell = HSTextsCell.createCell(tableView: tableView)
let cellModel = mutiModel.cellModel as? HSTextsModel
cell.cellModel = cellModel;
cell.selectionStyle = .none
return cell
case "blocks":
let cell:HSBlockCell = HSBlockCell.createCell(tableView: tableView)
let cellModel = mutiModel.cellModel as? HSBlockModel
if cellModel != nil {
cell.cellModel = cellModel
}
cell.selectionStyle = .none
return cell
case "marquee":
let cell:HSMarqueeCell = HSMarqueeCell.createCell(tableView: tableView)
cell.cellModel = mutiModel.cellModel as? HSMarqueeModel
return cell
case "across":
let cell:HSArcossCell = HSArcossCell.createCell(tableView: tableView)
cell.cellModel = mutiModel.cellModel as? HSAcrossModel
cell.selectionStyle = .none
return cell
case "collect":
let cell:HSCollectCell = HSCollectCell.createCell(tableView: tableView)
let cellModel = mutiModel.cellModel as? HSCollectModel
cell.cellModel = cellModel;
cell.selectionStyle = .none
return cell
case "list_discover":
let cell:HSDiscoverCell = HSDiscoverCell.createCell(tableView: tableView)
let cellModel = mutiModel.cellModel as? HSDiscoverModel
cell.cellModel = cellModel;
cell.selectionStyle = .none
return cell
case "square":
let cell:HSSquareCell = HSSquareCell.createCell(tableView: tableView)
let cellModel = mutiModel.cellModel as? HSSquareModel
cell.cellModel = cellModel;
cell.selectionStyle = .none
return cell
case "word":
let cell:HSWordCell = (tableView.dequeueReusableCell(withIdentifier: "HSWordCell") as? HSWordCell)!
let cellModel = mutiModel.cellModel as? FilterConModel
cell.model = cellModel;
cell.selectionStyle = .none
return cell
default:
return UITableViewCell.init(style:.default , reuseIdentifier: "none")
}
}
实现返回cell高度的方法
class func processCellHeight(mutiModel:HSAllKindsCellModel) -> CGFloat{
let show_type = mutiModel.show_type
if show_type == "banner"||show_type == "labels"||show_type == "scroll"||show_type == "images"||show_type == "icons" {
return mutiModel.cellHeight;
}
else if(show_type == "list_topic")
{
let topicModel:HSListTopicCellModel = (mutiModel.cellModel as? HSListTopicCellModel)!
if topicModel.ontop==true {
return 40
}
else{
return 80
}
}
else if(show_type == "list_teacher")
{
return 90
}
else if(show_type == "manage")
{
return 50
}
else if(show_type == "search")
{
return 44
}
else if(show_type == "list_meal"||show_type == "list_course"||show_type == "list_pack")
{
return mutiModel.cellHeight;
}
else if(show_type == "list_goods")
{
return mutiModel.cellHeight;
}
if show_type == "video" {
let allkinds = mutiModel.cellModel as? HSVideoSectionModel
return (HSwidth/allkinds!.hs_getSafeImgRatio())
}
if show_type == "scroll" {
return 40;
}
if show_type == "list_material" {
return ((mutiModel.cellModel as?HSMaterilCellModel)?.cellHeight)!;
}
else if show_type == "list_order"{
return 100
}
else if show_type == "list_material" {
return 70.5
}
else if show_type == "attach" {
return 135
}
else if show_type == "texts" {
let model = mutiModel.cellModel as!HSTextsModel
return 36*ceil(CGFloat(CGFloat(model.data_list!.count)/model.hs_getSafeColumns()))
}
else if show_type == "blocks" {
if mutiModel.cellModel == nil {
return 0.001;
}
let cellModel = mutiModel.cellModel as!HSBlockModel
let padding:CGFloat = 10.0
let itemW = (HSwidth-(CGFloat((cellModel.hs_getSafeColumns()))+1.0)*padding)/CGFloat((cellModel.hs_getSafeColumns()))
let itemH = itemW/(cellModel.hs_getSafeImgRatio())+21+15+5+5
let line = ceil(CGFloat(CGFloat(cellModel.data_list!.count)/CGFloat(cellModel.hs_getSafeColumns())))
return itemH*CGFloat(line) + 10.0*(CGFloat(line+1))
}
else if show_type == "marquee" {
return 60
}
else if show_type == "across" {
return 40
}
else if show_type == "collect" {
let model = mutiModel.cellModel as!HSCollectModel
return 36*ceil(CGFloat(CGFloat(model.data_list!.count)/model.hs_getSafeColumns()))
}
else if show_type == "list_discover" {
return 80
}
else if show_type == "word" {
return ((mutiModel.cellModel as?FilterConModel)?.cellHeight)!+50;
}
else if show_type == "square" {
if mutiModel.cellModel == nil {
return 0.001;
}
let cellModel = mutiModel.cellModel as!HSSquareModel
let padding:CGFloat = 10.0
let itemW = (HSwidth-(CGFloat((cellModel.hs_getSafeColumns()))+1.0)*padding)/CGFloat((cellModel.hs_getSafeColumns()))
let itemH = itemW/(cellModel.hs_getSafeImgRatio())+21+15+5+5+10
let line = ceil(CGFloat(CGFloat(cellModel.data_list!.count)/CGFloat(cellModel.hs_getSafeColumns())))
return itemH*CGFloat(line) + 10.0*(CGFloat(line+1))
}
return 80;
}
返回cell的Headerview的方法
class func processViewForHeader(mutiModel:HSAllKindsCellModel,tableView:UITableView) -> UIView{
if !hs_isEmptyString(mutiModel.cellHeaderModel?.header)
{
let backView = UIView()
if !hs_isEmptyString(mutiModel.cellHeaderModel?.header) {
backView.frame = CGRect(x: 0, y: 0, width: HSwidth, height:CGFloat((mutiModel.cellHeaderModel?.space_type)!)*3)
} else {
backView.frame = CGRect(x: 0, y: 0, width: HSwidth, height:3)
}
let spaceV = UIView()
spaceV.backgroundColor = UIColor.clear
let has_more:Bool = !hs_isEmptyString(mutiModel.cellHeaderModel!.more_url)
let headerView:HSComSectionHeaderView = HSComSectionHeaderView.createTableSectionHeader(hasMore: has_more, tableView: tableView)
mutiModel.cellHeaderModel!.subtitle = "更多"
headerView.sectionModel = mutiModel.cellHeaderModel
backView.addSubview(spaceV)
backView.addSubview(headerView)
spaceV.snp.makeConstraints({ (make) in
make.left.top.right.equalTo(backView)
make.height.equalTo(((mutiModel.cellHeaderModel?.space_type)!)*3)
})
headerView.snp.makeConstraints({ (make) in
make.left.right.bottom.equalTo(backView)
make.top.equalTo(spaceV.snp.bottom)
})
return backView;
}
if mutiModel.space_type != 0 {
let backview = UIView.init(frame: CGRect(x: 0, y: 0, width: HSwidth, height: CGFloat(mutiModel.space_type)*3.0));
backview.backgroundColor = UIColor.init(hexString: "eeeeee")
if (mutiModel.show_type == "list_topic") {
backview.backgroundColor = UIColor.clear;
}
return backview
}
let backview = UIView.init(frame: CGRect(x: 0, y: 0, width: HSwidth, height: 0.5));
backview.backgroundColor = UIColor.init(hexString: "eeeeee")
if (mutiModel.show_type == "list_topic") {
backview.backgroundColor = UIColor.clear;
}
return backview
}
class func processHeightForHeaderInSection(mutiModel:HSAllKindsCellModel) -> CGFloat{
if !hs_isEmptyString(mutiModel.cellHeaderModel?.header) {
return 40 + CGFloat((mutiModel.cellHeaderModel?.space_type)!)*3
}
if mutiModel.space_type != 0 {
return CGFloat(mutiModel.space_type)*3.0
}
return 0.5;
}
实现cell的点击方法,这里cell的点击方法都传入到路由中心中统一处理
class func processCellSelect(mutiModel:HSAllKindsCellModel) -> Void{
Router.process(with: mutiModel);
}
说明:这里新建viewProducter是后期需求逐渐变更的产物,开始所有的tableview代理方法都是写在一个VC当中的,但是随着版本的迭代,有一些固定页面也要支持通用的show-type,所以后来才把代理方法提取放在一个类中,这样就解决了,固定页面的tableview中使用通用解析的cell,只需要通过判断当前data是否含有show-type,如果有就交给viewproducter,没有就返回固定cell。
总结:1.通过这样的UI处理方式,UI展示样式由服务器端配置决定
2.UI展示顺序由服务器端决定(例如轮播图可放在任意位置,只取决于在array中的index)
3.固定页面也可以扩展业务,随时随地修改比较方便,我们不用总是天天改UI(这个还是比较爽的)
4.解决了对路由点击事件灵活性的限制(例如有一个图表页面,可以是今年的销售统计,也可以是用户注册统计,但是图标是不一样的,能更好的配合点击事件)
相关:iOS 浅析路由设计模式