Swift重写MJRefresh

来源:互联网 发布:淘宝卖家号 买东西显示 编辑:程序博客网 时间:2024/06/10 12:22

alt tag

GTMRefresh

github地址
简书地址

GTMRefresh 用Swift重写的MJRefresh

Introduction

  • 自定义方便, Demo里面有国内主流App的下拉效果的模仿
  • 代码简洁,总代码量不超过1000行
  • 支持国际化
  • 支持: UITableView, UICollectionView, UIScrollView, UIWebView

Demo

直接下载代码,里面Demo里面有各种效果的自定义效果(因为时间比较紧,demo代码可能不够漂亮)

alt tag

Demo模仿的下拉效果

  • YahooWeather
  • Curve Mask
  • Youku
  • TaoBao
  • QQ Video
  • DianPing
  • QQ

Installation

Cocoapods

Install Cocoapods if need be.

$ gem install cocoapods

Add GTMRefresh in your Podfile.

use_frameworks!pod 'GTMRefresh'

Then, run the following command.

$ pod install

Manual

Copy GTMRefresh folder to your project. That’s it.

Note: Make sure that all files in GTMRefresh included in Compile Sources in Build Phases.

版本

Vesrion 0.0.1

This version requires Xcode 8.0 and Swift 3.

使用帮助

Firstly, import GTMRefresh.

import GTMRefresh

使用默认的下拉和上拉效果

    self.tableView.gtm_addRefreshHeaderView {        [unowned self] in        print("excute refreshBlock")        self.refresh()    }    self.tableView.gtm_addLoadMoreFooterView {        [unowned self] in        print("excute loadMoreBlock")        self.loadMore()    }

代码触发刷新

    self.tableView.triggerRefreshing()

自定义下拉刷新效果

约定
- 必须继承 GTMRefreshHeader
- 必须实现 SubGTMRefreshHeaderProtocol

SubGTMRefreshHeaderProtocol

public protocol SubGTMRefreshHeaderProtocol {    /// 状态变成.idle    func toNormalState()    /// 状态变成.refreshing    func toRefreshingState()    /// 状态变成.pulling    func toPullingState()    /// 状态变成.willRefresh    func toWillRefreshState()    /// 下拉高度/触发高度 值改变    func changePullingPercent(percent: CGFloat)    /// 开始结束动画前执行    func willBeginEndRefershing(isSuccess: Bool)    /// 结束动画完成后执行    func willCompleteEndRefershing()    /// 控件的高度    ///    /// - Returns: 控件的高度    func contentHeight() -> CGFloat}

特殊效果的实现

