Fade in UITableViewCell row by row in Swift

2019-04-06 14:23发布

问题:

I am new to swift, I am trying to have a UITableView and the cells will be animated to appear one by one. How can I do that? Also, if the newly appeared row of cell not on the screen (hiding below the table). How can I move the table up when each cell appear?

    var tableData1: [String] = ["1", "2", "3", "4", "5", "6", "7"]

     override func viewWillAppear(animated: Bool) {
           tableView.scrollEnabled=false
    tableView.alpha=0.0
            NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(3), target: self, selector: "animateTable", userInfo: nil, repeats: false)
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.tableData1.count
    }

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell     {

        let cell:TblCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! TblCell
        cell.lblCarName.textAlignment = NSTextAlignment.Justified;
return cell
}

func animateTable() {

//what should be the code?//
}

回答1:

In the UITableView, the rows are prepared automatically for you when they get to be in your "range vision". I'm assuming you are, at least not initially, being able to scroll the tableView, so we would scroll it programmatically making the rows appear as it goes. How are we doing that? Actually UITableView has a method that let us scroll it to a specific row:

scrollToRowAtIndexPath(indexPath : NSIndexPath, atScrollPosition : UITableViewScrollPosition, animated : Bool);

I'm too tired to write the code, so I'm going to try to explain. First, for every cell you set alpha to 0, as soon as they get loaded (cellForRowAtIndexPath). Then let's suppose our screen fits the 5 first rows. You are going to animate their alphas sequentially (using UIView.animateWithDuration ) until the fifth one (index 4), then you are going to scrollToRowAtIndexPath passing NSIndexPath using 5, then 6,... until the rest of them (using scrollPosition = .Bottom). And for each of them, you would animate as soon as they get loaded. Just remember to put some time between this interactions. (animate first, run NSTimer to the second, and it goes on). And the boolean animated should be true of course.



回答2:

Step-1

In your cellForRowAtIndexPath method where initialize your cell, hide it like that;

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell     {
    let cell: TblCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TblCell
    cell.continueLabel.textAlignment = .justified
    cell.contentView.alpha = 0
    return cell
}

Step-2

Let's make fade animation. UITableViewDelegate has willDisplayCell method which is able to detect that when you scroll to top or bottom, first cell will display on the window.

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    UIView.animate(withDuration: 0.8, animations: {
        cell.contentView.alpha = 1
    })   
}

Your fade animation is on the progress. The most important thing is that you can not setup your cell's alpha directly in runtime because iOS is doing some special internal handling with the cell as part of your UITableView and ignores your setup. So if you setup your cell's contentView, everything's gonna be fine.



回答3:

Here is some code which can get you started. In my COBezierTableView I subclassed UITableView and override the layoutSubviewsmethod. In there you can manipulate the cells according to their relative position in the view. In this example I fade them out in the bottom.

import UIKit

public class MyCustomTableView: UITableView {

    // MARK: - Layout

    public override func layoutSubviews() {
        super.layoutSubviews()

        let indexpaths = indexPathsForVisibleRows!
        let totalVisibleCells = indexpaths.count - 1
        if totalVisibleCells <= 0 { return }

        for index in 0...totalVisibleCells {
            let indexPath = indexpaths[index] 
            if let cell = cellForRowAtIndexPath(indexPath) {
                if let superView = superview {
                    let point = convertPoint(cell.frame.origin, toView:superView)
                    let pointScale = point.y / CGFloat(superView.bounds.size.height)
                    cell.contentView.alpha = 1 - pointScale
                }
            }
        }
    }
}


回答4:

To appear each visible cell one by one, you can do it by playing with alpha and duration value.

extension UITableView {

    func fadeVisibleCells() {

        var delayCounter = 0.0

        for cell in self.visibleCells {

            cell.alpha = 0.0

            UIView.animate(withDuration: TimeInterval(delayCounter)) {
                cell.alpha = 1.0
            }

            delayCounter += 0.30
        }
    }
}


回答5:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell .alpha = 1.0
         let transform = CATransform3DTranslate(CATransform3DIdentity, 0, 3000, 1200)
       //let transform = CATransform3DTranslate(CATransform3DIdentity, 250, 0, 1250)
     //let transform = CATransform3DTranslate(CATransform3DIdentity, 250, 1250, 0)
      // let transform = CATransform3DTranslate(CATransform3DIdentity, -250, 300, 120)


   cell.layer.transform = transform




    UIView.animate(withDuration: 1.0) {
        cell.alpha = 1.0
        cell.layer.transform = CATransform3DIdentity
        cell.layer.transform = CATransform3DIdentity
    }
}