iOS-Swift-MJRefresh重写

作者: GTMYang | 来源:发表于2016-12-10 12:08 被阅读1496次
美景如画
GTMRefresh github
===================
GTMRefresh 用Swift重写的MJRefresh

Introduction

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

Demo

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

alt tag
alt tag
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 {
        [weak self] in
        print("excute refreshBlock")
        self.refresh()
    }

    self.tableView.gtm_addLoadMoreFooterView {
        [weak 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 UIKit
import GTMRefresh


class 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()) {
        [weak 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
}

相关文章

  • iOS-Swift-MJRefresh重写

    Introduction 自定义方便, Demo里面有国内主流App的下拉效果的模仿 代码简洁,总代码量不超过10...

  • iOS-Swift-MJRefresh

    前言 本篇文章较为基础,只是为了让新手尽快熟悉swift下的一些操作 最近用swift写项目的公司越来越多了,对于...

  • 重写,重写,重写 - 草稿

    重要的事情说三次,这是我本该早就发布的文章,由于我的失误,于是乎,现在写这篇文的时候,带着淡淡的忧伤。 今年,最快...

  • GeekBand OC 7. 多态

    运行时多态 重写override 重写方法 没有重写的方法会被重写 没有重写的方法中调用已经重写的方法会调用重写后...

  • Swift 重写override和重载overload

    1.重写override 重写是子类继承父类,重写父类的方法。 重写方法的参数列表必须完全与被重写的方法相同。重写...

  • swift overrid 跟 overload

    1.重写override 重写是子类继承父类,重写父类的方法。 重写方法的参数列表必须完全与被重写的方法相同。重写...

  • apache URL重写

    URL重写 URL rewrite介绍 URL重写 一、URL重写介绍 Apached的重写功能,即是mod_re...

  • swift中的继承

    只有类支持继承 重写实例方法、下标 重写类型方法、下标 用class修饰的可以被重写 重写属性 1.重写实例属性 ...

  • 第三章所有对象的通用方法

    目录 重写equals方法时遵守通用约定 重写equals方法时同时也要重写hashcode方法 始终重写 toS...

  • 重写(=覆盖)、重载

    override(重写、覆盖): 子类在继承父类时,重写(重新实现)父类中的方法。 重写(覆盖)的规则: 重写方法...

网友评论

  • wenshuaiDev:按钮点击调用triggerRefreshing() 下拉刷新的图片 就不显示了是什么原因呢。。。
  • wenshuaiDev:支持!! 感谢
  • 小迪_bd7a:1.3.3 GTMRefresh文件哪里去了?import GTMRefresh没有
  • 幻想无极:上拉加载有bug...
    GTMYang:@幻想无极 我昨天晚上调整了下,你看看你说的问题修复没。最新版本1.3.3
    幻想无极:@GTMYang 上拉加载空出了很大一截,cocopods拉的,而且不写延时的话下方的字要滚动到中间再滚下去
    GTMYang:什么问题?
  • 幻想无极:你的上拉加在怎么加载很久啊
    GTMYang:加载很久的问题已经修复了
  • 赤兔人生:楼主你好,pod 的版本好像是 1.1.3 的,方便更新下吗?
    赤兔人生:@GTMYang 谢谢 ,已经好了
    GTMYang:-> GTMRefresh (1.3.1)
    swift 实现的上拉刷新,下拉加载动效库
    pod 'GTMRefresh', '~> 1.3.1'
    - Homepage: https://github.com/GTMYang/GTMRefresh
    - Source: https://github.com/GTMYang/GTMRefresh.git
    - Versions: 1.3.1, 1.3, 1.1.3, 1.1.2, 1.1.0, 1.0.0, 0.0.3, 0.0.2, 0.0.1
    [master repo]
    GTMYang:你pod search GTMRefresh看一下
  • Mr_Jee:新版本1.1.2,设置代理,如何使用???
    GTMYang:最新版本改回block了
  • 47dc4c386a66:怎么修改字体颜色呢
    GTMYang:新版本支持修改文字颜色了
    GTMYang:这样吧,新版本中我把Label开放出来,这样就可以随便调整
    GTMYang:只能通过自定义的方式
  • 旅橙:你这个效果更丰富,学习了,
    GTMYang:@旅橙 帮我star谢谢
  • a1ca31b58342:楼主的,您这个在pod install的时候找不到..
    a1ca31b58342:@GTMYang pod install之后报错
    Analyzing dependencies
    [!] Unable to find a specification for `GTMRefresh`
    GTMYang:@JngViho 我刚测试了一下可以,你那边报什么错误没有?
    GTMYang:@JngViho 我这边可以,我再看一下
  • GTMYang:不错不错:+1:

本文标题:iOS-Swift-MJRefresh重写

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