TwinklingRefreshLayout 小而強(qiáng)大的刷新控件,自帶順滑的越界回彈就斤,v1.04 版重大發(fā)布啦悍募!

TwinklingRefreshLayout v1.04 版精心重構(gòu),優(yōu)化 UI洋机、刷新及越界動(dòng)畫效果坠宴,修復(fù)眾多 bug,完美發(fā)布槐秧!
TwinklingRefreshLayout延伸了Google的SwipeRefreshLayout的思想,不在列表控件上動(dòng)刀,而是使用一個(gè)ViewGroup來包含列表控件,以保持其較低的耦合性和較高的通用性啄踊。其主要特性有:

  1. 支持RecyclerView、ScrollView刁标、AbsListView系列(ListView颠通、GridView)、WebView以及其它可以獲取到scrollY的控件
  2. 支持加載更多
  3. 默認(rèn)支持 越界回彈膀懈,隨手勢(shì)速度有不同的效果
  4. 可開啟沒有刷新控件的純凈越界回彈模式
  5. setOnRefreshListener中擁有大量可以回調(diào)的方法
  6. 將Header和Footer抽象成了接口,并回調(diào)了滑動(dòng)過程中的系數(shù),方便實(shí)現(xiàn)個(gè)性化的Header和Footer

Demo

下載Demo

You can download the Video for more details.

使用方法

1.添加gradle依賴

將libray模塊復(fù)制到項(xiàng)目中,或者直接在build.gradle中依賴:

compile 'com.lcodecorex:tkrefreshlayout:1.0.4'

2.在xml中添加TwinklingRefreshLayout

<?xml version="1.0" encoding="utf-8"?>
<com.lcodecore.tkrefreshlayout.TwinklingRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/refreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:tr_wave_height="180dp"
    app:tr_head_height="100dp">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        android:background="#fff" />
</com.lcodecore.library.TwinklingRefreshLayout>

Android系統(tǒng)為了跟iOS不一樣顿锰,當(dāng)界面OverScroll的時(shí)候會(huì)顯示一個(gè)陰影。為了達(dá)到更好的顯示效果启搂,最好禁用系統(tǒng)的overScroll硼控,如上給RecyclerView添加android:overScrollMode="never"

3.在Activity或者Fragment中配置

TwinklingRefreshLayout不會(huì)自動(dòng)結(jié)束刷新或者加載更多胳赌,需要手動(dòng)控制
refreshLayout.setOnRefreshListener(new RefreshListenerAdapter(){
            @Override
            public void onRefresh(final TwinklingRefreshLayout refreshLayout) {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        refreshLayout.finishRefreshing();
                    }
                },2000);
            }

            @Override
            public void onLoadMore(final TwinklingRefreshLayout refreshLayout) {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        refreshLayout.finishLoadmore();
                    }
                },2000);
            }
        });
    }

使用finishRefreshing()方法結(jié)束刷新牢撼,finishLoadmore()方法結(jié)束加載更多。此處OnRefreshListener還有其它方法疑苫,可以選擇需要的來重寫熏版。

如果你想進(jìn)入到界面的時(shí)候主動(dòng)調(diào)用下刷新,可以調(diào)用startRefresh()/startLoadmore()方法捍掺。

setWaveHeight撼短、setHeaderHeight、setBottomHeight挺勿、setOverScrollHeight
  • setWaveHeight 設(shè)置頭部可拉伸的最大高度曲横。
  • setHeaderHeight 頭部固定高度(在此高度上顯示刷新狀態(tài))
  • setBottomHeight 底部高度
  • setOverScrollHeight 設(shè)置最大的越界高度

setEnableRefresh、setEnableLoadmore

靈活的設(shè)置是否禁用上下拉不瓶。

setHeaderView(IHeaderView headerView)禾嫉、setBottomView(IBottomView bottomView)

設(shè)置頭部/底部個(gè)性化刷新效果灾杰,頭部需要實(shí)現(xiàn)IHeaderView,底部需要實(shí)現(xiàn)IBottomView夭织。

