自定义下拉刷新渐变动画

实现思路

1.用ta b le view指定了刷新的内容区域,当下拉刷新时,若超出了table的内容的空白区域,系统会自动弹回内容的原位置。因此可以将刷新的vie w放在scrollview的上面

2.随着用户的滚动更新refresh vie w中的内容,根据用户向下拉动的远近来改变view背景色,视差滚动

3.用户松开结束滚动时,应该进行一次判断,判断用户是否要刷新页面。因为刷新将伴随着网络下载。只有当滚动到足够距离的时候,才认为是下拉刷新。
此时才回锁定到刷新的页面,并让其保持可见的状态。做动画的处理

此时心中会有一些问题

如何追踪用户的滚动进度?

*refreshview的可见区域的高度= content offset.y - contentInset.top.y

上代码

1.准备工作要注意的地方,我用图片进行展示


创建的类别
自定义下拉刷新渐变动画_第1张图片
视图控制器.png
自定义下拉刷新渐变动画_第2张图片
导航控制器.png
自定义下拉刷新渐变动画_第3张图片
ui tableview ce l l.png

2.创建刷新的视图:RefreshView.swift
`private unowned var scrollView : UIScrollView //unowened相当于o c的weak

init(frame : CGRect, scrollView : UIScrollView) {
    self.scrollView = scrollView;
    super.init(frame: frame)
    backgroundColor = UIColor.green
    
}

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

`

让刷新视图相应用户下拉的操作
当用户下拉table的时候会响应系统的一个通知,因此会响应scrollviewdidscroll方法

下拉刷新的渐变效果核心代码如下:

//在refreshviewcontroller中
override func scrollViewDidScroll(_ scrollView: UIScrollView) { //把通知传递给refreshview,让他进行相应的变化 refreshView.scrollViewDidScroll(scrollView: scrollView) }

//在refresh view 中

` func updateBackgroundColor() {
backgroundColor = UIColor(white: 0.7*progress + 0.2, alpha: 1.0)
}

func scrollViewDidScroll(scrollView: UIScrollView) {
    //刷新视图可见的区域
    let refreshHeight = max(0,  -scrollView.contentOffset.y - scrollView.contentInset.top)
    //场景的高度
    progress = min(1, refreshHeight/kSceneHeight)
    
    //根据进度来改变背景色
    updateBackgroundColor()
    
}`

视差滚动,即界面中的所有控件的动画,以不同的速度进行移动时,产生的立体的效果

确定一个动画需要知道控件的起始位置,结束位置,路径
它们之间的关系是 起始位置的y值 = 结束位置的y值 + 移动速率*场景的高度

创建一个工具类RefreshIterm.swift来处理动画的路径
`private var centerStart: CGPoint
private var centerEnd: CGPoint
unowned var view: UIView

//起始位置
init(view: UIView, centerEnd: CGPoint, parallaxRatio: CGFloat, sceneHeight: CGFloat) {
    self.view = view
    self.centerEnd = centerEnd
    centerStart = CGPoint(x: centerEnd.x, y: centerEnd.y + (parallaxRatio * sceneHeight))
    self.view.center = centerStart
}

//跟据下拉的进度确定控件的位置
func updateViewPositionForPercentage(percentage: CGFloat) {
    view.center = CGPoint(
        x: centerStart.x + (centerEnd.x - centerStart.x) * percentage,
        y: centerStart.y + (centerEnd.y - centerStart.y) * percentage)
}`

在refresh view中加载做动画的控件
`func setupRefreshItems() {
let groundImageView = UIImageView(image: UIImage(named: "ground"))
let buildingsImageView = UIImageView(image: UIImage(named: "buildings"))

    refreshItems = [
        RefreshIterm(view: buildingsImageView, centerEnd: CGPoint(x: bounds.midX,
                                                                  y: bounds.height - groundImageView.bounds.height - buildingsImageView.bounds.height / 2), parallaxRatio: 1.5, sceneHeight: kSceneHeight),
        RefreshIterm (view: groundImageView,
                                 centerEnd: CGPoint(x: bounds.midX,
                                                    y: bounds.height - groundImageView.bounds.height/2),
                                 parallaxRatio: 0.5, sceneHeight: kSceneHeight),
        
    ]
    
    for refreshItem in refreshItems {
        addSubview(refreshItem.view)
    }
}`

控件滚动的时候,改变控件的位置

func updateRefreshItemPositions() { for refreshItem in refreshItems { refreshItem.updateViewPositionForPercentage(percentage: progress) } }

自定义动画的刷新和锁定,通过判断用户是不是拉的足够远来决定是否要执行刷新的操作

首先声明一个de le ga te属性,在声明一个是否刷新的状态变量isrefreshing

开始刷新,调用UI view的animateWithDuration方法,将scrollview的contentins e t加上上场景的高度

出发刷新,首先不是正在刷新,下拉的进度最大时 ,触发刷新。

触发代理使控制器进行刷新操作

核心代码:
` func beginRefreshing() {
isRefreshing = true

    UIView.animate(withDuration: 0.4, delay: 0, options: .curveEaseInOut, animations: { () -> Void in
        self.scrollView.contentInset.top += kSceneHeight
    }) { (_) -> Void in
    }
}`

func endRefreshing() { UIView.animate(withDuration: 0.4, delay: 0, options: .curveEaseInOut, animations: { () -> Void in self.scrollView.contentInset.top -= kSceneHeight }) { (_) -> Void in self.isRefreshing = false } }

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { if !isRefreshing && progress == 1 { beginRefreshing() // -scrollView.contentInset.top delegate?.refreshViewDidRefresh(refreshView: self) } }

运行效果为:

自定义下拉刷新渐变动画_第4张图片
Untitled.gif

demo地址下载

你可能感兴趣的:(自定义下拉刷新渐变动画)