  • 当触发刷新的高度和控件高度不一样时重写willRefresHeight(),如Demo里的:Curve Mask
    /// 即将触发刷新的高度(特殊的控件需要重写该方法,返回不同的数值)    ///    /// - Returns: 触发刷新的高度    open func willRefresHeight() -> CGFloat {        return self.mj_h // 默认使用控件高度    }
  • 当Loadding动画显示区域的高度和控件高度不一样时重写refreshingHoldHeight(),如Demo里的:QQ
    /// Loadding动画显示区域的高度(特殊的控件需要重写该方法,返回不同的数值)    ///    /// - Returns: Loadding动画显示区域的高度    open func refreshingHoldHeight() -> CGFloat {        return self.mj_h // 默认使用控件高度    }

Example

////  TaoBaoRefreshHeader.swift//  PullToRefreshKit////  Created by luoyang on 10/12/16.//  Copyright © 2016年 luoyang. All rights reserved.//import UIKitimport GTMRefreshclass TaoBaoRefreshHeader: GTMRefreshHeader, SubGTMRefreshHeaderProtocol {    fileprivate let circleLayer = CAShapeLayer()    fileprivate let arrowLayer = CAShapeLayer()    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 230, height: 35))    fileprivate let textLabel = UILabel()    fileprivate let strokeColor = UIColor(red: 135.0/255.0, green: 136.0/255.0, blue: 137.0/255.0, alpha: 1.0)    override init(frame: CGRect) {        super.init(frame: frame)        setUpCircleLayer()        setUpArrowLayer()        textLabel.textAlignment = .center        textLabel.textColor = UIColor.lightGray        textLabel.font = UIFont.systemFont(ofSize: 14)        textLabel.text = "下拉即可刷新..."        imageView.image = UIImage(named: "taobaoLogo")        self.contentView.addSubview(imageView)        self.contentView.addSubview(textLabel)    }    func setUpArrowLayer(){        let bezierPath = UIBezierPath()        bezierPath.move(to: CGPoint(x: 20, y: 15))        bezierPath.addLine(to: CGPoint(x: 20, y: 25))        bezierPath.addLine(to: CGPoint(x: 25,y: 20))        bezierPath.move(to: CGPoint(x: 20, y: 25))        bezierPath.addLine(to: CGPoint(x: 15, y: 20))        self.arrowLayer.path = bezierPath.cgPath        self.arrowLayer.strokeColor = UIColor.lightGray.cgColor        self.arrowLayer.fillColor = UIColor.clear.cgColor        self.arrowLayer.lineWidth = 1.0        self.arrowLayer.lineCap = kCALineCapRound        self.arrowLayer.bounds = CGRect(x: 0, y: 0,width: 40, height: 40)        self.arrowLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)        self.layer.addSublayer(self.arrowLayer)    }    func setUpCircleLayer(){        let bezierPath = UIBezierPath(arcCenter: CGPoint(x: 20, y: 20),                                        radius: 12.0,                                        startAngle:CGFloat(-M_PI/2),                                        endAngle: CGFloat(M_PI_2 * 3),                                        clockwise: true)        self.circleLayer.path = bezierPath.cgPath        self.circleLayer.strokeColor = UIColor.lightGray.cgColor        self.circleLayer.fillColor = UIColor.clear.cgColor        self.circleLayer.strokeStart = 0.05        self.circleLayer.strokeEnd = 0.05        self.circleLayer.lineWidth = 1.0        self.circleLayer.lineCap = kCALineCapRound        self.circleLayer.bounds = CGRect(x: 0, y: 0,width: 40, height: 40)        self.circleLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)        self.layer.addSublayer(self.circleLayer)    }    required init?(coder aDecoder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }    override func layoutSubviews() {        super.layoutSubviews()        textLabel.frame = CGRect(x: 0,y: 0,width: 120, height: 40)        //放置Views和Layer        imageView.center = CGPoint(x: frame.width/2, y: frame.height - 60 - 18)        textLabel.center = CGPoint(x: frame.width/2 + 20, y: frame.height - 30)        self.arrowLayer.position = CGPoint(x: frame.width/2 - 60, y: frame.height - 30)        self.circleLayer.position = CGPoint(x: frame.width/2 - 60, y: frame.height - 30)    }    func toNormalState() {}    func toRefreshingState() {        self.circleLayer.strokeEnd = 0.95        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.z")        rotateAnimation.toValue = NSNumber(value: M_PI * 2.0 as Double)        rotateAnimation.duration = 0.6        rotateAnimation.isCumulative = true        rotateAnimation.repeatCount = 10000000        self.circleLayer.add(rotateAnimation, forKey: "rotate")        self.arrowLayer.isHidden = true        textLabel.text = "刷新中..."    }    func toPullingState() {}    func toWillRefreshState() {}    func changePullingPercent(percent: CGFloat) {        let adjustPercent = max(min(1.0, percent),0.0)        if adjustPercent  == 1.0{            textLabel.text = "释放即可刷新..."        }else{            textLabel.text = "下拉即可刷新..."        }        self.circleLayer.strokeEnd = 0.05 + 0.9 * adjustPercent    }    func willBeginEndRefershing(isSuccess: Bool) {}    func willCompleteEndRefershing() {        transitionWithOutAnimation {            self.circleLayer.strokeEnd = 0.05        };        self.circleLayer.removeAllAnimations()        self.arrowLayer.isHidden = false        textLabel.text = "下拉即可刷新"    }    func contentHeight()->CGFloat{        return 60    }    /// MARK: Private    func transitionWithOutAnimation(_ clousre:()->()){        CATransaction.begin()        CATransaction.setDisableActions(true)        clousre()        CATransaction.commit()    }}

自定义控件的使用

    self.tableView.gtm_addRefreshHeaderView(refreshHeader: CustomRefreshHeader()) {        [unowned self] in        print("excute refreshBlock")        self.refresh()    }

自定义上拉加载效果

约定
- 必须继承 GTMLoadMoreFooter
- 必须实现 SubGTMLoadMoreFooterProtocol

SubGTMLoadMoreFooterProtocol

public protocol SubGTMLoadMoreFooterProtocol {    func toNormalState()    func toNoMoreDataState()    func toWillRefreshState()    func toRefreshingState()    /// 控件的高度(自定义控件通过该方法设置自定义高度)    ///    /// - Returns: 控件的高度    func contentHeith() -> CGFloat}
0 0
原创粉丝点击