setEnableOverScroll

是否允許越界回彈吭露。

setOverScrollTopShow吠撮、setOverScrollBottomShow尊惰、setOverScrollRefreshShow

是否允許在越界的時(shí)候顯示刷新控件,默認(rèn)是允許的泥兰,也就是Fling越界的時(shí)候Header或Footer照常顯示弄屡,反之就是不顯示;可能有特殊的情況鞋诗,刷新控件會(huì)影響顯示體驗(yàn)才設(shè)立了這個(gè)狀態(tài)膀捷。

setPureScrollModeOn()

開啟純凈的越界回彈模式,也就是所有刷新相關(guān)的View都不顯示削彬,只顯示越界回彈效果

setAutoLoadMore

是否在底部越界的時(shí)候自動(dòng)切換到加載更多模式

addFixedExHeader

添加一個(gè)固定在頂部的Header(效果還需要優(yōu)化)

startRefresh全庸、startLoadMore、finishRefreshing融痛、finishLoadmore
setFloatRefresh(boolean)

支持切換到像SwipeRefreshLayout一樣的懸浮刷新模式了壶笼。

4.擴(kuò)展屬性

  • tr_wave_height 頭部拉伸允許的最大高度
  • tr_head_height 頭部高度
  • tr_bottom_height 底部高度
  • tr_overscroll_height 允許越界的最大高度
  • tr_enable_loadmore 是否允許加載更多,默認(rèn)為true
  • tr_pureScrollMode_on 是否開啟純凈的越界回彈模式
  • tr_overscroll_top_show - 否允許頂部越界時(shí)顯示頂部View
  • tr_overscroll_bottom_show 是否允許底部越界時(shí)顯示底部View
  • tr_enable_overscroll 是否允許越界回彈

其它說明

1.默認(rèn)支持越界回彈,并可以隨手勢(shì)越界不同的高度

這一點(diǎn)很多類似SwipeRefreshLayout的刷新控件都沒有做到(包括SwipeRefreshLayout),因?yàn)闆]有攔截下來的時(shí)間會(huì)傳遞給列表控件雁刷,而列表控件的滾動(dòng)狀態(tài)很難獲取覆劈。解決方案就是給列表控件設(shè)置了OnTouchListener并把事件交給GestureDetector處理,然后在列表控件的OnScrollListener中監(jiān)聽View是否滾動(dòng)到了頂部(沒有OnScrollListener的則采用延時(shí)監(jiān)聽策略)。

2.setOnRefreshListener大量可以回調(diào)的方法

  • onPullingDown(TwinklingRefreshLayout refreshLayout, float fraction) 正在下拉的過程
  • onPullingUp(TwinklingRefreshLayout refreshLayout, float fraction) 正在上拉的過程
  • onPullDownReleasing(TwinklingRefreshLayout refreshLayout, float fraction) 下拉釋放過程
  • onPullUpReleasing(TwinklingRefreshLayout refreshLayout, float fraction) 上拉釋放過程
  • onRefresh(TwinklingRefreshLayout refreshLayout) 正在刷新
  • onLoadMore(TwinklingRefreshLayout refreshLayout) 正在加載更多

其中fraction表示當(dāng)前下拉的距離與Header高度的比值(或者當(dāng)前上拉距離與Footer高度的比值)沛励。

3.Header和Footer

BezierLayout(pic 4)
  • setWaveColor
  • setRippleColor
GoogleDotView(pic 5)
SinaRefreshView(pic 3)
  • setArrowResource
  • setTextColor
  • setPullDownStr
  • setReleaseRefreshStr
  • setRefreshingStr
ProgressLayout(SwipeRefreshLayout pic 6)
  • setProgressBackgroundColorSchemeResource(@ColorRes int colorRes)
  • setProgressBackgroundColorSchemeColor(@ColorInt int color)
  • setColorSchemeResources(@ColorRes int... colorResIds)

Footer

BottomProgressView(pic 2)
  • setNormalColor(@ColorInt int color)
  • setAnimatingColor(@ColorInt int color)
