美文网首页SWIFT
swift UITableView 实现横向滚动按钮视图

swift UITableView 实现横向滚动按钮视图

作者: Sparkle_S | 来源:发表于2016-09-02 14:21 被阅读1315次

    当你在实现横向滚动视图时,常常需要一个类似于 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~

    相关文章

      网友评论

      • 杰宝_ff11:你好,使用您的代码后,出现效果每个cell的label宽度自动变成了14,尽管在cellForRowAt indexPath里打印宽度还都是正常的,不知道什么原因
        Sparkle_S:你需要注意一下,cell发生了翻转. 你可以查看一下Debug View Hierarchy
      • c4b4b99284aa:你好,最后一行topScrollView是什么
        Sparkle_S:@c4b4b99284aa 使用bgScrollView应该更好一些。一般使用这个空间的时候,下面会配合UIScrollView做界面展示。

      本文标题:swift UITableView 实现横向滚动按钮视图

      本文链接:https://www.haomeiwen.com/subject/afqhettx.html