swift UITableView 实现横向滚动按钮视图
2016-09-02 本文已影响1315人
Sparkle_S
当你在实现横向滚动视图时,常常需要一个类似于 UISegment 的控件放置在顶部.然而它并不是一个 UISegment 控件.它的实现你可以利用 UItableview , UIScrollView 或者 UICollectionView ,当各个按钮的标题长度参差不齐时, 最简便的通过 UICollection View 的实现方式便只能被遗弃. 在剩下的两种实现方式中, UItableview 的复用机制让它成为较好的实现方式. 这里,便是通过 UITableView 实现横向滚动的按钮视图. 效果如下:
首先,你需要实现一个上面只放有 label 的自定义 UITableViewCell ,创建原因:修改系统 cell 的 textAlignment 无效.(心累(ㄒoㄒ))
然后,你便可以实现横向滚动按钮视图,具体见代码:
class ScrollBtnsView: UIView ,UITableViewDelegate,UITableViewDataSource{
var clickBlock:((tag:Int)->())? //点击cell的回调
var btnTitleArr:[String] = [] { //按钮标题数据
didSet{
if btnTitleArr.count == 0 {
self.frame = CGRectZero
}
var allLength:CGFloat = 0
for titleStr in btnTitleArr {
let curLength = self.getStrLength(titleStr)+60
lengthArr.append(curLength)
pointXArr.append(allLength)
allLength += curLength
}
viewLength = allLength
}
}
var tbView:BaseTableView! //横向滚动视图
var flagView:UIView! //底部的标注线
var earlierFlag:Int = 0 //标注点击之前的cell
var lengthArr:[CGFloat] = [] //每个 cell 的宽度
var pointXArr:[CGFloat] = [] //每个 cell 的位置
var viewLength:CGFloat = 0{ //视图总宽度
didSet{
if viewLength<SCREEN_WIDTH {
//如果所有按钮的宽度小于屏幕宽度,按比例调整每个宽度
var newLengthArr:[CGFloat] = []
var newPonitXArr:[CGFloat] = []
var aLength:CGFloat = 0
for length in lengthArr {
let newLength = (length*SCREEN_WIDTH)/viewLength
newLengthArr.append(newLength)
newPonitXArr.append(aLength)
aLength += newLength
}
lengthArr = newLengthArr
pointXArr = newPonitXArr
viewLength = SCREEN_WIDTH
}
}
}
// MARK: - system method
override func awakeFromNib() {
super.awakeFromNib()
self.setUp()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setUp()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - private method
func setUp() {
//创建 tbview
tbView = BaseTableView.init(frame: CGRectMake(0, 0, self.frame.height, SCREEN_WIDTH), style: .Plain)
tbView.showsVerticalScrollIndicator = false
tbView.scrollsToTop = false
tbView.separatorStyle = .None
tbView.delegate = self
tbView.dataSource = self
//逆时针旋转90度
tbView.center = CGPointMake(SCREEN_WIDTH/2.0, self.frame.height/2.0)
tbView.transform = CGAffineTransformMakeRotation(-CGFloat(M_PI)/2)
self.addSubview(tbView)
//创建 flagView
flagView = UIView.init(frame: CGRectMake(0, 0, 2, 0))
flagView.backgroundColor = UIColor.redColor()
tbView.addSubview(flagView)
//添加线
let lineView = UIView.init(frame: CGRectMake(0, self.frame.height-1, self.frame.width, 1))
lineView.backgroundColor = UIColor.init(white: 0.8, alpha: 1)
self.addSubview(lineView)
}
func getStrLength(str:NSString) -> CGFloat {
let attributes = [NSFontAttributeName:UIFont.systemFontOfSize(15)]
let size = str.sizeWithAttributes(attributes)
return size.width
}
// MARK: - public method
func configBtnScrollView(titles:[String],block:((tag:Int)->())) {
btnTitleArr = titles
clickBlock = block
flagView.frame = CGRectMake(0, 0, 2, lengthArr[0])
tbView.reloadData()
}
func upDataOldAndNewBtn(newRow:Int) {
let newIndexPath = NSIndexPath.init(forRow: newRow, inSection: 0)
//修改文字颜色
let earlierCell:HorizontalLabelCell? = tbView.cellForRowAtIndexPath(NSIndexPath.init(forRow: earlierFlag, inSection: 0)) as! HorizontalLabelCell?
earlierCell?.cellLabel.textColor = UIColor.grayColor()
let curCell = tbView.cellForRowAtIndexPath(newIndexPath) as! HorizontalLabelCell?
curCell?.cellLabel.textColor = UIColor.redColor()
//修改 flagView 的位置
let curY = pointXArr[newRow]
let curH = lengthArr[newRow]
UIView.animateWithDuration(0.3, animations: {
self.flagView.frame = CGRectMake(0, curY, 2,curH )
})
//重设 tableview 的偏移量
var offSet:CGFloat = 0
if (viewLength-curY)<SCREEN_WIDTH{
offSet = viewLength-SCREEN_WIDTH
}else if (curY + curH)>SCREEN_WIDTH {
offSet = curY + curH/2.0-SCREEN_WIDTH/2.0
}
UIView.animateWithDuration(0.3) {
self.tbView.contentOffset = CGPointMake(0, offSet)
}
//重设 earlierCell 标注
earlierFlag = newRow
}
// MARK: - UITableViewDelegate
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return btnTitleArr.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return lengthArr[indexPath.row]
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellID = "HorizontalLabelCell"
var cell:HorizontalLabelCell? = tableView.dequeueReusableCellWithIdentifier(cellID) as! HorizontalLabelCell?
if cell == nil {
cell = HorizontalLabelCell.init(style: .Default, reuseIdentifier: cellID)
}
//设置选中风格
cell?.selectionStyle = .None
//顺时针旋转90度
cell?.transform = CGAffineTransformMakeRotation(CGFloat(M_PI)/2)
cell?.cellLabel.text = btnTitleArr[indexPath.row]
//设置 label 的 frame
cell?.cellLabel.frame = CGRectMake(0, 0, lengthArr[indexPath.row], self.frame.height)
if indexPath.row == earlierFlag {
cell?.cellLabel.textColor = UIColor.redColor()
}else{
cell?.cellLabel.textColor = UIColor.grayColor()
}
return cell!
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.upDataOldAndNewBtn(indexPath.row)
//cell 点击回调
let tag = indexPath.row
if let clickBlock = clickBlock {
clickBlock(tag: tag)
}
}
}
最后,调用.很简单吧
let scrollBtnsView = ScrollBtnsView.init(frame: CGRectMake(0, 64, SCREEN_WIDTH, 50))
scrollBtnsView.configBtnScrollView(["标题1","2","标题标题3","标题4","标题标题标题5","标题标题6"]) { (tag) in
print("点击 cell\(tag)")
}
self.view.addSubview(scrollBtnsView)
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let offSetFlag = Int(scrollView.contentOffset.x/SCREEN_WIDTH)
topScrollView.upDataOldAndNewBtn(offSetFlag)
}
期待你的评论建议O(∩_∩)O~