1、使用 UIScrollView + UIStackView 的方式
2、设置UIStackView的上、左、下、高度,snapKit的 AutoLayout 会自动计算宽度
3、在layoutSubviews里要设置scrollow.contentSize,否则不能滑动。
import UIKit
struct HorizotalConfigration {
var itemWidth:CGFloat = 170 //元素宽度
var itemHeight:CGFloat = 100 //元素高度
var spacing:CGFloat = 25 //元素之间的间距
var marginLeft:CGFloat = 15 //左间距
var marginRight:CGFloat = 15 //右间距
}
class HorizontalScrollView<ItemView:UIView,ItemModel> : UIView {
var dataArr: [ItemModel]? {
didSet {
for data in dataArr ?? [] {
let itemView = ItemView()
stackView.addArrangedSubview(itemView)
itemView.snp.makeConstraints { (make) in
make.height.equalTo(configuration.itemHeight)
make.width.equalTo(configuration.itemWidth)
}
// 添加点击手势
let tap = UITapGestureRecognizer(target: self, action:#selector(self.didClicked(_:)))
tap.numberOfTouchesRequired = 1
tap.numberOfTapsRequired = 1
itemView.addGestureRecognizer(tap)
map(itemView,data)
}
setNeedsLayout()
layoutIfNeeded()
}
}
private var scrollView: UIScrollView!
private lazy var stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.distribution = .equalSpacing
return stackView
}()
private var configuration = HorizotalConfigration()
private var map:((_ cell:ItemView, _ itemModel:ItemModel)->Void)
/// 每个cell点击以后的回调闭包
public var itemClicked:((_ itemView:ItemView, _ model:ItemModel, _ index:Int)->Void)?
init(configuration:HorizotalConfigration,map:@escaping(_ cell:ItemView,_ model:ItemModel)->Void){
self.configuration = configuration
self.map = map
super.init(frame: .zero)
setupStackView()
}
override public func layoutSubviews() {
super.layoutSubviews()
let stackViewWidth = stackView.frame.size.width
scrollView?.contentSize = CGSize(width: stackViewWidth + configuration.marginLeft + configuration.marginRight, height: 0)
}
// 手势的点击事件
@objc private func didClicked(_ tap:UITapGestureRecognizer){
if let cell = tap.view as? ItemView, let data = self.dataArr?[cell.tag]{
self.itemClicked?(cell, data, cell.tag)
}
}
func setupStackView() {
stackView.spacing = configuration.spacing
scrollView = UIScrollView()
scrollView.showsHorizontalScrollIndicator = false
self.addSubview(scrollView)
scrollView.addSubview(stackView)
scrollView.snp.makeConstraints { (make) in
make.top.left.right.equalToSuperview()
make.height.equalTo(configuration.itemHeight)
make.bottom.equalToSuperview()
}
stackView.snp.makeConstraints { (make) in
make.top.bottom.equalToSuperview()
make.left.equalToSuperview().offset(configuration.marginLeft)
make.height.equalTo(configuration.itemHeight)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
效果:
使用:
private var hscrollView : HorizontalScrollView<DoctorServiceItemView,DoctorServiceModel>!
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
contentView.backgroundColor = UIColor(lca_hex: 0xf3f3f3)
let configuration = HorizotalConfigration()
hscrollView = HorizontalScrollView(configuration: configuration, map: { itemView, itemModel in
itemView.backgroundImageView.image = itemModel.image
itemView.titleLabel.text = itemModel.title
itemView.descLabel.text = "立即进入"
})
contentView.addSubview(hscrollView)
hscrollView.dataArr = [DoctorServiceModel(image: UIImage(named: "XQ-ZSLT")!, title: "钻石绿通"),DoctorServiceModel(image: UIImage(named: "XQ=BGJD")!, title: "报告解读"),DoctorServiceModel(image: UIImage(named: "XQ-SHZY")!, title: "手术/住院预约"),DoctorServiceModel(image: UIImage(named: "XQ-YDY")!, title: "主任一对一")]
hscrollView.snp.makeConstraints { make in
make.left.right.equalTo(contentView)
make.top.bottom.equalTo(contentView).inset(10)
}
hscrollView.itemClicked = { itemView,itemModel,index in
printDebug("点击事件")
}
}
override func layoutSubviews() {
super.layoutSubviews()
hscrollView.layoutSubviews()
}