LoadingView(pic 3)

更多動(dòng)效可以參考AVLoadingIndicatorView庫责语。

3.實(shí)現(xiàn)個(gè)性化的Header和Footer

相關(guān)接口分別為IHeaderView和IBottomView,代碼如下:

public interface IHeaderView {
    View getView();

    void onPullingDown(float fraction,float maxHeadHeight,float headHeight);

    void onPullReleasing(float fraction,float maxHeadHeight,float headHeight);

    void startAnim(float maxHeadHeight,float headHeight);

    void reset();
}

其中g(shù)etView()方法用于在TwinklingRefreshLayout中獲取到實(shí)際的Header,因此不能返回null。

實(shí)現(xiàn)像新浪微博那樣的刷新效果(有部分修改,具體請(qǐng)看源碼),實(shí)現(xiàn)代碼如下:

1.首先定義SinaRefreshHeader繼承自FrameLayout并實(shí)現(xiàn)IHeaderView方法

2.getView()方法中返回this

3.在onAttachedToWindow()或者構(gòu)造函數(shù)方法中獲取一下需要用到的布局

@Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        if (rootView == null) {
            rootView = View.inflate(getContext(), R.layout.view_sinaheader, null);
            refreshArrow = (ImageView) rootView.findViewById(R.id.iv_arrow);
            refreshTextView = (TextView) rootView.findViewById(R.id.tv);
            loadingView = (ImageView) rootView.findViewById(R.id.iv_loading);
            addView(rootView);
        }
    }

4.實(shí)現(xiàn)其它方法

@Override
    public void onPullingDown(float fraction, float maxHeadHeight, float headHeight) {
        if (fraction < 1f) refreshTextView.setText(pullDownStr);
        if (fraction > 1f) refreshTextView.setText(releaseRefreshStr);
        refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);


    }

    @Override
    public void onPullReleasing(float fraction, float maxHeadHeight, float headHeight) {
        if (fraction < 1f) {
            refreshTextView.setText(pullDownStr);
            refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180);
            if (refreshArrow.getVisibility() == GONE) {
                refreshArrow.setVisibility(VISIBLE);
                loadingView.setVisibility(GONE);
            }
        }
    }

    @Override
    public void startAnim(float maxHeadHeight, float headHeight) {
        refreshTextView.setText(refreshingStr);
        refreshArrow.setVisibility(GONE);
        loadingView.setVisibility(VISIBLE);
    }

5.布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">
    <ImageView
        android:id="@+id/iv_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_arrow"/>

    <ImageView
        android:id="@+id/iv_loading"
        android:visibility="gone"
        android:layout_width="34dp"
        android:layout_height="34dp"
        android:src="@drawable/anim_loading_view"/>

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:textSize="16sp"
        android:text="下拉刷新"/>
</LinearLayout>

注意fraction的使用,比如上面的代碼refreshArrow.setRotation(fraction * headHeight / maxHeadHeight * 180)目派,fraction * headHeight表示當(dāng)前頭部滑動(dòng)的距離坤候,然后算出它和最大高度的比例,然后乘以180企蹭,可以使得在滑動(dòng)到最大距離時(shí)Arrow恰好能旋轉(zhuǎn)180度白筹。

onPullingDown/onPullingUp表示正在下拉/正在上拉的過程。
onPullReleasing表示向上拉/下拉釋放時(shí)回調(diào)的狀態(tài)练对。
startAnim則是在onRefresh/onLoadMore之后才會(huì)回調(diào)的過程(此處是顯示了加載中的小菊花)

如上所示遍蟋,輕而易舉就可以實(shí)現(xiàn)一個(gè)個(gè)性化的Header或者Footer。(更簡(jiǎn)單的實(shí)現(xiàn)請(qǐng)參考Demo中的 TextHeaderView(圖四))螟凭。

TODO

  • 制作一個(gè)star相關(guān)的動(dòng)效
  • CoordinateLayout及NestedScroll支持
  • 帶視差效果的Header

