无限滑动的思考

自从体验到了UICollectionView的强大后,真的无法自拔,做什么都想往上面靠.就像我上篇说的,他能实现各种各样的酷炫动画,不过很多时候,一些不复杂的功能,其实有更容易的解决方法.

无限滑动

这个算是一个很普通的功能.但其实所有的上下,左右滑动都类似于他.只是他们不是无限地滑下去.
实现的方式主要有两种:

  1. 滑动的区域有多长,view就有多长
  2. 几个View利用视觉的误差交替显示
    这又是老生常谈的运行速度和内存的不可兼得.

UIScrollView

UIScrollView的实现原理
这篇文章很短,一看就明白的scrollView是如何实现的.

//这就是一个超级简易的scrollView
class customScrollView: UIView {
    var contentSize:CGSize
    override init(frame: CGRect) {
        self.contentSize = frame.size
        super.init(frame: frame)
        self.clipsToBounds = true        
        let panGes = UIPanGestureRecognizer.init(target: self, action: "handlePanGesture:")
        self.addGestureRecognizer(panGes)
    }
    
    func handlePanGesture(gestureRecognizer: UIPanGestureRecognizer){
        let translation = gestureRecognizer.translationInView(self)
        let bounds = self.bounds
        let newBoundsOriginY = bounds.origin.y - translation.y
        
        if newBoundsOriginY + self.frame.size.height <= contentSize.height && newBoundsOriginY >= 0{
            self.bounds = CGRectMake(bounds.origin.x, newBoundsOriginY, bounds.size.width, bounds.size.height)
            gestureRecognizer .setTranslation(CGPointZero, inView: self)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
} 

你可以设置他的contentSize,想有多大就有多大,就是上面的第一种实现方式.主要就是两点

  • 设置clipsToBounds,超过自身部分截取
  • 根据手势改变bounds,实现移动效果

UICollectionView,UITableView

UICollectionView,UITableView都是继承于UIScrollView,他的滑动区域也是想多长就多长.
不过这样内存花销确实大,所以上面的Cell复用又有点类似于第二种实现方式.所以滑动过快,cell上控件很多的情况下,滑动可能会有卡顿.
cell上添加的控件都是复用的,不能重复添加,主要有两种情况

  • 从storyboard,xib加载.
  • 自己创建,dequeueReusableCellWithIdentifier出来一个cell.如果为空,则新建一个,在上面添加控件,当cell不为空时,不要添加控价,不然以后每次从池里取出的复用cell都会添加,类似:
UITableViewCell  *cell  = [tableView dequeueReusableCellWithIdentifier:cellID];
if (!cell){
   //添加控件,以后每次从池里取出,都已初始化好
}
//不要添加控件,会重复
return cell;

//也可以这样,类似:

UIButton *button = [cell.contentView viewWithTag:KMinTag];
if (!button) {
    //做初始化的工作
}

这两个控件基本上是使用最多的了,有一些基本的特点

  • UITableView只能上下滑动,UICollectionView可以上下左右滑动
  • UITableView可以实现从下至上,UICollectionView可以实现从右至左滑动,只需要加载数据的时候setContentOffset就可以了.这种情况不多,就在聊天加载数据的时候遇到过.

UIView交替实现

用几个View交替来实现,这样代码量很少.

        //建三个View,左中右,添加左滑右滑手势
        let leftView = photoView(frame: leftFrame)
        self.view.addSubview(leftView)
        
        let middleView = photoView(frame: middleFrame)
        self.view.addSubview(middleView)
        
        let rightView = photoView(frame: rightFrame)
        self.view.addSubview(rightView)
        
        viewArray = [leftView,middleView,rightView];
        
        let leftSwipe = UISwipeGestureRecognizer(target: self, action: "leftSwipeEvent")
        leftSwipe.direction = UISwipeGestureRecognizerDirection.Left
        self.view.addGestureRecognizer(leftSwipe)
        
        let rightSwipe = UISwipeGestureRecognizer(target: self, action: "rightSwipeEvent")
        rightSwipe.direction = UISwipeGestureRecognizerDirection.Right
        self.view.addGestureRecognizer(rightSwipe)


       //滑动的时候,利用视觉误差,移动视图
       func leftSwipeEvent(){
        let leftView = viewArray[0]
        viewArray.append(leftView)
        viewArray.removeAtIndex(0)
        
        UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
                () -> Void in
                self.viewArray[0].frame = self.leftFrame
                self.viewArray[1].frame = self.middleFrame
            
            }) {
                (finished:Bool) -> Void in
                self.viewArray[2].frame = self.rightFrame
        }
    }

        func rightSwipeEvent(){
        let rightView = viewArray[2]
        viewArray.insert(rightView, atIndex: 0)
        viewArray.removeLast()
        
        UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
            () -> Void in
            self.viewArray[2].frame = self.rightFrame
            self.viewArray[1].frame = self.middleFrame
            
            }) {
                (finished:Bool) -> Void in
                self.viewArray[0].frame = self.leftFrame
        }
    }

感觉这几种方式各有各的优缺点,做的时候还是要自己把握.

  • 有复杂动画,每个cell控件较少的情况下推荐用collectionView
  • 就是简单的无限轮播,每个view上控件比较复杂的话推荐用多个view交替显示

以上代码写了个demo,github地址,欢迎大家交流

作者:levi
comments powered by Disqus