1. 程式人生 > >iOS-Swift-MJRefresh 重寫控制元件

iOS-Swift-MJRefresh 重寫控制元件

alt tag

GTMRefresh

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

相關推薦

iOS-Swift-MJRefresh 重寫控制元件

GTMRefresh GTMRefresh 用Swift重寫的MJRefresh Introduction 自定義方便, Demo裡面有國內主流App的下拉效果的模仿 程式碼簡潔,總程式碼量不超過1000行 支援國際化 支援: UITab

ios-swift-為圖片控制元件(自定義控制元件)新增點選事件

@IBOutlet var img_guanggao: UIImageView! override func viewDidLoad() { super.viewDidLoad(

IOS版App的控制元件元素定位

前言 Android版App的控制元件元素可以通過Android studio自帶的工具uiautomatorviewer來協助定位! IOS版App的控制元件元素可以通過Appium來實現(未實現),或app-inspector來實現,在此記錄app-inspector的使用 安裝 一、安裝Node

iOS-自定義的控制元件UILabel、、、touches等系列事件不執行問題

本文首發地址 解決答案在最下面··· 1.場景描述場景描述 我繼承了UILabel搞了一個自定義的控制元件。 在搞上一些觸控事件 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)e

iOS UIView及其子控制元件的常用設定

為控制元件新增邊框 view.layer.borderWidth = 1; view.layer.borderColor = [[UIColor blackColor] CGColor]; b

android仿ios的時間滾動控制元件WheelView

<LinearLayout android:layout_width="200dp" android:orientation="horizontal" android:layout_gravity=

android仿ios實現分段選擇控制元件UISegmentedControl

在ios7中有一種扁平風格的控制元件叫做分段選擇控制元件UISegmentedControl,控制元件上橫放或豎放著幾個被簡單線條隔開的按鈕,每次點選能切換不同的按鈕和按鈕所對應的介面,比如qq客戶端V6.5.3版本中訊息頁與電話頁分離就是用的這種原理。但是很可

iOS開發——解決UIScrollView控制元件移動錯位和無法滾動

跟著iOS老師發的教程做了個簡陋的圖片瀏覽器,因為圖片太多展示不開所以想要用Scroll View來顯示,就自己試了一下。然而並沒有自己想象的那麼順利orz 當把要顯示的圖片都放置到Scroll View上時,它還是不會滾動。這時因為沒有設定他的content

Swift 畫線控制元件(支援xib和storyboard)

因專案中經常用到各種分割線,索性封裝了一個畫線的控制元件。 特性 支援在xib中使用 支援設定線的顏色 支援設定線的粗細 padding屬性 支援橫線和豎線 支援畫虛線 可設定虛線間隔 可

[ ios ] 摺疊顯示文字控制元件

使用第三方控制元件"ZybTextView",可以方便的摺疊顯示大量文字。只需呼叫初始化方法,指定要顯示的文字的標題陣列和內容陣列。 使用方法,1.匯入標頭檔案,2.呼叫初始化方法。程式碼與效果如下

c# 如何重寫控制元件的OnPaint事件

使用OnPaint事件可以隨時繪製圖形 呼叫窗體的OnPaint事件 protected override void OnPaint(PaintEventArgs e) {     base.OnPaint(e);    //繪圖 } 但是如何重寫控制元件的OnPaint

動態改變listctrl 單元格背景及文字顏色(非重寫控制元件)

CListCtrl 類裡面沒有直接改變單元格背景及文字顏色的成員函式,只有改變整個背景的顏色。我有時候只是需要把某個單元格的顏色改變來突出顯示就可以了: 我們可以通過過載ListCtrl控制元件的Customdraw 訊息,然後在裡面寫一些程式碼就可以了; void

swift 自定義控制元件在StoryBoard(xib)裡使用的屬性

有時候我們在StoryBoard裡用拖拽方法建立屬性的時候,總會有一些常用的屬性沒有提供視覺化操作,所以我們必須在連線類中用程式碼去實現,雖然也比較簡單,但是這樣重複的操作大大的增加了開發時間,如果能在拖拽的介面就能直接除錯相關屬性,就像一個UIView直接視覺化設定背景顏

iOS銀聯ApplePay控制元件開發

自從今早上蘋果準備向大陸開發Apple Pay,朋友圈以及各種QQ群裡就開始炸開了鍋,而且據說有幾個比較前衛的公司已經開始支援了Apple Pay,所以呢,我們的產品老大也閒不住了,加上自己還是比較感興趣的,於是乎,自己開始東西寫Demo了,就當趕個潮流吧。

iOS系統自帶控制元件 UIBarButtonSystemItem 的樣式解析

UIBarButtonSystemItem的樣式解析 樣式 圖片 UIBarButtonSystemItemDone UIBarButtonSystemItemCancel UIBarButton

ios 通過設定UI控制元件的center和size來設定位置時需注意!

<iframe id="iframeu848856_0" src="http://pos.baidu.com/mccm?rdid=848856&amp;dc=2&amp;di=u848856&amp;dri=0&amp;dis=0&amp;dai=2&

iOS 自定義重新整理控制元件UIScrollView (Refresh)

前言: 開發的時候經常會用到下拉重新整理這個控制元件,一直以來想自己寫一個,但是時間問題,都是使用別人寫好的,今天查了資料,自己自定一個 1.主要原理:        a.建立UIScrollView的類目 提供 類似addHeaderRefresh等方法,這樣tabl

iOS masonry動態約束控制元件位置

#import "FourViewController.h" #import "View+MASAdditions.h" #import "FiveViewControllerr.h" #define WS(weakSelf)  __weak __typeof(&

Android仿iOS左右滑動開關控制元件(Android4.0以上適用)

上週使用Android的switch模仿iOS的左右滑動開關控制元件,程式碼如下: aty_switch.xml: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android

ios學習之UI控制元件的一些基本使用

第一次寫部落格,主要是想記錄一下自己的對ios開發的一些心得 先上一張個人做的QQ登入介面的圖 在這個介面裡,有2個text,2個label,1個button,其中所有的屬性都是在inspector這裡面修改的,如圖所示藍色圖示即為inspector 在輸入QQ號和