更新日志

v1.04

新增功能
  • 第二次重構(gòu)完成,將核心邏輯拆分為RefreshProcessor虚青、AnimProcessor、OverScrollProcessor螺男、CoProcessor
  • 優(yōu)化越界策越棒厘,手勢(shì)決定越界高度
  • 優(yōu)化界面流暢度
  • 添加類似SwipeRefreshLayout的懸浮刷新功能(ProgressLayout)
  • 滑到底部自動(dòng)加載更多or回彈可選纵穿,默認(rèn)為回彈
  • 允許在結(jié)束刷新之前執(zhí)行一個(gè)動(dòng)效:IHeadView.onFinish(animEndListener)
  • 新增支持Header(Beta)
  • 優(yōu)化BezierLayout、SinaRefreshLayout等的顯示并增加調(diào)節(jié)屬性
  • 新增支持設(shè)置是否允許OverScroll
fixed bugs
  • 修復(fù)刷新或加載更多時(shí)奢人,列表item沒有鋪滿列表控件谓媒,滑動(dòng)無效的問題
  • 添加主動(dòng)刷新/加載更多的方法:startRefresh(),startLoadMore()
  • 修復(fù)頂部和底部越界高度不一致的問題
  • 修復(fù)WebView在底部fling時(shí)不能越界的問題
  • 動(dòng)畫執(zhí)行時(shí)間與高度相關(guān),動(dòng)效更加柔和

v1.03

  • 擴(kuò)展了更多的屬性
  • 修復(fù)Fragment回收導(dǎo)致的空指針異常問題
  • 加入x方向判斷,減小了滑動(dòng)沖突
  • 優(yōu)化加載更多列表顯示問題
  • 可以靈活的設(shè)置是否禁用上下拉
  • 修復(fù)GridView滑動(dòng)過程中出現(xiàn)的白條問題
  • Demo中添加輪播條展示

v1.02

  • 修復(fù)加載更多列表控件的顯示問題

v1.01

  • 支持了RecyclerView何乎、ScrollView句惯、AbsListView、WebView
  • 支持越界回彈
  • 支持個(gè)性化Header支救、Footer

ps:如有任何問題或者是建議抢野,可以郵箱聯(lián)系我!(lcodecore@163.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末各墨,一起剝皮案震驚了整個(gè)濱河市指孤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贬堵,老刑警劉巖恃轩,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異黎做,居然都是意外死亡叉跛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門引几,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昧互,“玉大人,你說我怎么就攤上這事伟桅〕ň颍” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵楣铁,是天一觀的道長(zhǎng)玖雁。 經(jīng)常有香客問我,道長(zhǎng)盖腕,這世上最難降的妖魔是什么赫冬? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮溃列,結(jié)果婚禮上劲厌,老公的妹妹穿的比我還像新娘。我一直安慰自己听隐,他們只是感情好补鼻,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般风范。 火紅的嫁衣襯著肌膚如雪咨跌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天硼婿,我揣著相機(jī)與錄音锌半,去河邊找鬼。 笑死寇漫,一個(gè)胖子當(dāng)著我的面吹牛刊殉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猪腕,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼冗澈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼钦勘!你這毒婦竟也來了陋葡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤彻采,失蹤者是張志新(化名)和其女友劉穎腐缤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肛响,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岭粤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了特笋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剃浇。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猎物,靈堂內(nèi)的尸體忽然破棺而出虎囚,到底是詐尸還是另有隱情,我是刑警寧澤蔫磨,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布淘讥,位于F島的核電站,受9級(jí)特大地震影響堤如,放射性物質(zhì)發(fā)生泄漏蒲列。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一搀罢、第九天 我趴在偏房一處隱蔽的房頂上張望蝗岖。 院中可真熱鬧,春花似錦榔至、人聲如沸抵赢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓣俯。三九已至杰标,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彩匕,已是汗流浹背腔剂。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驼仪,地道東北人掸犬。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像绪爸,于是被迫代替她去往敵國(guó)和親湾碎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容