master aae4f4a3304c cached
70 files
115.5 KB
29.8k tokens
324 symbols
1 requests
Download .txt
Repository: mylhyl/Android-CommonRefreshLayout
Branch: master
Commit: aae4f4a3304c
Files: 70
Total size: 115.5 KB

Directory structure:
gitextract_bdxoz3li/

├── .gitignore
├── README.md
├── build.gradle
├── commonrefreshlayout/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── mylhyl/
│       │               └── crlayout/
│       │                   └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── mylhyl/
│           │           └── crlayout/
│           │               ├── BaseSwipeRefresh.java
│           │               ├── MultiSwipeRefreshLayout.java
│           │               ├── SwipeRefreshAbsListView.java
│           │               ├── SwipeRefreshAdapterView.java
│           │               ├── SwipeRefreshExpandableListView.java
│           │               ├── SwipeRefreshGridView.java
│           │               ├── SwipeRefreshListView.java
│           │               ├── SwipeRefreshRecyclerView.java
│           │               ├── SwipeRefreshWebView.java
│           │               ├── app/
│           │               │   ├── BaseSwipeRefreshFragment.java
│           │               │   ├── SwipeRefreshAbsListFragment.java
│           │               │   ├── SwipeRefreshAdapterFragment.java
│           │               │   ├── SwipeRefreshExpandableListFragment.java
│           │               │   └── SwipeRefreshListFragment.java
│           │               └── internal/
│           │                   ├── ILoadSwipeRefresh.java
│           │                   ├── ISwipeRefresh.java
│           │                   ├── LoadConfig.java
│           │                   ├── LoadLayout.java
│           │                   ├── LoadLayoutBase.java
│           │                   └── LoadLayoutConvert.java
│           └── res/
│               └── values/
│                   └── attrs.xml
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── preview/
│   └── sample-debug.apk
├── sample/
│   ├── .gitignore
│   ├── build.gradle
│   ├── libs/
│   │   └── lite-http-3.0.0.jar
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── mylhyl/
│       │               └── crlayout/
│       │                   └── sample/
│       │                       └── ApplicationTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── mylhyl/
│       │   │           └── crlayout/
│       │   │               └── sample/
│       │   │                   ├── APP.java
│       │   │                   ├── MainActivity.java
│       │   │                   ├── TypesFragment.java
│       │   │                   ├── app/
│       │   │                   │   ├── AppExpandableListFragment.java
│       │   │                   │   ├── AppListFragment.java
│       │   │                   │   ├── GridViewFragment.java
│       │   │                   │   ├── ListViewFragment.java
│       │   │                   │   ├── RecyclerViewFragment.java
│       │   │                   │   └── WebViewFragment.java
│       │   │                   └── widget/
│       │   │                       └── MySwipeRefreshGridView.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── footer_progressbar.xml
│       │       │   └── selector_list.xml
│       │       ├── layout/
│       │       │   ├── fragment_grid_view.xml
│       │       │   ├── fragment_list_view.xml
│       │       │   ├── fragment_recycler_view.xml
│       │       │   ├── fragment_recycler_view_item.xml
│       │       │   ├── fragment_types.xml
│       │       │   ├── fragment_web_view.xml
│       │       │   ├── image_item.xml
│       │       │   └── swipe_refresh_footer.xml
│       │       ├── menu/
│       │       │   └── menu.xml
│       │       ├── values/
│       │       │   ├── array.xml
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       └── values-w820dp/
│       │           └── dimens.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── mylhyl/
│                       └── crlayout/
│                           └── sample/
│                               └── ExampleUnitTest.java
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.iml
.gradle
.idea
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures


================================================
FILE: README.md
================================================
#### Android-CommonRefreshLayout
基于`SwipeRefreshLayout`下拉刷新、上拉加载。支持的`AbsListView`、`RecycleView`、`WebView`

####特点
 * 在布局`layout`中使用,支持`xml`属性
 * 支持自动下拉刷新,什么用呢?比如进入界面时,只需要调用`autoRefresh()`方法即可,显示上拉动画同时刷新回调`onRefresh`将会被调用
 * 上拉加载支持自定义`View`或设置加载文字、动画、加载完成
 * 轻松设置`Adapter`空数据视图,默认为`TextView`支持更文字,也可自定义`View`
 * 对于简单的界面,例如只有`ListView`可以继承 [SwipeRefreshListFragment](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshListFragment.java)
   轻松搞定

####效果图
<img src="preview/gif.gif" width="240px"/>

####使用
  仔细看`listSelector`属性,我们是支持的,效果见`sample`
```xml
    <com.mylhyl.crlayout.SwipeRefreshListView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:crl="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/swipeRefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:listSelector="@drawable/selector_list"
        crl:load_text="数据正在加载中"
        crl:load_indeterminate_drawable="@drawable/footer_progressbar"
        tools:context=".app.ListViewFragment" />
```
 设置上拉加载,更多方法见 [LoadConfig](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadConfig.java)
```java
        LoadConfig loadConfig = swipeRefreshListView.getLoadConfig();
        loadConfig.setLoadText("set自定义加载");
        loadConfig.setIndeterminateDrawable(getResources().getDrawable(R.drawable.footer_progressbar));
```
或 xml属性配置,更多属生见[attrs](commonrefreshlayout/src/main/res/values/attrs.xml)
```xml
            crl:load_text="数据正在加载中"
            crl:load_indeterminate_drawable="@drawable/footer_progressbar"
```

 自定义上拉加载
 
 * 方式一:代码配置
 
```java
        getSwipeRefreshLayout().setLoadLayoutResource(R.layout.swipe_refresh_footer);
```
 * 方式二:xml属性配置
 
```xml
        crl:load_layout="@layout/swipe_refresh_footer"
```
 * 方式三:继承重写`getLoadLayoutResource()`方法
 
```java
        public class MySwipeRefreshGridView extends SwipeRefreshGridView {
        
            @Override
            protected int getLoadLayoutResource() {
                return R.layout.swipe_refresh_footer;
            }
        }
```
设置adapter空数据视图文字
```java
        swipeRefreshListView.setEmptyText("数据呢?");
```
 自定义adapter空数据视图
```java
        ImageView emptyView = new ImageView(getContext());
        emptyView.setImageResource(R.mipmap.empty);
        swipeRefreshGridView.setEmptyView(emptyView);
```
注册`ListView`长按事件怎么办?好说好说提供了方法`getScrollView()`,既然能获取`ListView`那`SwipeRefreshLayout`是不是也可以获取到呢?答案是肯定的,方法`getSwipeRefreshLayout`,你可以随心所欲设置下拉圆圈的颜色、大小等。
关于更多公开方法见 [ISwipeRefresh](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ISwipeRefresh.java)、[ILoadSwipeRefresh](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ILoadSwipeRefresh.java)

#### 注意事项
`setLoadAnimator`、`setLoadLayoutResource`方法须在`setOnListLoadListener`之前调用 

#### 使用Gradle构建时添加一下依赖即可:
```javascript
compile 'com.mylhyl:commonrefreshlayout:2.4'
```
#### 如果使用eclipse
只能`clone`源码,然后在 eclipse 中用`library`方式引用
     
#### [下载APK体验](preview/sample-debug.apk)

#### 更新日志
> 2.4 修复第二次setAdapter崩溃的问题,修改已知BUG

> 2.1 修复空数据视图不显示

> 2.0 UI编辑支持预览

> 1.9 优化代码

> 1.8 优化加载更多显示效果

> 1.7 新增`setEnabled`禁用下拉刷新

> 1.6 新增加载完成,命名`footer`修改为`load`

> 1.5 优化`SwipeRefreshWebView`的`autoRefresh`方法

> 1.4 优化`SwipeRefreshWebView`显示下拉动画

> 1.3 增加`autoRefresh(@ColorRes int... colorResIds)`方法,指定动画颜色

> 1.2 修复滑动到底部会上拉加载多次

> 1.1 修改为`recyclerview-v7:23.4.0`

> 1.0 初始版本


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'com.novoda:bintray-release:0.3.4'
    }
}

allprojects {
    repositories {
        jcenter()
    }
    tasks.withType(Javadoc) {
        options {
            encoding "UTF-8"
            charSet 'UTF-8'
            links "http://docs.oracle.com/javase/7/docs/api"
            failOnError false
        }
    }
}

================================================
FILE: commonrefreshlayout/.gitignore
================================================
/build


================================================
FILE: commonrefreshlayout/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'maven'
apply plugin: 'com.novoda.bintray-release'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "2017.5.26"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
        checkReleaseBuilds false
    }
}

dependencies {
    compile 'com.android.support:recyclerview-v7:23.4.0'
}

publish {
    userOrg = 'mylhyl'
    groupId = 'com.mylhyl'
    artifactId = 'commonrefreshlayout'
    version = '2.4'
    description = 'android pull refresh layout'
    website = "https://github.com/mylhyl/Android-CommonRefreshLayout"
}

================================================
FILE: commonrefreshlayout/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\android\android-sdk-windows/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: commonrefreshlayout/src/androidTest/java/com/mylhyl/crlayout/ApplicationTest.java
================================================
package com.mylhyl.crlayout;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: commonrefreshlayout/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mylhyl.crlayout">

    <application />
</manifest>


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/BaseSwipeRefresh.java
================================================
package com.mylhyl.crlayout;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.annotation.ColorRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.mylhyl.crlayout.internal.ISwipeRefresh;

/**
 * android v4 兼容包 中 SwipeRefreshLayout 刷新控件,支持上拉加载
 * <p/>
 * <pre>
 * 此处主要封装以下几点:
 * 1.手动刷新 {@link #autoRefresh() autoRefresh}
 * 2.支持上拉加载,并可自定义
 * 3.解决 SwipeRefreshLayout 与可滑动控件使用过程中冲突的问题
 * </pre>
 * Created by hupei on 2016/5/12.
 */
public abstract class BaseSwipeRefresh<T extends View> extends FrameLayout implements ISwipeRefresh {

    /**
     * 创建可滑动 View,子类实现
     *
     * @param context
     * @param attrs
     * @return
     */
    protected abstract T createScrollView(Context context, AttributeSet attrs);

    private FrameLayout mRefreshLayoutWrapper;
    protected MultiSwipeRefreshLayout mLoadSwipeRefresh;
    private T mScrollView;
    private View mEmptyView;
    private String mEmptyViewText = "";
    private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener;

    protected boolean isLoadCompleted;

    public BaseSwipeRefresh(Context context) {
        this(context, null);
    }

    public BaseSwipeRefresh(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseSwipeRefresh(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (!isInEditMode())
            init(context, attrs, defStyleAttr, 0);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public BaseSwipeRefresh(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        if (!isInEditMode())
            init(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        int[] crLayout = R.styleable.crLayout;
        if (crLayout != null && crLayout.length > 0) {
            final TypedArray a = context.obtainStyledAttributes(attrs, crLayout, defStyleAttr, defStyleRes);
            if (a != null) {
                mEmptyViewText = a.getString(R.styleable.crLayout_empty_text);
                a.recycle();
            }
        }
        mLoadSwipeRefresh = new MultiSwipeRefreshLayout(context, attrs);
        mScrollView = createScrollView(context, attrs);
        mEmptyView = createEmptyView(context);
        addSwipeRefreshView(context, mLoadSwipeRefresh, mScrollView, mEmptyView);
    }

    @SuppressWarnings("ResourceType")
    private View createEmptyView(Context context) {
        TextView emptyView = new TextView(context);
        emptyView.setId(android.R.id.empty);
        emptyView.setTextAppearance(context, android.R.attr.textAppearanceSmall);
        emptyView.setGravity(Gravity.CENTER);
        emptyView.setVisibility(View.GONE);
        emptyView.setText(mEmptyViewText);
        return emptyView;
    }

    private void addSwipeRefreshView(Context context, MultiSwipeRefreshLayout loadSwipeRefresh, T scrollView, View emptyView) {
        mRefreshLayoutWrapper = new FrameLayout(context);
        mRefreshLayoutWrapper.addView(scrollView,
                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        mRefreshLayoutWrapper.addView(emptyView,
                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));

        loadSwipeRefresh.addView(mRefreshLayoutWrapper, new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));

        addView(loadSwipeRefresh, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1));
        loadSwipeRefresh.setSwipeableChildren(scrollView, emptyView);
    }

    @Override
    public void autoRefresh() {
        mLoadSwipeRefresh.showProgressView();
        this.setRefreshing(true);
    }

    @Override
    public void autoRefresh(@ColorRes int... colorResIds) {
        mLoadSwipeRefresh.showProgressView(colorResIds);
        this.setRefreshing(true);
    }

    @Override
    public final void autoRefresh(boolean scale, int start, int end, @ColorRes int... colorResIds) {
        mLoadSwipeRefresh.showProgressView(scale, start, end, colorResIds);
        this.setRefreshing(true);
    }

    @Override
    public final void setEmptyText(int resId) {
        setEmptyText(getContext().getString(resId));
    }

    @Override
    public final void setEmptyText(CharSequence text) {
        if (mEmptyView != null && mEmptyView instanceof TextView) {
            TextView textView = (TextView) mEmptyView;
            textView.setText(text);
        }
    }

    @Override
    public final void setEmptyView(View newEmptyView) {
        if (null != newEmptyView) {
            if (mEmptyView != null && mRefreshLayoutWrapper != null) {
                mRefreshLayoutWrapper.removeView(mEmptyView);
            }
            newEmptyView.setVisibility(GONE);
            mEmptyView = newEmptyView;
            newEmptyView.setClickable(true);

            ViewParent newEmptyViewParent = newEmptyView.getParent();
            if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {
                ((ViewGroup) newEmptyViewParent).removeView(newEmptyView);
            }
            FrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams());
            if (null != lp) {
                mRefreshLayoutWrapper.addView(newEmptyView, lp);
            } else {
                mRefreshLayoutWrapper.addView(newEmptyView);
            }
        }
    }

    private static FrameLayout.LayoutParams convertEmptyViewLayoutParams(ViewGroup.LayoutParams lp) {
        FrameLayout.LayoutParams newLp = null;
        if (null != lp) {
            newLp = new FrameLayout.LayoutParams(lp);
            if (lp instanceof LinearLayout.LayoutParams)
                newLp.gravity = ((LinearLayout.LayoutParams) lp).gravity;
            else newLp.gravity = Gravity.CENTER;
        }
        return newLp;
    }

    @Override
    public final View getEmptyView() {
        return mEmptyView;
    }

    final void updateEmptyViewShown(boolean shown) {
        /*
         * ListView不能设置隐藏,否则下拉刷新动画无法跟随手势,因为 SwipeRefreshLayout 必须有滚动的view。
		 * mListView.setVisibility(!shown ? View.VISIBLE : View.GONE);
		 */
        if (mEmptyView != null)
            mEmptyView.setVisibility(shown ? View.VISIBLE : View.GONE);
    }

    @Override
    public final void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener) {
        mOnRefreshListener = listener;
        mLoadSwipeRefresh.setOnRefreshListener(listener);
    }

    @Override
    public final void setRefreshing(boolean refreshing) {
        isLoadCompleted = false;
        mLoadSwipeRefresh.setRefreshing(refreshing);
        // 下拉刷新中,此处目的是为了手动调用 setRefreshing(true)时,响应下拉刷新事件
        if (mLoadSwipeRefresh.isRefreshing() && mOnRefreshListener != null)
            mOnRefreshListener.onRefresh();
    }

    @Override
    public void setEnabled(boolean enabled) {
        getSwipeRefreshLayout().setEnabled(enabled);
    }

    @Override
    public final T getScrollView() {
        return mScrollView;
    }

    @Override
    public final SwipeRefreshLayout getSwipeRefreshLayout() {
        return mLoadSwipeRefresh;
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/MultiSwipeRefreshLayout.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.support.annotation.ColorRes;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AbsListView;

public final class MultiSwipeRefreshLayout extends SwipeRefreshLayout {
    // Default offset in dips from the top of the view to where the progress spinner should stop
    private static final int DEFAULT_CIRCLE_TARGET = 64;
    private float mSpinnerFinalOffset;
    private static final int[] DEFAULT_COLOR_RES = new int[]{android.R.color.holo_blue_light, android.R.color.holo_red_light,
            android.R.color.holo_orange_light, android.R.color.holo_green_light};

    private int mTouchSlop;
    private float mPrevX;// 上一次触摸时的X坐标
    private View[] mSwipeableChildren;
    private int[] mColorResIds;

    public MultiSwipeRefreshLayout(Context context) {
        this(context, null);
    }

    public MultiSwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        final DisplayMetrics metrics = getResources().getDisplayMetrics();
        mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;
        // 触发移动事件的最短距离,如果小于这个距离就不触发移动控件
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    public final void showProgressView() {
        if (mColorResIds == null)
            mColorResIds = DEFAULT_COLOR_RES;
        showProgressView(mColorResIds);
    }

    public final void showProgressView(@ColorRes int... colorResIds) {
        showProgressView(false, 0, (int) mSpinnerFinalOffset, colorResIds);
    }

    public final void showProgressView(boolean scale, int start, int end, @ColorRes int... colorResIds) {
        this.mColorResIds = colorResIds;
        setColorSchemeResources(colorResIds);
        // 显示下拉动画,关键在于源码中的 mUsingCustomStart = true
        //有二种方法显示动画,我的文章:http://blog.csdn.net/hupei/article/details/51953370
        setProgressViewOffset(scale, start, end);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPrevX = event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                final float eventX = event.getX();
                float xDiff = Math.abs(eventX - mPrevX);
                // 增加容差,让下拉刷新在竖直滑动时就可以触发
                if (xDiff > mTouchSlop + DEFAULT_CIRCLE_TARGET) {
                    return false;
                }
        }
        return super.onInterceptTouchEvent(event);
    }

    final void setSwipeableChildren(final View... views) {
        assert views != null;
        mSwipeableChildren = views;
    }


    @Override
    public boolean canChildScrollUp() {
        if (mSwipeableChildren != null && mSwipeableChildren.length > 0) {
            for (View view : mSwipeableChildren) {
                if (view != null && view.isShown() && !canViewScrollUp(view)) {
                    return false;
                }
            }
        }
        return true;
    }

    private static boolean canViewScrollUp(View target) {
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (target instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) target;
                return absListView.getChildCount() > 0
                        && (absListView.getFirstVisiblePosition() > 0
                        || absListView.getChildAt(0).getTop() < absListView.getPaddingTop());
            } else {
                return ViewCompat.canScrollVertically(target, -1) || target.getScrollY() > 0;
            }
        } else {
            return ViewCompat.canScrollVertically(target, -1);
        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAbsListView.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListAdapter;

import com.mylhyl.crlayout.internal.ILoadSwipeRefresh;

/**
 * SwipeRefreshLayout 加 AbsListView 布局<br>
 * 子类必须实现 {@linkplain BaseSwipeRefresh#createScrollView(Context, AttributeSet)}  createScrollView}方法
 * <p> Created by hupei on 2016/5/12.
 */
public abstract class SwipeRefreshAbsListView<T extends AbsListView> extends
        SwipeRefreshAdapterView<T> {
    private ListAdapter mEmptyDataSetAdapter;
    private EmptyDataSetObserver mDataSetObserver;

    public SwipeRefreshAbsListView(Context context) {
        super(context);
    }

    public SwipeRefreshAbsListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public final void setOnItemClickListener(AdapterView.OnItemClickListener listener) {
        getScrollView().setOnItemClickListener(listener);
    }

    /**
     * 为 AbsListView 设置适配器
     *
     * @param adapter
     */
    public final void setAdapter(ListAdapter adapter) {
        if (adapter == null)
            throw new NullPointerException("mAdapter is null please call SwipeRefreshAbsListView" +
                    ".setAdapter");
        getScrollView().setOnScrollListener(new OnScrollAbsListListener(this));
        getScrollView().setAdapter(adapter);
        registerDataSetObserver(adapter);
    }

    final void registerDataSetObserver(ListAdapter adapter) {
        if (mEmptyDataSetAdapter != null && mDataSetObserver != null)
            mEmptyDataSetAdapter.unregisterDataSetObserver(mDataSetObserver);

        mEmptyDataSetAdapter = adapter;
        if (mEmptyDataSetAdapter != null) {
            mDataSetObserver = new EmptyDataSetObserver();
            mEmptyDataSetAdapter.registerDataSetObserver(mDataSetObserver);
            mDataSetObserver.onChanged();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mEmptyDataSetAdapter != null && mDataSetObserver != null) {
            mEmptyDataSetAdapter.unregisterDataSetObserver(mDataSetObserver);
            mDataSetObserver = null;
        }
    }

    public static class OnScrollAbsListListener implements AbsListView.OnScrollListener {
        private ILoadSwipeRefresh mILoadSwipeRefresh;
        private AbsListView.OnScrollListener mOnScrollListener;

        public OnScrollAbsListListener(ILoadSwipeRefresh loadSwipeRefresh) {
            mILoadSwipeRefresh = loadSwipeRefresh;
        }

        public OnScrollAbsListListener(ILoadSwipeRefresh loadSwipeRefresh, AbsListView
                .OnScrollListener onScrollListener) {
            mILoadSwipeRefresh = loadSwipeRefresh;
            mOnScrollListener = onScrollListener;
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // 只有在闲置状态情况下检查
            if (scrollState == SCROLL_STATE_IDLE) {
                // 如果满足允许上拉加载、非加载状态中、最后一个显示的 item 与数据源的大小一样,则表示滑动入底部
                if (mILoadSwipeRefresh.isEnabledLoad() && !mILoadSwipeRefresh.isLoading()
                        && view.getLastVisiblePosition() == (view.getCount() - 1)) {
                    mILoadSwipeRefresh.loadData();// 执行上拉加载数据
                }
            }
            if (null != mOnScrollListener)
                mOnScrollListener.onScrollStateChanged(view, scrollState);
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int
                totalItemCount) {
            if (null != mOnScrollListener)
                mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
                        totalItemCount);
        }
    }

    private class EmptyDataSetObserver extends DataSetObserver {
        @Override
        public void onChanged() {
            updateEmptyViewShown(mEmptyDataSetAdapter == null || mEmptyDataSetAdapter.isEmpty());
        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAdapterView.java
================================================
package com.mylhyl.crlayout;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;

import com.mylhyl.crlayout.internal.ILoadSwipeRefresh;
import com.mylhyl.crlayout.internal.LoadConfig;
import com.mylhyl.crlayout.internal.LoadLayout;
import com.mylhyl.crlayout.internal.LoadLayoutBase;
import com.mylhyl.crlayout.internal.LoadLayoutConvert;

public abstract class SwipeRefreshAdapterView<T extends View> extends BaseSwipeRefresh<T>
        implements ILoadSwipeRefresh {

    private static final String DEFAULT_FOOTER_TEXT = "加载数据中...";
    private static final String DEFAULT_FOOTER_COMPLETED_TEXT = "没有更多了";
    private static final int mLoadAnimatorDuration = 300;

    private boolean mLoading;// 是否处于上拉加载状态中
    private boolean mEnabledLoad;// 是否允许上拉加载
    private LoadLayoutBase mLoadLayout;
    private int mLoadResource;
    private String mLoadText;
    private String mCompletedText;
    private Drawable mLoadIndeterminateDrawable;

    private OnListLoadListener mOnListLoadListener;

    private ValueAnimator mShowLoadAnimator;
    private ValueAnimator mHideLoadAnimator;
    private int mLoadLayoutHeight;
    private boolean isLoadAnimator;

    public SwipeRefreshAdapterView(Context context) {
        this(context, null);
    }

    public SwipeRefreshAdapterView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SwipeRefreshAdapterView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr, 0);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SwipeRefreshAdapterView(Context context, AttributeSet attrs, int defStyleAttr, int
            defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        int[] crLayout = R.styleable.crLayout;
        if (crLayout != null && crLayout.length > 0) {
            final TypedArray a = context.obtainStyledAttributes(attrs, crLayout, defStyleAttr,
                    defStyleRes);
            if (a != null) {
                mLoadResource = a.getResourceId(R.styleable.crLayout_load_layout, 0);
                mLoadText = a.getString(R.styleable.crLayout_load_text);
                mLoadIndeterminateDrawable = a.getDrawable(R.styleable
                        .crLayout_load_indeterminate_drawable);
                mCompletedText = a.getString(R.styleable.crLayout_load_completed_text);
                isLoadAnimator = a.getBoolean(R.styleable.crLayout_load_animator, false);
                a.recycle();
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (isLoadAnimator && mLoadLayout != null && mLoadLayoutHeight == 0) {
            mLoadLayoutHeight = mLoadLayout.getMeasuredHeight();
            if (mLoadLayoutHeight > 0) {
                mLoadLayout.setVisibility(GONE);
                initShowLoadAnimator();
                initHideLoadAnimator();
            }
        }
    }

    private void initShowLoadAnimator() {
        mShowLoadAnimator = ValueAnimator.ofFloat(0, mLoadLayoutHeight);
        mShowLoadAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                LayoutParams lp = (LayoutParams) mLoadLayout.getLayoutParams();
                lp.height = (int) ((Float) animation.getAnimatedValue()).floatValue();
                mLoadLayout.setLayoutParams(lp);
                getScrollView().setTranslationY(-lp.height);
            }
        });
        mShowLoadAnimator.addListener(new SimpleAnimatorListener() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (mOnListLoadListener != null && !isLoadCompleted) {
                    mOnListLoadListener.onListLoad();
                }
            }
        });
        mShowLoadAnimator.setDuration(mLoadAnimatorDuration);
    }

    private void initHideLoadAnimator() {
        mHideLoadAnimator = ValueAnimator.ofFloat(mLoadLayoutHeight, 0);
        mHideLoadAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                LayoutParams lp = (LayoutParams) mLoadLayout.getLayoutParams();
                lp.height = (int) ((Float) animation.getAnimatedValue()).floatValue();
                mLoadLayout.setLayoutParams(lp);
                getScrollView().setTranslationY(-lp.height);
            }
        });
        mHideLoadAnimator.setDuration(mLoadAnimatorDuration);
    }

    @Override
    public final void setOnListLoadListener(OnListLoadListener onListLoadListener) {
        this.mOnListLoadListener = onListLoadListener;
        setEnabledLoad(mOnListLoadListener != null);
        if (mEnabledLoad) addLoadLayout();
    }

    private void addLoadLayout() {
        if (mLoadLayout == null) {
            createLoadLayout();//创建上拉加载 View
            LayoutParams layoutParams = new LayoutParams(mLoadLayout.getLayoutParams());
            layoutParams.gravity = Gravity.BOTTOM;
            //永远处于第二节点,防止 mLoadLayout 遮挡其它控件
            addView(mLoadLayout, 1, layoutParams);
        }
    }

    private void createLoadLayout() {
        if ((mLoadResource = getLoadLayoutResource()) > 0) {
            View view = LayoutInflater.from(getContext()).inflate(mLoadResource, this, false);
            mLoadLayout = new LoadLayoutConvert(getContext(), view);
        } else {
            LoadLayout footerLayout = new LoadLayout(getContext());
            mLoadLayout = footerLayout;
        }
        if (mLoadLayout == null)
            throw new NullPointerException("mLoadLayout is null");

        if (!isLoadAnimator) mLoadLayout.setVisibility(GONE);

        if (TextUtils.isEmpty(mCompletedText))
            mCompletedText = DEFAULT_FOOTER_COMPLETED_TEXT;
        mLoadLayout.setLoadCompletedText(mCompletedText);

        if (TextUtils.isEmpty(mLoadText))
            mLoadText = DEFAULT_FOOTER_TEXT;
        mLoadLayout.setLoadText(mLoadText);

        if (mLoadIndeterminateDrawable != null)
            mLoadLayout.setIndeterminateDrawable(mLoadIndeterminateDrawable);
    }

    @Override
    public final void setLoadLayoutResource(int resource) {
        mLoadResource = resource;
        if (mLoadLayout != null)
            throw new RuntimeException("please call setLoadLayoutResource before " +
                    "setOnListLoadListener");
    }

    /**
     * 获取自定义上拉加载 layoutResource,子类可重写
     *
     * @return
     */
    protected int getLoadLayoutResource() {
        return mLoadResource;
    }


    @Override
    public final void loadData() {
        setLoading(true);
    }

    @Override
    public final void setLoading(boolean loading) {
        if (mLoading == loading) return;
        this.mLoading = loading;
        if (mLoading) showLoadLayout();
        else hideLoadLayout();
    }

    private void showLoadLayout() {
        if (mLoadLayout != null) {
            LoadConfig footerLayout = getLoadConfig();
            if (isLoadCompleted) {
                footerLayout.setLoadCompletedText(mLoadLayout.getCompletedText());
                footerLayout.setProgressBarVisibility(View.GONE);
                mLoadLayout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        setLoading(false);
                    }
                }, 1000);
            } else {
                footerLayout.setLoadText(mLoadLayout.getFooterText());
                footerLayout.setProgressBarVisibility(View.VISIBLE);
            }
            mLoadLayout.setVisibility(View.VISIBLE);

            if (isLoadAnimator && mShowLoadAnimator != null) mShowLoadAnimator.start();
            else if (!isLoadAnimator && !isLoadCompleted && mOnListLoadListener != null)
                mOnListLoadListener.onListLoad();
        }
    }

    private void hideLoadLayout() {
        if (isLoadAnimator && mHideLoadAnimator != null) mHideLoadAnimator.start();
        else mLoadLayout.setVisibility(GONE);
    }

    @Override
    public final void setEnabledLoad(boolean enabled) {
        mEnabledLoad = enabled;
    }

    @Override
    public final boolean isLoading() {
        return mLoading;
    }

    @Override
    public final boolean isEnabledLoad() {
        return mEnabledLoad;
    }

    @Override
    public void setLoadCompleted(boolean loadCompleted) {
        isLoadCompleted = loadCompleted;
    }

    @Override
    public LoadConfig getLoadConfig() {
        if (mLoadLayout == null) addLoadLayout();
        return mLoadLayout;
    }

    @Override
    public void setLoadAnimator(boolean loadAnimator) {
        isLoadAnimator = loadAnimator;
        if (mLoadLayout != null)
            throw new RuntimeException("please call setLoadAnimator before setOnListLoadListener");
    }

    public interface OnListLoadListener {
        /**
         * 当上拉加载时,此方法将被调用
         */
        void onListLoad();
    }

    static class SimpleAnimatorListener implements Animator.AnimatorListener {
        @Override
        public void onAnimationStart(Animator animation) {

        }

        @Override
        public void onAnimationEnd(Animator animation) {

        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshExpandableListView.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;

/**
 * SwipeRefreshLayout 包含 ExpandableListView 布局<br>
 * 如须自定义加载框,可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}
 * <p>Created by hupei on 2016/5/16.
 */
public class SwipeRefreshExpandableListView extends SwipeRefreshAbsListView<ExpandableListView> {
    private ExpandableListAdapter mAdapter;

    public SwipeRefreshExpandableListView(Context context) {
        super(context);
    }

    public SwipeRefreshExpandableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 为 ExpandableListView 设置适配器
     *
     * @param adapter
     */
    public final void setAdapter(ExpandableListAdapter adapter) {
        mAdapter = adapter;
        if (mAdapter == null)
            throw new NullPointerException("mAdapter is null please call SwipeRefreshExpandableListView.setAdapter");
        getScrollView().setOnScrollListener(new OnScrollAbsListListener(this));
        getScrollView().setAdapter(mAdapter);
        registerDataSetObserver(new ExpandableListConnector(mAdapter));
    }

    @Override
    protected ExpandableListView createScrollView(Context context, AttributeSet attrs) {
        ExpandableListView expandableListView = new ExpandableListView(context, attrs);
        expandableListView.setId(android.R.id.list);
        return expandableListView;
    }

    private class ExpandableListConnector extends BaseAdapter {
        private ExpandableListAdapter mExpandableListAdapter;

        public ExpandableListConnector(ExpandableListAdapter expandableListAdapter) {
            this.mExpandableListAdapter = expandableListAdapter;
        }

        @Override
        public int getCount() {
            if (mExpandableListAdapter == null) return 0;
            return mExpandableListAdapter.getGroupCount();
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {
            mExpandableListAdapter.registerDataSetObserver(observer);
        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {
            mExpandableListAdapter.unregisterDataSetObserver(observer);
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return null;
        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshGridView.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;

/**
 * SwipeRefreshLayout 包含 HeaderGridView 布局<br>
 * 如须自定义加载框,可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}方法
 * <p>Created by hupei on 2016/5/17.
 */
public class SwipeRefreshGridView extends SwipeRefreshAbsListView<GridView> {

    @Override
    protected GridView createScrollView(Context context, AttributeSet attrs) {
        GridView gridView = new GridView(context, attrs);
        gridView.setId(android.R.id.list);
        return gridView;
    }

    public SwipeRefreshGridView(Context context) {
        super(context);
    }

    public SwipeRefreshGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshListView.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

/**
 * SwipeRefreshLayout 包含 ListView 布局<br>
 * 如须自定义加载框,可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}方法
 * <p>Created by hupei on 2016/5/12.
 */
public class SwipeRefreshListView extends SwipeRefreshAbsListView<ListView> {

    public SwipeRefreshListView(Context context) {
        super(context);
    }

    public SwipeRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected ListView createScrollView(Context context, AttributeSet attrs) {
        ListView listView = new ListView(context, attrs);
        listView.setId(android.R.id.list);
        return listView;
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshRecyclerView.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;

import com.mylhyl.crlayout.internal.ILoadSwipeRefresh;

/**
 * SwipeRefreshLayout 加 RecyclerView 布局<br>
 * 如须自定义加载框,可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}方法
 * <p> Created by hupei on 2016/5/12.
 */
public class SwipeRefreshRecyclerView extends SwipeRefreshAdapterView<RecyclerView> {
    private RecyclerView.Adapter mEmptyDataSetAdapter;
    private EmptyDataSetObserver mDataSetObserver;

    public SwipeRefreshRecyclerView(Context context) {
        super(context);
    }

    public SwipeRefreshRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 为 RecyclerView 设置适配器
     *
     * @param adapter
     */
    public final void setAdapter(RecyclerView.Adapter adapter) {
        if (adapter == null)
            throw new NullPointerException("mAdapter is null please call CygSwipeRefreshLayout" +
                    ".setAdapter");
        getScrollView().setOnScrollListener(new OnScrollRecyclerViewListener(this));
        getScrollView().setAdapter(adapter);
        registerAdapterDataObserver(adapter);
    }

    public void setLayoutManager(RecyclerView.LayoutManager layout) {
        getScrollView().setLayoutManager(layout);
    }

    @Override
    protected RecyclerView createScrollView(Context context, AttributeSet attrs) {
        RecyclerView recyclerView = new RecyclerView(context, attrs);
        recyclerView.setId(android.R.id.list);
        return recyclerView;
    }

    private void registerAdapterDataObserver(RecyclerView.Adapter adapter) {
        if (mEmptyDataSetAdapter != null && mDataSetObserver != null)
            mEmptyDataSetAdapter.unregisterAdapterDataObserver(mDataSetObserver);

        mEmptyDataSetAdapter = adapter;
        if (mEmptyDataSetAdapter != null){
            mDataSetObserver = new EmptyDataSetObserver();
            mEmptyDataSetAdapter.registerAdapterDataObserver(mDataSetObserver);
            mDataSetObserver.onChanged();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mEmptyDataSetAdapter != null && mDataSetObserver != null) {
            mEmptyDataSetAdapter.unregisterAdapterDataObserver(mDataSetObserver);
            mDataSetObserver = null;
        }
    }

    public static class OnScrollRecyclerViewListener extends RecyclerView.OnScrollListener {
        private ILoadSwipeRefresh mILoadSwipeRefresh;
        private RecyclerView.OnScrollListener mOnScrollListener;

        public OnScrollRecyclerViewListener(ILoadSwipeRefresh loadSwipeRefresh) {
            mILoadSwipeRefresh = loadSwipeRefresh;
        }

        public OnScrollRecyclerViewListener(ILoadSwipeRefresh loadSwipeRefresh, RecyclerView
                .OnScrollListener onScrollListener) {
            mILoadSwipeRefresh = loadSwipeRefresh;
            mOnScrollListener = onScrollListener;
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            // 只有在闲置状态情况下检查
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                // 如果满足允许上拉加载、非加载状态中、最后一个显示的 item 与数据源的大小一样,则表示滑动入底部
                if (!isFirstItemVisible(recyclerView) && mILoadSwipeRefresh.isEnabledLoad()
                        && !mILoadSwipeRefresh.isLoading() && isLastItemVisible(recyclerView)) {
                    mILoadSwipeRefresh.loadData();// 执行上拉加载数据
                }
            }
            if (null != mOnScrollListener)
                mOnScrollListener.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if (null != mOnScrollListener)
                mOnScrollListener.onScrolled(recyclerView, dx, dy);
        }

        /**
         * 判断第一个条目是否完全可见
         *
         * @param recyclerView
         * @return
         */
        private boolean isFirstItemVisible(RecyclerView recyclerView) {
            final RecyclerView.Adapter<?> adapter = recyclerView.getAdapter();
            // 如果未设置Adapter或者Adapter没有数据可以下拉刷新
            if (null == adapter || adapter.getItemCount() == 0) {
                return true;
            }
            // 第一个条目完全展示,可以刷新
            if (getFirstVisiblePosition(recyclerView) == 0) {
                return recyclerView.getChildAt(0).getTop() >= recyclerView.getTop();
            }
            return false;
        }

        /**
         * 获取第一个可见子View的位置下标
         *
         * @param recyclerView
         * @return
         */
        private int getFirstVisiblePosition(RecyclerView recyclerView) {
            View firstVisibleChild = recyclerView.getChildAt(0);
            return firstVisibleChild != null ?
                    recyclerView.getChildAdapterPosition(firstVisibleChild) : -1;
        }

        /**
         * 判断最后一个条目是否完全可见
         *
         * @param recyclerView
         * @return
         */
        private boolean isLastItemVisible(RecyclerView recyclerView) {
            final RecyclerView.Adapter<?> adapter = recyclerView.getAdapter();
            // 如果未设置Adapter或者Adapter没有数据可以上拉刷新
            if (null == adapter || adapter.getItemCount() == 0) {
                return true;
            }
            // 最后一个条目View完全展示,可以刷新
            int lastVisiblePosition = getLastVisiblePosition(recyclerView);
            if (lastVisiblePosition >= recyclerView.getAdapter().getItemCount() - 1) {
                return recyclerView.getChildAt(recyclerView.getChildCount() - 1).getBottom()
                        <= recyclerView.getBottom();
            }
            return false;
        }

        /**
         * 获取最后一个可见子View的位置下标
         *
         * @param recyclerView
         * @return
         */
        private int getLastVisiblePosition(RecyclerView recyclerView) {
            View lastVisibleChild = recyclerView.getChildAt(recyclerView.getChildCount() - 1);
            return lastVisibleChild != null ? recyclerView.getChildAdapterPosition
                    (lastVisibleChild) : -1;
        }
    }

    private class EmptyDataSetObserver extends RecyclerView.AdapterDataObserver {
        @Override
        public void onChanged() {
            updateEmptyViewShown(mEmptyDataSetAdapter == null || mEmptyDataSetAdapter
                    .getItemCount() == 0);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            onChanged();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            onChanged();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            onChanged();
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            onChanged();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            onChanged();
        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshWebView.java
================================================
package com.mylhyl.crlayout;

import android.content.Context;
import android.support.annotation.ColorRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

/**
 * SwipeRefreshLayout 加 WebView 布局<br>
 * <p> Created by hupei on 2016/5/12.
 */
public class SwipeRefreshWebView extends BaseSwipeRefresh<WebView> {
    private final SwipeRefreshLayout.OnRefreshListener refreshListener = new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            getScrollView().reload();
        }
    };
    private final WebChromeClient defaultWebChromeClient = new WebChromeClient() {

        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            if (newProgress == 100) {
                setRefreshing(false);
            }
        }
    };

    public SwipeRefreshWebView(Context context) {
        this(context, null);
    }

    public SwipeRefreshWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (!isInEditMode()) {
            setOnRefreshListener(refreshListener);
            getScrollView().setWebChromeClient(defaultWebChromeClient);
        }
    }

    @Override
    public final void autoRefresh() {
        mLoadSwipeRefresh.showProgressView();
        mLoadSwipeRefresh.setRefreshing(true);
    }

    @Override
    public final void autoRefresh(@ColorRes int... colorResIds) {
        //重写主要是为了显示动画时,不响应 onRefresh() 方法
        mLoadSwipeRefresh.showProgressView(colorResIds);
        mLoadSwipeRefresh.setRefreshing(true);
    }

    @Override
    protected WebView createScrollView(Context context, AttributeSet attrs) {
        WebView webView = new WebView(context, attrs);
        webView.setId(android.R.id.list);
        return webView;
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/BaseSwipeRefreshFragment.java
================================================
package com.mylhyl.crlayout.app;

import android.os.Bundle;
import android.support.annotation.ColorRes;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.mylhyl.crlayout.BaseSwipeRefresh;
import com.mylhyl.crlayout.internal.ISwipeRefresh;

/**
 * Google自家下拉刷新 SwipeRefreshLayout <br>
 * <p/>
 * 注:SwipeRefreshLayout 只能有一个 childView,childView自身必须是可滚动的view<br>
 * 或 childView 必须包含可滚动的view,如ScrollView或者AbsListView<br>
 * 子类继承重写 onCreateView 必须 super
 */
abstract class BaseSwipeRefreshFragment<T extends BaseSwipeRefresh> extends Fragment
        implements SwipeRefreshLayout.OnRefreshListener {

    /**
     * 创建下拉刷新控件子类重写
     *
     * @return
     */
    public abstract T createSwipeRefreshLayout();

    protected T mSwipeRefresh;

    @Override
    public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return mSwipeRefresh = createSwipeRefreshLayout();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // 注册下拉刷新
        mSwipeRefresh.setOnRefreshListener(this);
    }

    public final void autoRefresh() {
        getSwipeRefreshLayout().autoRefresh();
    }

    public final void autoRefresh(@ColorRes int... colorResIds) {
        getSwipeRefreshLayout().autoRefresh(colorResIds);
    }

    /**
     * {@link ISwipeRefresh#setRefreshing(boolean)}
     */
    public final void setRefreshing(boolean refreshing) {
        getSwipeRefreshLayout().setRefreshing(refreshing);
    }


    public final void setEmptyText(int resId) {
        setEmptyText(getString(resId));
    }

    public final void setEmptyText(CharSequence text) {
        getSwipeRefreshLayout().setEmptyText(text);
    }

    public final void setEmptyView(View emptyView) {
        getSwipeRefreshLayout().setEmptyView(emptyView);
    }

    public final T getSwipeRefreshLayout() {
        return mSwipeRefresh;
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAbsListFragment.java
================================================
package com.mylhyl.crlayout.app;

import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ExpandableListView;
import android.widget.ListAdapter;

import com.mylhyl.crlayout.SwipeRefreshAbsListView;


abstract class SwipeRefreshAbsListFragment<T extends SwipeRefreshAbsListView> extends SwipeRefreshAdapterFragment<T> {
    private final AdapterView.OnItemClickListener mOnItemClickListener = new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            /**
             * ListView or GridView 单点事件
             */
            onListItemClick(parent, view, position, id);
        }
    };


    /**
     * Item 点击时此方法调用,子类可重写
     *
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    public void onListItemClick(AdapterView<?> parent, View view, int position, long id) {
    }

    /**
     * 适配器设置数据源
     *
     * @param adapter
     * @author hupei
     * @date 2015年7月31日 上午9:06:14
     */
    public final void setListAdapter(ListAdapter adapter) {
        AbsListView absListView = (AbsListView) getSwipeRefreshLayout().getScrollView();
        if (absListView instanceof ExpandableListView) {
            new RuntimeException("please call SwipeRefreshExpandableListFragment.setListAdapter()");
        }
        T swipeRefreshLayout = getSwipeRefreshLayout();
        if (swipeRefreshLayout != null && swipeRefreshLayout instanceof SwipeRefreshAbsListView) {
            absListView.setVisibility(View.VISIBLE);
            absListView.setOnItemClickListener(mOnItemClickListener);

            swipeRefreshLayout.setAdapter(adapter);
        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAdapterFragment.java
================================================
package com.mylhyl.crlayout.app;

import com.mylhyl.crlayout.SwipeRefreshAdapterView;
import com.mylhyl.crlayout.SwipeRefreshListView;

/**
 * 如果开启{@linkplain SwipeRefreshAdapterFragment#setEnabledLoad(boolean) 上拉加载}功能
 * 必须重写 {@linkplain SwipeRefreshAdapterFragment#onListLoad() onListLoad()}方法<br>
 */
abstract class SwipeRefreshAdapterFragment<T extends SwipeRefreshAdapterView> extends BaseSwipeRefreshFragment<T>
        implements SwipeRefreshAdapterView.OnListLoadListener {


    /**
     * 设置允许上拉加载,重写{@link #onListLoad() onListLoad 方法实现上拉加载数据}
     *
     * @param enabled
     * @see SwipeRefreshListView#setEnabledLoad(boolean)
     * @see SwipeRefreshListView#setOnListLoadListener(SwipeRefreshAdapterView.OnListLoadListener)
     */
    public final void setEnabledLoad(boolean enabled) {
        if (enabled)
            mSwipeRefresh.setOnListLoadListener(this);
        mSwipeRefresh.setEnabledLoad(enabled);
    }


    /**
     * {@link SwipeRefreshAdapterView#setLoading(boolean)}
     */
    public final void setLoading(boolean loading) {
        getSwipeRefreshLayout().setLoading(loading);
    }

    @Override
    public void onListLoad() {

    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshExpandableListFragment.java
================================================
package com.mylhyl.crlayout.app;

import android.view.View;
import android.widget.AdapterView;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;

import com.mylhyl.crlayout.SwipeRefreshExpandableListView;

/**
 * Created by hupei on 2016/5/16.
 */
public abstract class SwipeRefreshExpandableListFragment extends SwipeRefreshAbsListFragment<SwipeRefreshExpandableListView> {
    private final ExpandableListView.OnGroupClickListener mOnGroupClickListener = new ExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
            return onListGroupClick(parent, v, groupPosition, id);
        }
    };
    private final ExpandableListView.OnChildClickListener mOnChildClickListener = new ExpandableListView.OnChildClickListener() {

        @Override
        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
            return onListChildClick(parent, v, groupPosition, childPosition, id);
        }
    };

    public boolean onListChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        return false;
    }

    public boolean onListGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
        return false;
    }

    @Override
    public final void onListItemClick(AdapterView<?> parent, View view, int position, long id) {
        //子类不允许重写
        super.onListItemClick(parent, view, position, id);
    }

    @Override
    public SwipeRefreshExpandableListView createSwipeRefreshLayout() {
        return new SwipeRefreshExpandableListView(getActivity());
    }

    public final void setListAdapter(ExpandableListAdapter adapter) {
        ExpandableListView expandableListView = getSwipeRefreshLayout().getScrollView();
        SwipeRefreshExpandableListView swipeRefreshExpandableListView = getSwipeRefreshLayout();
        if (expandableListView != null && swipeRefreshExpandableListView != null) {
            expandableListView.setVisibility(View.VISIBLE);

            expandableListView.setOnGroupClickListener(mOnGroupClickListener);
            expandableListView.setOnChildClickListener(mOnChildClickListener);

            swipeRefreshExpandableListView.setAdapter(adapter);
        }
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshListFragment.java
================================================
package com.mylhyl.crlayout.app;

import com.mylhyl.crlayout.SwipeRefreshListView;

public abstract class SwipeRefreshListFragment extends SwipeRefreshAbsListFragment<SwipeRefreshListView> {

    @Override
    public SwipeRefreshListView createSwipeRefreshLayout() {
        return new SwipeRefreshListView(getActivity());
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ILoadSwipeRefresh.java
================================================
package com.mylhyl.crlayout.internal;

import com.mylhyl.crlayout.SwipeRefreshAdapterView;

/**
 * Created by hupei on 2016/5/18.
 */
public interface ILoadSwipeRefresh {

    void setOnListLoadListener(SwipeRefreshAdapterView.OnListLoadListener onListLoadListener);

    void setLoadLayoutResource(int resource);

    void loadData();

    /**
     * 设置是否处于上拉加载状态
     *
     * @param loading 为true加载状态,false结束加载
     */
    void setLoading(boolean loading);

    /**
     * 允许上拉加载
     *
     * @param enabled
     */
    void setEnabledLoad(boolean enabled);

    /**
     * 是否在上拉加载中
     *
     * @return
     */
    boolean isLoading();

    /**
     * 是否允许上拉加载
     *
     * @return
     */
    boolean isEnabledLoad();

    /**
     * 设置加载完成
     *
     * @param loadCompleted
     */
    void setLoadCompleted(boolean loadCompleted);

    LoadConfig getLoadConfig();

    /**
     * 设置加载Layout有动画显示效果,默认false
     *
     * @param isLoadAnimator true 启用动画
     */
    void setLoadAnimator(boolean isLoadAnimator);
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ISwipeRefresh.java
================================================
package com.mylhyl.crlayout.internal;

import android.support.annotation.ColorRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.View;

/**
 * Created by hupei on 2016/5/18.
 */
public interface ISwipeRefresh<T> {
    /**
     * 显示刷新动画,颜色随系统
     */
    void autoRefresh();

    /**
     * 显示刷新动画,可指定颜色
     *
     * @param colorResIds 动画颜色
     */
    void autoRefresh(@ColorRes int... colorResIds);

    void autoRefresh(boolean scale, int start, int end, @ColorRes int... colorResIds);

    void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener);

    void setEmptyText(CharSequence text);

    void setEmptyText(int resId);

    void setEmptyView(View emptyView);

    View getEmptyView();

    /**
     * 设置下拉刷新状态
     *
     * @param refreshing true=刷新中;false=刷新完成
     */
    void setRefreshing(boolean refreshing);

    /**
     * 禁用下拉刷新
     *
     * @param enabled
     */
    void setEnabled(boolean enabled);

    /**
     * 获取可滑动的 ListView、ExpandableListView、GridView、RecyclerView
     *
     * @return
     */
    T getScrollView();


    SwipeRefreshLayout getSwipeRefreshLayout();
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadConfig.java
================================================
package com.mylhyl.crlayout.internal;

import android.graphics.drawable.Drawable;

/**
 * Created by hupei on 2016/5/19.
 */
public interface LoadConfig {
    /**
     * 设置加载文字
     *
     * @param label
     */
    void setLoadText(String label);

    /**
     * 设置加载文字大小
     *
     * @param size
     */
    void setLoadTextSize(float size);

    /**
     * 设置加载文字颜色
     *
     * @param color
     */
    void setLoadTextColor(int color);

    /**
     * 设置菊花显示或隐藏
     *
     * @param v
     */
    void setProgressBarVisibility(int v);

    /**
     * 设置菊花样式
     *
     * @param d
     */
    void setIndeterminateDrawable(Drawable d);

    /**
     * 设置加载完成文字
     *
     * @param text
     */
    void setLoadCompletedText(String text);

    /**
     * 设置加载更多 Layout 高度
     *
     * @param height
     */
    void setLoadViewHeight(int height);

    /**
     * 设置加载更多 Layout 资源背景
     *
     * @param resId
     */
    void setLoadViewBackgroundResource(int resId);

    /**
     * 设置加载更多 Layout 颜色背景
     *
     * @param color
     */
    void setLoadViewBackgroundColor(int color);
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayout.java
================================================
package com.mylhyl.crlayout.internal;

import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * 上拉加载 layout 包含 ProgressBar 与 TextView
 * Created by hupei on 2016/5/19.
 */
public final class LoadLayout extends LoadLayoutBase {
    public LoadLayout(Context context) {
        super(context);
    }

    @Override
    void createFooter(ViewGroup v) {
        LinearLayout root = (LinearLayout) v;
        root.setOrientation(HORIZONTAL);
        root.setGravity(Gravity.CENTER);
        root.setBackgroundColor(Color.WHITE);
        root.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, pxTdp(50)));

        mProgressBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmallInverse);
        root.addView(mProgressBar, new AbsListView.LayoutParams(
                AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT));

        mTextView = new TextView(getContext());
        mTextView.setTextAppearance(getContext(), android.R.attr.textAppearanceMedium);
        root.addView(mTextView, new LayoutParams(
                AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT));
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutBase.java
================================================
package com.mylhyl.crlayout.internal;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * 上拉加载 layout 基类
 * Created by hupei on 2016/5/19.
 */
public abstract class LoadLayoutBase extends LinearLayout implements LoadConfig {

    private String mFooterText;
    private String mCompletedText;

    protected ProgressBar mProgressBar;
    protected TextView mTextView;

    abstract void createFooter(ViewGroup v);

    public LoadLayoutBase(Context context) {
        super(context);
        createFooter(this);
    }

    public LoadLayoutBase(Context context, View v) {
        super(context);
        createFooter((ViewGroup) v);
    }

    protected int pxTdp(int size) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, getResources().getDisplayMetrics());
    }

    @Override
    public void setLoadViewHeight(int height) {
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = pxTdp(height);
        setLayoutParams(params);
    }

    @Override
    public void setLoadText(String text) {
        mFooterText = text;
        if (mTextView != null)
            mTextView.setText(text);
    }

    @Override
    public void setLoadTextSize(float size) {
        if (mTextView != null)
            mTextView.setTextSize(size);
    }

    @Override
    public void setLoadTextColor(@ColorInt int color) {
        if (mTextView != null)
            mTextView.setTextColor(color);
    }

    @Override
    public void setLoadViewBackgroundResource(@DrawableRes int resId) {
        setBackgroundResource(resId);
    }

    @Override
    public void setLoadViewBackgroundColor(@ColorInt int color) {
        setBackgroundColor(color);
    }

    @Override
    public void setProgressBarVisibility(int v) {
        if (mProgressBar != null)
            mProgressBar.setVisibility(v);
    }

    @Override
    public void setIndeterminateDrawable(Drawable d) {
        if (mProgressBar != null)
            mProgressBar.setIndeterminateDrawable(d);
    }

    @Override
    public void setLoadCompletedText(String text) {
        mCompletedText = text;
        if (mTextView != null)
            mTextView.setText(text);
    }

    public String getFooterText() {
        return mFooterText;
    }

    public String getCompletedText() {
        return mCompletedText;
    }
}


================================================
FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutConvert.java
================================================
package com.mylhyl.crlayout.internal;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * 转换自定义上拉加载 View
 * Created by hupei on 2016/5/19.
 */
public final class LoadLayoutConvert extends LoadLayoutBase {

    public LoadLayoutConvert(Context context, View v) {
        super(context, v);
    }

    @Override
    void createFooter(ViewGroup v) {
        //查找 mProgressBar 与 mTextView
        int count = v.getChildCount();
        for (int i = 0; i < count; i++) {
            View childAt = v.getChildAt(i);
            if (childAt instanceof ProgressBar)
                mProgressBar = (ProgressBar) childAt;
            else if (childAt instanceof TextView)
                mTextView = (TextView) childAt;
        }
        setLayoutParams(v.getLayoutParams());
        addView(v);
    }
}


================================================
FILE: commonrefreshlayout/src/main/res/values/attrs.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="crLayout">
        <!-- 自定义加载更多 res layout id-->
        <attr name="load_layout" format="reference" />
        <!--加载更多显示的文字-->
        <attr name="load_text" format="string" />
        <!--加载更多的进度菊花-->
        <attr name="load_indeterminate_drawable" format="reference" />
        <!--加载更多完成显示的文字-->
        <attr name="load_completed_text" format="string" />
        <!--加载更多layout有动画显示效果-->
        <attr name="load_animator" format="boolean"/>
        <attr name="empty_text" format="string"/>
    </declare-styleable>
</resources>


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Fri May 26 15:10:51 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: sample/.gitignore
================================================
/build


================================================
FILE: sample/build.gradle
================================================
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.mylhyl.prlayout.sample"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile project(':commonrefreshlayout')
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:support-v4:23.3.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.mylhyl:cygadapter:1.0.0'
    compile files('libs/lite-http-3.0.0.jar')
    compile 'com.android.support:cardview-v7:23.3.0'
}


================================================
FILE: sample/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\android\android-sdk-windows/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: sample/src/androidTest/java/com/mylhyl/crlayout/sample/ApplicationTest.java
================================================
package com.mylhyl.crlayout.sample;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: sample/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mylhyl.crlayout.sample">

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:name=".APP"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="com.mylhyl.crlayout.sample.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/APP.java
================================================
package com.mylhyl.crlayout.sample;

import android.app.Application;

import com.bumptech.glide.request.target.ViewTarget;

public class APP extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //因为Glide加载图片的源码中也使用了setTag和getTag模式而
        //https://github.com/bumptech/glide/issues/370
        ViewTarget.setTagId(R.string.app_name);
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/MainActivity.java
================================================
package com.mylhyl.crlayout.sample;

import android.content.ContentUris;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;

import com.mylhyl.crlayout.sample.app.AppExpandableListFragment;
import com.mylhyl.crlayout.sample.app.AppListFragment;
import com.mylhyl.crlayout.sample.app.GridViewFragment;
import com.mylhyl.crlayout.sample.app.ListViewFragment;
import com.mylhyl.crlayout.sample.app.RecyclerViewFragment;
import com.mylhyl.crlayout.sample.app.WebViewFragment;

public class MainActivity extends AppCompatActivity implements TypesFragment.OnFragmentInteractionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(android.R.id.content, TypesFragment.newInstance())
                    .commitAllowingStateLoss();
        }
    }

    @Override
    public void onFragmentInteraction(Uri uri) {
        Fragment fragment = null;
        int typeId = (int) ContentUris.parseId(uri);
        switch (typeId) {
            case 0:
                fragment = ListViewFragment.newInstance();
                break;
            case 1:
                fragment = GridViewFragment.newInstance();
                break;
            case 2:
                fragment = RecyclerViewFragment.newInstance();
                break;
            case 3:
                fragment = WebViewFragment.newInstance();
                break;
            case 4:
                fragment = AppListFragment.newInstance();
                break;
            case 5:
                fragment = AppExpandableListFragment.newInstance();
                break;
        }
        if (fragment != null)
            getSupportFragmentManager().beginTransaction()
                    .replace(android.R.id.content, fragment)
                    .addToBackStack(null)
                    .commitAllowingStateLoss();
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/TypesFragment.java
================================================
package com.mylhyl.crlayout.sample;

import android.content.ContentUris;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;


public class TypesFragment extends Fragment implements AdapterView.OnItemClickListener {

    private OnFragmentInteractionListener mListener;
    private Uri mUri = Uri.parse("content://com.mylhyl.crlayout.sample/types");

    public TypesFragment() {
    }

    public static TypesFragment newInstance() {
        return new TypesFragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_types, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ListView listView = (ListView) view.findViewById(R.id.listView);
        listView.setOnItemClickListener(this);
        listView.setAdapter(new ArrayAdapter<>(getContext(),
                android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.types)));
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Uri uri = ContentUris.withAppendedId(mUri, position);
        onButtonPressed(uri);
    }

    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(Uri uri);
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/AppExpandableListFragment.java
================================================
package com.mylhyl.crlayout.sample.app;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;
import android.widget.Toast;

import com.mylhyl.crlayout.SwipeRefreshExpandableListView;
import com.mylhyl.crlayout.app.SwipeRefreshExpandableListFragment;
import com.mylhyl.crlayout.sample.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by hupei on 2016/5/13.
 */
public class AppExpandableListFragment extends SwipeRefreshExpandableListFragment {
    private MyExpandableListAdapter adapter;
    private List<String> groups = new ArrayList<>();
    private List<List<String>> childs = new ArrayList<>();
    private int index;
    private int footerIndex = 20;

    public static AppExpandableListFragment newInstance() {
        return new AppExpandableListFragment();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
        setEnabledLoad(true);
        for (int i = 0; i < footerIndex; i++) {
            groups.add("group = " + i);
            List<String> child = new ArrayList<>();
            for (int j = 0; j < 3; j++) {
                child.add("child = " + i + ":" + j);
            }
            childs.add(child);
        }
        adapter = new MyExpandableListAdapter(this.getContext());
        setListAdapter(adapter);
        setEmptyText("什么也没有!");
    }

    @Override
    public SwipeRefreshExpandableListView createSwipeRefreshLayout() {
        return new SwipeRefreshExpandableListView(getActivity());
    }

    @Override
    public boolean onListGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
        Toast.makeText(getContext(), "groupPosition:" + groupPosition, Toast.LENGTH_SHORT).show();
        return false;
    }

    @Override
    public boolean onListChildClick(ExpandableListView parent, View v,
                                    int groupPosition, int childPosition, long id) {
        Toast.makeText(getContext(), "groupPosition:"
                + groupPosition + " | childPosition:" + childPosition, Toast.LENGTH_SHORT).show();
        return true;
    }

    @Override
    public void onRefresh() {
        getSwipeRefreshLayout().getScrollView().postDelayed(new Runnable() {
            @Override
            public void run() {
                int count = --index;
                groups.add(0, "下拉group = " + count);
                List<String> child = new ArrayList<>();
                for (int j = 0; j < 3; j++) {
                    child.add("下拉child = " + count + ":" + j);
                }
                childs.add(child);
                adapter.notifyDataSetChanged();
                setRefreshing(false);
            }
        }, 1000);
    }

    @Override
    public void onListLoad() {
        getSwipeRefreshLayout().getScrollView().postDelayed(new Runnable() {
            @Override
            public void run() {
                int count = footerIndex + 3;
                for (int i = footerIndex; i < count; i++) {
                    groups.add("上拉group = " + count);
                    List<String> child = new ArrayList<>();
                    for (int j = 0; j < 3; j++) {
                        child.add("上拉child = " + count + ":" + j);
                    }
                    childs.add(0, child);
                }
                footerIndex = count;
                adapter.notifyDataSetChanged();
                setLoading(false);
            }
        }, 2000);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        groups.clear();
        childs.clear();
        adapter.notifyDataSetChanged();
        return super.onOptionsItemSelected(item);
    }

    class MyExpandableListAdapter extends BaseExpandableListAdapter {
        private LayoutInflater inflater;

        public MyExpandableListAdapter(Context context) {
            inflater = LayoutInflater.from(context);
        }

        @Override
        public int getGroupCount() {
            return groups.size();
        }

        @Override
        public int getChildrenCount(int groupPosition) {
            return childs.get(groupPosition).size();
        }

        @Override
        public String getGroup(int groupPosition) {
            return groups.get(groupPosition);
        }

        @Override
        public String getChild(int groupPosition, int childPosition) {
            return childs.get(groupPosition).get(childPosition);
        }

        @Override
        public long getGroupId(int groupPosition) {
            return 0;
        }

        @Override
        public long getChildId(int groupPosition, int childPosition) {
            return 0;
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }

        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
            View view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
            TextView tv = (TextView) view.findViewById(android.R.id.text1);
            tv.setText(getGroup(groupPosition));
            return view;
        }

        @Override
        public View getChildView(int groupPosition, int childPosition,
                                 boolean isLastChild, View convertView, ViewGroup parent) {
            View view = inflater.inflate(android.R.layout.simple_expandable_list_item_2, parent, false);
            TextView tv = (TextView) view.findViewById(android.R.id.text1);
            tv.setText(getChild(groupPosition, childPosition));
            tv.setTextColor(Color.RED);
            return view;
        }

        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/AppListFragment.java
================================================
package com.mylhyl.crlayout.sample.app;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.litesuits.http.LiteHttp;
import com.litesuits.http.listener.HttpListener;
import com.litesuits.http.request.AbstractRequest;
import com.litesuits.http.request.StringRequest;
import com.litesuits.http.request.param.HttpMethods;
import com.litesuits.http.response.Response;
import com.mylhyl.crlayout.internal.LoadConfig;
import com.mylhyl.crlayout.app.SwipeRefreshListFragment;
import com.mylhyl.crlayout.sample.R;
import com.mylhyl.cygadapter.CygAdapter;
import com.mylhyl.cygadapter.CygViewHolder;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by hupei on 2016/5/13.
 */
public class AppListFragment extends SwipeRefreshListFragment {
    private static final String URL = "http://image.baidu.com/";
    private static final String REGEX_IMG = "<img.*?src=\"http://(.*?).jpg\"";
    private CygAdapter<String> adapter;
    private List<String> objects = new ArrayList<>();
    private LiteHttp liteHttp;
    private int index;

    public static AppListFragment newInstance() {
        return new AppListFragment();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);

        getSwipeRefreshLayout().setLoadAnimator(true);
        setEnabledLoad(true);

        adapter = new CygAdapter<String>(getContext(), R.layout.image_item, objects) {
            @Override
            public void onBindData(CygViewHolder viewHolder, String item, int position) {
                ImageView imageView = viewHolder.findViewById(R.id.img_item);
                Glide.with(mContext)
                        .load(item.toString())
                        .into(imageView);
            }
        };
        setListAdapter(adapter);
        setEmptyText("无数据");
        LoadConfig loadConfig = getSwipeRefreshLayout().getLoadConfig();
        loadConfig.setLoadCompletedText("亲,数据加载完了!");
        if (liteHttp == null) {
            liteHttp = LiteHttp.build(getContext())
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .create();
        } else {
            liteHttp.getConfig()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000);
        }
        autoRefresh(R.color.colorPrimary);
    }

    @Override
    public void onListItemClick(AdapterView<?> parent, View view, int position, long id) {
        super.onListItemClick(parent, view, position, id);
        Toast.makeText(getContext(), "" + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRefresh() {
        index = 0;
        adapter.clear(true);
        executeAsync(URL);
        getSwipeRefreshLayout().postDelayed(new Runnable() {
            @Override
            public void run() {
                setRefreshing(false);
            }
        }, 1000);
    }

    @Override
    public void onListLoad() {
        executeAsync(URL);
        getSwipeRefreshLayout().postDelayed(new Runnable() {
            @Override
            public void run() {
                setLoading(false);
                ++index;
                if (index == 1) {
                    getSwipeRefreshLayout().setLoadCompleted(true);
                }
            }
        }, 1000);
    }

    private void executeAsync(String url) {
        StringRequest stringRequest = new StringRequest(url).setMethod(HttpMethods.Get)
                .setHttpListener(new HttpListener<String>() {
                    @Override
                    public void onLoading(AbstractRequest<String> request, long total, long len) {
                        super.onLoading(request, total, len);
                    }

                    @Override
                    public void onSuccess(String s, Response<String> response) {
                        String result = response.getResult();
                        List<String> imgSrcList = getImgSrcList(result);
                        adapter.addAll(imgSrcList);
                    }

                    @Override
                    public void onStart(AbstractRequest<String> request) {
                        super.onStart(request);
                    }

                    @Override
                    public void onUploading(AbstractRequest<String> request, long total, long len) {
                        super.onUploading(request, total, len);
                    }
                });
        liteHttp.executeAsync(stringRequest);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        objects.clear();
        adapter.notifyDataSetChanged();
        return super.onOptionsItemSelected(item);
    }

    private static List<String> getImgSrcList(String htmlStr) {
        List<String> pics = new ArrayList<>();
        Pattern pImage = Pattern.compile(REGEX_IMG, Pattern.CASE_INSENSITIVE);
        Matcher mImage = pImage.matcher(htmlStr);
        while (mImage.find()) {
            String src = mImage.group(1);
            if (src.length() < 100) {
                pics.add("http://" + src + ".jpg");
            }
        }
        return pics;
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/GridViewFragment.java
================================================
package com.mylhyl.crlayout.sample.app;

import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Toast;

import com.mylhyl.crlayout.internal.LoadConfig;
import com.mylhyl.crlayout.SwipeRefreshAdapterView;
import com.mylhyl.crlayout.SwipeRefreshGridView;
import com.mylhyl.crlayout.sample.R;

import java.util.ArrayList;
import java.util.List;


public class GridViewFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,
        SwipeRefreshAdapterView.OnListLoadListener, AdapterView.OnItemClickListener {
    private SwipeRefreshGridView swipeRefreshGridView;
    private ArrayAdapter<String> adapter;
    private List<String> objects = new ArrayList<>();
    private int index;
    private int footerIndex = 38;

    public GridViewFragment() {
    }

    public static GridViewFragment newInstance() {
        GridViewFragment fragment = new GridViewFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_grid_view, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        swipeRefreshGridView = (SwipeRefreshGridView) view.findViewById(R.id.swipeRefresh);
        ImageView emptyView = new ImageView(getContext());
        emptyView.setImageResource(R.mipmap.empty);
        swipeRefreshGridView.setEmptyView(emptyView);
        swipeRefreshGridView.setLoadAnimator(true);
        swipeRefreshGridView.setLoadLayoutResource(R.layout.swipe_refresh_footer);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
        swipeRefreshGridView.setOnItemClickListener(this);
        swipeRefreshGridView.setOnListLoadListener(this);
        swipeRefreshGridView.setOnRefreshListener(this);

        LoadConfig loadConfig = swipeRefreshGridView.getLoadConfig();
        loadConfig.setLoadText("加载更多数据...");
        loadConfig.setLoadTextSize(18);
        loadConfig.setLoadTextColor(Color.GREEN);

        for (int i = 0; i < footerIndex; i++) {
            objects.add("Grid数据 = " + i);
        }
        adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, objects);
        swipeRefreshGridView.setAdapter(adapter);
    }


    @Override
    public void onRefresh() {
        index = 0;
        swipeRefreshGridView.postDelayed(new Runnable() {
            @Override
            public void run() {
                objects.add(0, "下拉 = " + (--index));
                adapter.notifyDataSetChanged();
                swipeRefreshGridView.setRefreshing(false);
            }
        }, 1000);
    }

    @Override
    public void onListLoad() {
        ++index;
        swipeRefreshGridView.postDelayed(new Runnable() {
            @Override
            public void run() {
                int count = footerIndex + 15;
                for (int i = footerIndex; i < count; i++) {
                    objects.add("上拉 = " + i);
                }
                footerIndex = count;
                adapter.notifyDataSetChanged();
                swipeRefreshGridView.setLoading(false);
                if (index == 1) {
                    swipeRefreshGridView.setLoadCompleted(true);
                }
            }
        }, 2000);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        objects.clear();
        adapter.notifyDataSetChanged();
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Toast.makeText(getContext(), "" + position, Toast.LENGTH_SHORT).show();
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/ListViewFragment.java
================================================
package com.mylhyl.crlayout.sample.app;

import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.mylhyl.crlayout.SwipeRefreshAdapterView;
import com.mylhyl.crlayout.SwipeRefreshListView;
import com.mylhyl.crlayout.internal.LoadConfig;
import com.mylhyl.crlayout.sample.R;

import java.util.ArrayList;
import java.util.List;


public class ListViewFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,
        SwipeRefreshAdapterView.OnListLoadListener, AdapterView.OnItemClickListener {
    private SwipeRefreshListView swipeRefreshListView;
    private ArrayAdapter<String> adapter;
    private List<String> objects = new ArrayList<>();
    private int index;
    private int pagerSize = 20;

    public ListViewFragment() {
    }

    public static ListViewFragment newInstance() {
        ListViewFragment fragment = new ListViewFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_list_view, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        swipeRefreshListView = (SwipeRefreshListView) view.findViewById(R.id.swipeRefresh);
        swipeRefreshListView.getSwipeRefreshLayout().setColorSchemeResources(R.color.colorPrimary);
        swipeRefreshListView.setEnabled(false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
        swipeRefreshListView.setOnItemClickListener(this);
        swipeRefreshListView.setOnListLoadListener(this);
        swipeRefreshListView.setOnRefreshListener(this);

        initListViewHead();

        LoadConfig loadConfig = swipeRefreshListView.getLoadConfig();
        loadConfig.setLoadViewBackgroundColor(getResources().getColor(android.R.color.darker_gray));
//        swipeRefreshListView.setEmptyText("数据呢?");

        for (int i = 0; i < pagerSize; i++) {
            objects.add("数据 = " + i);
        }
        adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, objects);
        swipeRefreshListView.setAdapter(adapter);

    }

    private int mCurrentPosition;
    private ViewPager mViewPager;
    private final Handler mAutoPlayHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mCurrentPosition++;
            if (mViewPager != null)
                mViewPager.setCurrentItem(mCurrentPosition);
            mAutoPlayHandler.sendEmptyMessageDelayed(1000, 3000);
        }
    };

    private void initListViewHead() {
        if (mViewPager == null) {
            mViewPager = new ViewPager(getContext());
            mViewPager.setLayoutParams(new AbsListView.LayoutParams(
                    AbsListView.LayoutParams.MATCH_PARENT, (int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics())));
        }
        mViewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return 4 + 2;
            }

            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
            }

            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                int toRealPosition = toRealPosition(position);
                TextView textView = (TextView) container.getChildAt(toRealPosition);
                if (textView == null) {
                    textView = new TextView(getContext());
                    textView.setTextColor(Color.RED);
                    textView.setTextSize(18);
                    textView.setGravity(Gravity.CENTER);
                    container.addView(textView);
                }
                textView.setText("position=" + toRealPosition);
                return textView;
            }
        });

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                mCurrentPosition = position % (4 + 2);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                if (state == ViewPager.SCROLL_STATE_IDLE) {
                    int current = mViewPager.getCurrentItem();
                    int last = mViewPager.getAdapter().getCount() - 2;
                    if (current == 0) {
                        mViewPager.setCurrentItem(last, false);
                    } else if (current == last + 1) {
                        mViewPager.setCurrentItem(1, false);
                    }
                }
            }
        });
        mViewPager.setCurrentItem(1, false);
        swipeRefreshListView.getScrollView().addHeaderView(mViewPager);
        mAutoPlayHandler.sendEmptyMessageDelayed(1000, 3000);
    }

    private int toRealPosition(int position) {
        int realPosition = (position - 1) % 4;
        if (realPosition < 0)
            realPosition += 4;

        return realPosition;
    }

    @Override
    public void onDestroyView() {
        if (mAutoPlayHandler != null)
            mAutoPlayHandler.removeMessages(1000);
        super.onDestroyView();
    }


    @Override
    public void onRefresh() {
        index = 0;
        swipeRefreshListView.postDelayed(new Runnable() {
            @Override
            public void run() {
                objects.add(0, "下拉 = " + (--index));
                adapter.notifyDataSetChanged();
                swipeRefreshListView.setRefreshing(false);
            }
        }, 1000);
    }

    @Override
    public void onListLoad() {
        ++index;
        swipeRefreshListView.postDelayed(new Runnable() {
            @Override
            public void run() {
                int count = pagerSize + 10;
                for (int i = pagerSize; i < count; i++) {
                    objects.add("上拉 = " + i);
                }
                pagerSize = count;
                adapter.notifyDataSetChanged();
                swipeRefreshListView.setLoading(false);

                if (index == 1) {
                    swipeRefreshListView.setLoadCompleted(true);
                }
            }
        }, 1000);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        objects.clear();
        adapter.notifyDataSetChanged();
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        //有head,position-1才是真实item
        Toast.makeText(getContext(), "" + (position - 1), Toast.LENGTH_SHORT).show();
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/RecyclerViewFragment.java
================================================
package com.mylhyl.crlayout.sample.app;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.mylhyl.crlayout.SwipeRefreshAdapterView;
import com.mylhyl.crlayout.SwipeRefreshRecyclerView;
import com.mylhyl.crlayout.sample.R;

import java.util.ArrayList;
import java.util.List;


public class RecyclerViewFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,
        SwipeRefreshAdapterView.OnListLoadListener {
    private SwipeRefreshRecyclerView swipeRefreshRecyclerView;
    private RecyclerViewAdapter adapter;
    private List<String> objects = new ArrayList<>();
    private int index;
    private int footerIndex = 10;

    public RecyclerViewFragment() {
    }

    public static RecyclerViewFragment newInstance() {
        RecyclerViewFragment fragment = new RecyclerViewFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_recycler_view, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        swipeRefreshRecyclerView = (SwipeRefreshRecyclerView) view.findViewById(R.id.swipeRefresh);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
        swipeRefreshRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(),
                LinearLayoutManager.VERTICAL, false));
        swipeRefreshRecyclerView.setOnListLoadListener(this);
        swipeRefreshRecyclerView.setOnRefreshListener(this);

        for (int i = 0; i < footerIndex; i++) {
            objects.add("数据 = " + i);
        }
        adapter = new RecyclerViewAdapter();
        swipeRefreshRecyclerView.setAdapter(adapter);
        swipeRefreshRecyclerView.setEmptyText("数据又没有了!");
    }


    @Override
    public void onRefresh() {
        index = 0;
        swipeRefreshRecyclerView.postDelayed(new Runnable() {
            @Override
            public void run() {
                objects.add(0, "下拉 = " + (--index));
                adapter.notifyDataSetChanged();
                swipeRefreshRecyclerView.setRefreshing(false);
            }
        }, 1000);
    }

    @Override
    public void onListLoad() {
        ++index;
//        swipeRefreshRecyclerView.postDelayed(new Runnable() {
//            @Override
//            public void run() {
        int count = footerIndex + 5;
        for (int i = footerIndex; i < count; i++) {
            objects.add("上拉 = " + i);
        }
        footerIndex = count;
        adapter.notifyDataSetChanged();
        swipeRefreshRecyclerView.setLoading(false);
//                if (index == 1) {
//                    swipeRefreshRecyclerView.setLoadCompleted(true);
//                }
//            }
//        }, 2000);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.menu) {
            objects.clear();
            adapter.notifyDataSetChanged();
        } else if (item.getItemId() == R.id.menu_reset) {
            objects.clear();
            for (int i = 0; i < 5; i++) {
                objects.add("重置数据 = " + i);
            }
            adapter = new RecyclerViewAdapter();
            swipeRefreshRecyclerView.setAdapter(adapter);
        }
        return super.onOptionsItemSelected(item);
    }

    class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

        @Override
        public int getItemCount() {
            return objects.size();
        }

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
                    getContext()).inflate(R.layout.fragment_recycler_view_item, parent,
                    false));
            return holder;
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ((MyViewHolder) holder).tv.setText(objects.get(position));
        }

        class MyViewHolder extends RecyclerView.ViewHolder {
            TextView tv;

            public MyViewHolder(View view) {
                super(view);
                tv = (TextView) view.findViewById(android.R.id.text1);
            }
        }

    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/WebViewFragment.java
================================================
package com.mylhyl.crlayout.sample.app;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.mylhyl.crlayout.SwipeRefreshWebView;
import com.mylhyl.crlayout.sample.R;


public class WebViewFragment extends Fragment {
    private SwipeRefreshWebView swipeRefreshWebView;

    public WebViewFragment() {
    }

    public static WebViewFragment newInstance() {
        WebViewFragment fragment = new WebViewFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_web_view, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        swipeRefreshWebView = (SwipeRefreshWebView) view.findViewById(R.id.swipeRefresh);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);
        swipeRefreshWebView.autoRefresh(R.color.colorPrimary);
        WebView scrollView = swipeRefreshWebView.getScrollView();
        scrollView.loadUrl("https://github.com/mylhyl");
        scrollView.setWebViewClient(new SampleWebViewClient());
    }

    private class SampleWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            swipeRefreshWebView.autoRefresh();
            view.loadUrl(url);
            return true;
        }
    }
}


================================================
FILE: sample/src/main/java/com/mylhyl/crlayout/sample/widget/MySwipeRefreshGridView.java
================================================
package com.mylhyl.crlayout.sample.widget;

import android.content.Context;
import android.util.AttributeSet;

import com.mylhyl.crlayout.SwipeRefreshGridView;
import com.mylhyl.crlayout.sample.R;

/**
 * Created by hupei on 2016/5/16.
 */
public class MySwipeRefreshGridView extends SwipeRefreshGridView {
    public MySwipeRefreshGridView(Context context) {
        super(context);
    }

    public MySwipeRefreshGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected int getLoadLayoutResource() {
        return R.layout.swipe_refresh_footer;
    }
}


================================================
FILE: sample/src/main/res/drawable/footer_progressbar.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360">
    <shape
        android:innerRadiusRatio="3"
        android:shape="ring"
        android:thicknessRatio="8"
        android:useLevel="false">
        <gradient
            android:centerColor="#FF7121"
            android:centerY="0.50"
            android:endColor="#FFFF00"
            android:startColor="#6BD3FF"
            android:type="sweep"
            android:useLevel="false" />
    </shape>
</animated-rotate>

================================================
FILE: sample/src/main/res/drawable/selector_list.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/holo_red_light" android:state_pressed="true" />
    <item android:drawable="@android:color/white" android:state_pressed="false" />
</selector>

================================================
FILE: sample/src/main/res/layout/fragment_grid_view.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<com.mylhyl.crlayout.sample.widget.MySwipeRefreshGridView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:crl="http://schemas.android.com/apk/res-auto"
    android:id="@+id/swipeRefresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:numColumns="2"
    crl:load_completed_text="全部加载完成"
    tools:context=".app.GridViewFragment" />


================================================
FILE: sample/src/main/res/layout/fragment_list_view.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<com.mylhyl.crlayout.SwipeRefreshListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:crl="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/swipeRefresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/darker_gray"
    android:listSelector="@drawable/selector_list"
    crl:load_text="数据正在加载中"
    crl:empty_text="数据呢?"
    crl:load_indeterminate_drawable="@drawable/footer_progressbar"
    tools:context=".app.ListViewFragment" />


================================================
FILE: sample/src/main/res/layout/fragment_recycler_view.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<com.mylhyl.crlayout.SwipeRefreshRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:crl="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/swipeRefresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    crl:load_animator="true"
    tools:context=".app.RecyclerViewFragment">

    <RadioButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="20dp"
        android:background="@color/colorPrimary" />
</com.mylhyl.crlayout.SwipeRefreshRecyclerView>


================================================
FILE: sample/src/main/res/layout/fragment_recycler_view_item.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    android:layout_marginBottom="2dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="2dp"
    app:cardCornerRadius="5dp"
    app:elevation="1dp">

    <TextView
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="left|center_vertical"
        android:padding="5dp"
        android:textSize="21sp" />

</android.support.v7.widget.CardView>

================================================
FILE: sample/src/main/res/layout/fragment_types.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mylhyl.crlayout.sample.TypesFragment" />


================================================
FILE: sample/src/main/res/layout/fragment_web_view.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<com.mylhyl.crlayout.SwipeRefreshWebView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/swipeRefresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".app.WebViewFragment" />


================================================
FILE: sample/src/main/res/layout/image_item.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/img_item"
    android:layout_width="200dp"
    android:layout_height="200dp"/>

================================================
FILE: sample/src/main/res/layout/swipe_refresh_footer.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:background="@android:color/holo_red_light"
    android:gravity="center"
    android:padding="10dp">

    <ProgressBar
        style="@android:style/Widget.ProgressBar.Small.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="xml自定义加载"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@android:color/darker_gray"
        android:textSize="14sp"
        android:textStyle="bold" />
</LinearLayout>

================================================
FILE: sample/src/main/res/menu/menu.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu"
        android:showAsAction="always"
        android:title="清空"/>
    <item
        android:id="@+id/menu_reset"
        android:showAsAction="always"
        android:title="重置"/>
</menu>

================================================
FILE: sample/src/main/res/values/array.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="types">
        <item>ListView</item>
        <item>GridView</item>
        <item>RecyclerView</item>
        <item>WebView</item>
        <item>AppListFragment</item>
        <item>AppExpandableListFragment</item>
    </string-array>
</resources>

================================================
FILE: sample/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>


================================================
FILE: sample/src/main/res/values/dimens.xml
================================================
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>


================================================
FILE: sample/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">CommonRefreshLayout</string>

    <!-- TODO: Remove or change this placeholder text -->
    <string name="hello_blank_fragment">Hello blank fragment</string>
</resources>


================================================
FILE: sample/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


================================================
FILE: sample/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
         (such as screen margins) for screens with more than 820dp of available width. This
         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
    <dimen name="activity_horizontal_margin">64dp</dimen>
</resources>


================================================
FILE: sample/src/test/java/com/mylhyl/crlayout/sample/ExampleUnitTest.java
================================================
package com.mylhyl.crlayout.sample;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * To work on unit tests, switch the Test Artifact in the Build Variants view.
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: settings.gradle
================================================
include ':sample', ':commonrefreshlayout'
Download .txt
gitextract_bdxoz3li/

├── .gitignore
├── README.md
├── build.gradle
├── commonrefreshlayout/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── mylhyl/
│       │               └── crlayout/
│       │                   └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── mylhyl/
│           │           └── crlayout/
│           │               ├── BaseSwipeRefresh.java
│           │               ├── MultiSwipeRefreshLayout.java
│           │               ├── SwipeRefreshAbsListView.java
│           │               ├── SwipeRefreshAdapterView.java
│           │               ├── SwipeRefreshExpandableListView.java
│           │               ├── SwipeRefreshGridView.java
│           │               ├── SwipeRefreshListView.java
│           │               ├── SwipeRefreshRecyclerView.java
│           │               ├── SwipeRefreshWebView.java
│           │               ├── app/
│           │               │   ├── BaseSwipeRefreshFragment.java
│           │               │   ├── SwipeRefreshAbsListFragment.java
│           │               │   ├── SwipeRefreshAdapterFragment.java
│           │               │   ├── SwipeRefreshExpandableListFragment.java
│           │               │   └── SwipeRefreshListFragment.java
│           │               └── internal/
│           │                   ├── ILoadSwipeRefresh.java
│           │                   ├── ISwipeRefresh.java
│           │                   ├── LoadConfig.java
│           │                   ├── LoadLayout.java
│           │                   ├── LoadLayoutBase.java
│           │                   └── LoadLayoutConvert.java
│           └── res/
│               └── values/
│                   └── attrs.xml
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── preview/
│   └── sample-debug.apk
├── sample/
│   ├── .gitignore
│   ├── build.gradle
│   ├── libs/
│   │   └── lite-http-3.0.0.jar
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── mylhyl/
│       │               └── crlayout/
│       │                   └── sample/
│       │                       └── ApplicationTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── mylhyl/
│       │   │           └── crlayout/
│       │   │               └── sample/
│       │   │                   ├── APP.java
│       │   │                   ├── MainActivity.java
│       │   │                   ├── TypesFragment.java
│       │   │                   ├── app/
│       │   │                   │   ├── AppExpandableListFragment.java
│       │   │                   │   ├── AppListFragment.java
│       │   │                   │   ├── GridViewFragment.java
│       │   │                   │   ├── ListViewFragment.java
│       │   │                   │   ├── RecyclerViewFragment.java
│       │   │                   │   └── WebViewFragment.java
│       │   │                   └── widget/
│       │   │                       └── MySwipeRefreshGridView.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── footer_progressbar.xml
│       │       │   └── selector_list.xml
│       │       ├── layout/
│       │       │   ├── fragment_grid_view.xml
│       │       │   ├── fragment_list_view.xml
│       │       │   ├── fragment_recycler_view.xml
│       │       │   ├── fragment_recycler_view_item.xml
│       │       │   ├── fragment_types.xml
│       │       │   ├── fragment_web_view.xml
│       │       │   ├── image_item.xml
│       │       │   └── swipe_refresh_footer.xml
│       │       ├── menu/
│       │       │   └── menu.xml
│       │       ├── values/
│       │       │   ├── array.xml
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       └── values-w820dp/
│       │           └── dimens.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── mylhyl/
│                       └── crlayout/
│                           └── sample/
│                               └── ExampleUnitTest.java
└── settings.gradle
Download .txt
SYMBOL INDEX (324 symbols across 33 files)

FILE: commonrefreshlayout/src/androidTest/java/com/mylhyl/crlayout/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/BaseSwipeRefresh.java
  class BaseSwipeRefresh (line 31) | public abstract class BaseSwipeRefresh<T extends View> extends FrameLayo...
    method createScrollView (line 40) | protected abstract T createScrollView(Context context, AttributeSet at...
    method BaseSwipeRefresh (line 51) | public BaseSwipeRefresh(Context context) {
    method BaseSwipeRefresh (line 55) | public BaseSwipeRefresh(Context context, AttributeSet attrs) {
    method BaseSwipeRefresh (line 59) | public BaseSwipeRefresh(Context context, AttributeSet attrs, int defSt...
    method BaseSwipeRefresh (line 65) | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    method init (line 72) | private void init(Context context, AttributeSet attrs, int defStyleAtt...
    method createEmptyView (line 87) | @SuppressWarnings("ResourceType")
    method addSwipeRefreshView (line 98) | private void addSwipeRefreshView(Context context, MultiSwipeRefreshLay...
    method autoRefresh (line 112) | @Override
    method autoRefresh (line 118) | @Override
    method autoRefresh (line 124) | @Override
    method setEmptyText (line 130) | @Override
    method setEmptyText (line 135) | @Override
    method setEmptyView (line 143) | @Override
    method convertEmptyViewLayoutParams (line 166) | private static FrameLayout.LayoutParams convertEmptyViewLayoutParams(V...
    method getEmptyView (line 177) | @Override
    method updateEmptyViewShown (line 182) | final void updateEmptyViewShown(boolean shown) {
    method setOnRefreshListener (line 191) | @Override
    method setRefreshing (line 197) | @Override
    method setEnabled (line 206) | @Override
    method getScrollView (line 211) | @Override
    method getSwipeRefreshLayout (line 216) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/MultiSwipeRefreshLayout.java
  class MultiSwipeRefreshLayout (line 14) | public final class MultiSwipeRefreshLayout extends SwipeRefreshLayout {
    method MultiSwipeRefreshLayout (line 26) | public MultiSwipeRefreshLayout(Context context) {
    method MultiSwipeRefreshLayout (line 30) | public MultiSwipeRefreshLayout(Context context, AttributeSet attrs) {
    method showProgressView (line 38) | public final void showProgressView() {
    method showProgressView (line 44) | public final void showProgressView(@ColorRes int... colorResIds) {
    method showProgressView (line 48) | public final void showProgressView(boolean scale, int start, int end, ...
    method onInterceptTouchEvent (line 56) | @Override
    method setSwipeableChildren (line 73) | final void setSwipeableChildren(final View... views) {
    method canChildScrollUp (line 79) | @Override
    method canViewScrollUp (line 91) | private static boolean canViewScrollUp(View target) {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAbsListView.java
  class SwipeRefreshAbsListView (line 17) | public abstract class SwipeRefreshAbsListView<T extends AbsListView> ext...
    method SwipeRefreshAbsListView (line 22) | public SwipeRefreshAbsListView(Context context) {
    method SwipeRefreshAbsListView (line 26) | public SwipeRefreshAbsListView(Context context, AttributeSet attrs) {
    method setOnItemClickListener (line 30) | public final void setOnItemClickListener(AdapterView.OnItemClickListen...
    method setAdapter (line 39) | public final void setAdapter(ListAdapter adapter) {
    method registerDataSetObserver (line 48) | final void registerDataSetObserver(ListAdapter adapter) {
    method onDetachedFromWindow (line 60) | @Override
    class OnScrollAbsListListener (line 69) | public static class OnScrollAbsListListener implements AbsListView.OnS...
      method OnScrollAbsListListener (line 73) | public OnScrollAbsListListener(ILoadSwipeRefresh loadSwipeRefresh) {
      method OnScrollAbsListListener (line 77) | public OnScrollAbsListListener(ILoadSwipeRefresh loadSwipeRefresh, A...
      method onScrollStateChanged (line 83) | @Override
      method onScroll (line 97) | @Override
    class EmptyDataSetObserver (line 106) | private class EmptyDataSetObserver extends DataSetObserver {
      method onChanged (line 107) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAdapterView.java
  class SwipeRefreshAdapterView (line 22) | public abstract class SwipeRefreshAdapterView<T extends View> extends Ba...
    method SwipeRefreshAdapterView (line 44) | public SwipeRefreshAdapterView(Context context) {
    method SwipeRefreshAdapterView (line 48) | public SwipeRefreshAdapterView(Context context, AttributeSet attrs) {
    method SwipeRefreshAdapterView (line 52) | public SwipeRefreshAdapterView(Context context, AttributeSet attrs, in...
    method SwipeRefreshAdapterView (line 57) | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    method init (line 64) | private void init(Context context, AttributeSet attrs, int defStyleAtt...
    method onMeasure (line 81) | @Override
    method initShowLoadAnimator (line 94) | private void initShowLoadAnimator() {
    method initHideLoadAnimator (line 116) | private void initHideLoadAnimator() {
    method setOnListLoadListener (line 130) | @Override
    method addLoadLayout (line 137) | private void addLoadLayout() {
    method createLoadLayout (line 147) | private void createLoadLayout() {
    method setLoadLayoutResource (line 172) | @Override
    method getLoadLayoutResource (line 185) | protected int getLoadLayoutResource() {
    method loadData (line 190) | @Override
    method setLoading (line 195) | @Override
    method showLoadLayout (line 203) | private void showLoadLayout() {
    method hideLoadLayout (line 227) | private void hideLoadLayout() {
    method setEnabledLoad (line 232) | @Override
    method isLoading (line 237) | @Override
    method isEnabledLoad (line 242) | @Override
    method setLoadCompleted (line 247) | @Override
    method getLoadConfig (line 252) | @Override
    method setLoadAnimator (line 258) | @Override
    type OnListLoadListener (line 265) | public interface OnListLoadListener {
      method onListLoad (line 269) | void onListLoad();
    class SimpleAnimatorListener (line 272) | static class SimpleAnimatorListener implements Animator.AnimatorListen...
      method onAnimationStart (line 273) | @Override
      method onAnimationEnd (line 278) | @Override
      method onAnimationCancel (line 283) | @Override
      method onAnimationRepeat (line 288) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshExpandableListView.java
  class SwipeRefreshExpandableListView (line 17) | public class SwipeRefreshExpandableListView extends SwipeRefreshAbsListV...
    method SwipeRefreshExpandableListView (line 20) | public SwipeRefreshExpandableListView(Context context) {
    method SwipeRefreshExpandableListView (line 24) | public SwipeRefreshExpandableListView(Context context, AttributeSet at...
    method setAdapter (line 33) | public final void setAdapter(ExpandableListAdapter adapter) {
    method createScrollView (line 42) | @Override
    class ExpandableListConnector (line 49) | private class ExpandableListConnector extends BaseAdapter {
      method ExpandableListConnector (line 52) | public ExpandableListConnector(ExpandableListAdapter expandableListA...
      method getCount (line 56) | @Override
      method registerDataSetObserver (line 62) | @Override
      method unregisterDataSetObserver (line 67) | @Override
      method getItem (line 72) | @Override
      method getItemId (line 77) | @Override
      method getView (line 82) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshGridView.java
  class SwipeRefreshGridView (line 12) | public class SwipeRefreshGridView extends SwipeRefreshAbsListView<GridVi...
    method createScrollView (line 14) | @Override
    method SwipeRefreshGridView (line 21) | public SwipeRefreshGridView(Context context) {
    method SwipeRefreshGridView (line 25) | public SwipeRefreshGridView(Context context, AttributeSet attrs) {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshListView.java
  class SwipeRefreshListView (line 12) | public class SwipeRefreshListView extends SwipeRefreshAbsListView<ListVi...
    method SwipeRefreshListView (line 14) | public SwipeRefreshListView(Context context) {
    method SwipeRefreshListView (line 18) | public SwipeRefreshListView(Context context, AttributeSet attrs) {
    method createScrollView (line 22) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshRecyclerView.java
  class SwipeRefreshRecyclerView (line 15) | public class SwipeRefreshRecyclerView extends SwipeRefreshAdapterView<Re...
    method SwipeRefreshRecyclerView (line 19) | public SwipeRefreshRecyclerView(Context context) {
    method SwipeRefreshRecyclerView (line 23) | public SwipeRefreshRecyclerView(Context context, AttributeSet attrs) {
    method setAdapter (line 32) | public final void setAdapter(RecyclerView.Adapter adapter) {
    method setLayoutManager (line 41) | public void setLayoutManager(RecyclerView.LayoutManager layout) {
    method createScrollView (line 45) | @Override
    method registerAdapterDataObserver (line 52) | private void registerAdapterDataObserver(RecyclerView.Adapter adapter) {
    method onDetachedFromWindow (line 64) | @Override
    class OnScrollRecyclerViewListener (line 73) | public static class OnScrollRecyclerViewListener extends RecyclerView....
      method OnScrollRecyclerViewListener (line 77) | public OnScrollRecyclerViewListener(ILoadSwipeRefresh loadSwipeRefre...
      method OnScrollRecyclerViewListener (line 81) | public OnScrollRecyclerViewListener(ILoadSwipeRefresh loadSwipeRefre...
      method onScrollStateChanged (line 87) | @Override
      method onScrolled (line 102) | @Override
      method isFirstItemVisible (line 115) | private boolean isFirstItemVisible(RecyclerView recyclerView) {
      method getFirstVisiblePosition (line 134) | private int getFirstVisiblePosition(RecyclerView recyclerView) {
      method isLastItemVisible (line 146) | private boolean isLastItemVisible(RecyclerView recyclerView) {
      method getLastVisiblePosition (line 167) | private int getLastVisiblePosition(RecyclerView recyclerView) {
    class EmptyDataSetObserver (line 174) | private class EmptyDataSetObserver extends RecyclerView.AdapterDataObs...
      method onChanged (line 175) | @Override
      method onItemRangeChanged (line 181) | @Override
      method onItemRangeChanged (line 186) | @Override
      method onItemRangeInserted (line 191) | @Override
      method onItemRangeMoved (line 196) | @Override
      method onItemRangeRemoved (line 201) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshWebView.java
  class SwipeRefreshWebView (line 14) | public class SwipeRefreshWebView extends BaseSwipeRefresh<WebView> {
    method onRefresh (line 16) | @Override
    method onProgressChanged (line 23) | @Override
    method SwipeRefreshWebView (line 31) | public SwipeRefreshWebView(Context context) {
    method SwipeRefreshWebView (line 35) | public SwipeRefreshWebView(Context context, AttributeSet attrs) {
    method autoRefresh (line 43) | @Override
    method autoRefresh (line 49) | @Override
    method createScrollView (line 56) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/BaseSwipeRefreshFragment.java
  class BaseSwipeRefreshFragment (line 22) | abstract class BaseSwipeRefreshFragment<T extends BaseSwipeRefresh> exte...
    method createSwipeRefreshLayout (line 30) | public abstract T createSwipeRefreshLayout();
    method onCreateView (line 34) | @Override
    method onViewCreated (line 39) | @Override
    method autoRefresh (line 46) | public final void autoRefresh() {
    method autoRefresh (line 50) | public final void autoRefresh(@ColorRes int... colorResIds) {
    method setRefreshing (line 57) | public final void setRefreshing(boolean refreshing) {
    method setEmptyText (line 62) | public final void setEmptyText(int resId) {
    method setEmptyText (line 66) | public final void setEmptyText(CharSequence text) {
    method setEmptyView (line 70) | public final void setEmptyView(View emptyView) {
    method getSwipeRefreshLayout (line 74) | public final T getSwipeRefreshLayout() {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAbsListFragment.java
  class SwipeRefreshAbsListFragment (line 12) | abstract class SwipeRefreshAbsListFragment<T extends SwipeRefreshAbsList...
    method onItemClick (line 15) | @Override
    method onListItemClick (line 33) | public void onListItemClick(AdapterView<?> parent, View view, int posi...
    method setListAdapter (line 43) | public final void setListAdapter(ListAdapter adapter) {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAdapterFragment.java
  class SwipeRefreshAdapterFragment (line 10) | abstract class SwipeRefreshAdapterFragment<T extends SwipeRefreshAdapter...
    method setEnabledLoad (line 21) | public final void setEnabledLoad(boolean enabled) {
    method setLoading (line 31) | public final void setLoading(boolean loading) {
    method onListLoad (line 35) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshExpandableListFragment.java
  class SwipeRefreshExpandableListFragment (line 13) | public abstract class SwipeRefreshExpandableListFragment extends SwipeRe...
    method onGroupClick (line 15) | @Override
    method onChildClick (line 22) | @Override
    method onListChildClick (line 28) | public boolean onListChildClick(ExpandableListView parent, View v, int...
    method onListGroupClick (line 32) | public boolean onListGroupClick(ExpandableListView parent, View v, int...
    method onListItemClick (line 36) | @Override
    method createSwipeRefreshLayout (line 42) | @Override
    method setListAdapter (line 47) | public final void setListAdapter(ExpandableListAdapter adapter) {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshListFragment.java
  class SwipeRefreshListFragment (line 5) | public abstract class SwipeRefreshListFragment extends SwipeRefreshAbsLi...
    method createSwipeRefreshLayout (line 7) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ILoadSwipeRefresh.java
  type ILoadSwipeRefresh (line 8) | public interface ILoadSwipeRefresh {
    method setOnListLoadListener (line 10) | void setOnListLoadListener(SwipeRefreshAdapterView.OnListLoadListener ...
    method setLoadLayoutResource (line 12) | void setLoadLayoutResource(int resource);
    method loadData (line 14) | void loadData();
    method setLoading (line 21) | void setLoading(boolean loading);
    method setEnabledLoad (line 28) | void setEnabledLoad(boolean enabled);
    method isLoading (line 35) | boolean isLoading();
    method isEnabledLoad (line 42) | boolean isEnabledLoad();
    method setLoadCompleted (line 49) | void setLoadCompleted(boolean loadCompleted);
    method getLoadConfig (line 51) | LoadConfig getLoadConfig();
    method setLoadAnimator (line 58) | void setLoadAnimator(boolean isLoadAnimator);

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ISwipeRefresh.java
  type ISwipeRefresh (line 10) | public interface ISwipeRefresh<T> {
    method autoRefresh (line 14) | void autoRefresh();
    method autoRefresh (line 21) | void autoRefresh(@ColorRes int... colorResIds);
    method autoRefresh (line 23) | void autoRefresh(boolean scale, int start, int end, @ColorRes int... c...
    method setOnRefreshListener (line 25) | void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener);
    method setEmptyText (line 27) | void setEmptyText(CharSequence text);
    method setEmptyText (line 29) | void setEmptyText(int resId);
    method setEmptyView (line 31) | void setEmptyView(View emptyView);
    method getEmptyView (line 33) | View getEmptyView();
    method setRefreshing (line 40) | void setRefreshing(boolean refreshing);
    method setEnabled (line 47) | void setEnabled(boolean enabled);
    method getScrollView (line 54) | T getScrollView();
    method getSwipeRefreshLayout (line 57) | SwipeRefreshLayout getSwipeRefreshLayout();

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadConfig.java
  type LoadConfig (line 8) | public interface LoadConfig {
    method setLoadText (line 14) | void setLoadText(String label);
    method setLoadTextSize (line 21) | void setLoadTextSize(float size);
    method setLoadTextColor (line 28) | void setLoadTextColor(int color);
    method setProgressBarVisibility (line 35) | void setProgressBarVisibility(int v);
    method setIndeterminateDrawable (line 42) | void setIndeterminateDrawable(Drawable d);
    method setLoadCompletedText (line 49) | void setLoadCompletedText(String text);
    method setLoadViewHeight (line 56) | void setLoadViewHeight(int height);
    method setLoadViewBackgroundResource (line 63) | void setLoadViewBackgroundResource(int resId);
    method setLoadViewBackgroundColor (line 70) | void setLoadViewBackgroundColor(int color);

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayout.java
  class LoadLayout (line 16) | public final class LoadLayout extends LoadLayoutBase {
    method LoadLayout (line 17) | public LoadLayout(Context context) {
    method createFooter (line 21) | @Override

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutBase.java
  class LoadLayoutBase (line 18) | public abstract class LoadLayoutBase extends LinearLayout implements Loa...
    method createFooter (line 26) | abstract void createFooter(ViewGroup v);
    method LoadLayoutBase (line 28) | public LoadLayoutBase(Context context) {
    method LoadLayoutBase (line 33) | public LoadLayoutBase(Context context, View v) {
    method pxTdp (line 38) | protected int pxTdp(int size) {
    method setLoadViewHeight (line 42) | @Override
    method setLoadText (line 49) | @Override
    method setLoadTextSize (line 56) | @Override
    method setLoadTextColor (line 62) | @Override
    method setLoadViewBackgroundResource (line 68) | @Override
    method setLoadViewBackgroundColor (line 73) | @Override
    method setProgressBarVisibility (line 78) | @Override
    method setIndeterminateDrawable (line 84) | @Override
    method setLoadCompletedText (line 90) | @Override
    method getFooterText (line 97) | public String getFooterText() {
    method getCompletedText (line 101) | public String getCompletedText() {

FILE: commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutConvert.java
  class LoadLayoutConvert (line 13) | public final class LoadLayoutConvert extends LoadLayoutBase {
    method LoadLayoutConvert (line 15) | public LoadLayoutConvert(Context context, View v) {
    method createFooter (line 19) | @Override

FILE: sample/src/androidTest/java/com/mylhyl/crlayout/sample/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/APP.java
  class APP (line 7) | public class APP extends Application {
    method onCreate (line 8) | @Override

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/MainActivity.java
  class MainActivity (line 16) | public class MainActivity extends AppCompatActivity implements TypesFrag...
    method onCreate (line 18) | @Override
    method onFragmentInteraction (line 28) | @Override

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/TypesFragment.java
  class TypesFragment (line 17) | public class TypesFragment extends Fragment implements AdapterView.OnIte...
    method TypesFragment (line 22) | public TypesFragment() {
    method newInstance (line 25) | public static TypesFragment newInstance() {
    method onCreateView (line 29) | @Override
    method onViewCreated (line 35) | @Override
    method onAttach (line 44) | @Override
    method onDetach (line 55) | @Override
    method onItemClick (line 61) | @Override
    method onButtonPressed (line 67) | public void onButtonPressed(Uri uri) {
    type OnFragmentInteractionListener (line 73) | public interface OnFragmentInteractionListener {
      method onFragmentInteraction (line 74) | void onFragmentInteraction(Uri uri);

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/AppExpandableListFragment.java
  class AppExpandableListFragment (line 27) | public class AppExpandableListFragment extends SwipeRefreshExpandableLis...
    method newInstance (line 34) | public static AppExpandableListFragment newInstance() {
    method onActivityCreated (line 38) | @Override
    method createSwipeRefreshLayout (line 56) | @Override
    method onListGroupClick (line 61) | @Override
    method onListChildClick (line 67) | @Override
    method onRefresh (line 75) | @Override
    method onListLoad (line 93) | @Override
    method onCreateOptionsMenu (line 114) | @Override
    method onOptionsItemSelected (line 119) | @Override
    class MyExpandableListAdapter (line 127) | class MyExpandableListAdapter extends BaseExpandableListAdapter {
      method MyExpandableListAdapter (line 130) | public MyExpandableListAdapter(Context context) {
      method getGroupCount (line 134) | @Override
      method getChildrenCount (line 139) | @Override
      method getGroup (line 144) | @Override
      method getChild (line 149) | @Override
      method getGroupId (line 154) | @Override
      method getChildId (line 159) | @Override
      method hasStableIds (line 164) | @Override
      method getGroupView (line 169) | @Override
      method getChildView (line 177) | @Override
      method isChildSelectable (line 187) | @Override

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/AppListFragment.java
  class AppListFragment (line 33) | public class AppListFragment extends SwipeRefreshListFragment {
    method newInstance (line 41) | public static AppListFragment newInstance() {
    method onActivityCreated (line 45) | @Override
    method onListItemClick (line 79) | @Override
    method onRefresh (line 85) | @Override
    method onListLoad (line 98) | @Override
    method executeAsync (line 113) | private void executeAsync(String url) {
    method onCreateOptionsMenu (line 141) | @Override
    method onOptionsItemSelected (line 146) | @Override
    method getImgSrcList (line 153) | private static List<String> getImgSrcList(String htmlStr) {

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/GridViewFragment.java
  class GridViewFragment (line 28) | public class GridViewFragment extends Fragment implements SwipeRefreshLa...
    method GridViewFragment (line 36) | public GridViewFragment() {
    method newInstance (line 39) | public static GridViewFragment newInstance() {
    method onCreateView (line 44) | @Override
    method onViewCreated (line 50) | @Override
    method onActivityCreated (line 61) | @Override
    method onRefresh (line 82) | @Override
    method onListLoad (line 95) | @Override
    method onCreateOptionsMenu (line 115) | @Override
    method onOptionsItemSelected (line 120) | @Override
    method onItemClick (line 127) | @Override

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/ListViewFragment.java
  class ListViewFragment (line 35) | public class ListViewFragment extends Fragment implements SwipeRefreshLa...
    method ListViewFragment (line 43) | public ListViewFragment() {
    method newInstance (line 46) | public static ListViewFragment newInstance() {
    method onCreateView (line 51) | @Override
    method onViewCreated (line 57) | @Override
    method onActivityCreated (line 65) | @Override
    method handleMessage (line 90) | @Override
    method initListViewHead (line 99) | private void initListViewHead() {
    method toRealPosition (line 166) | private int toRealPosition(int position) {
    method onDestroyView (line 174) | @Override
    method onRefresh (line 182) | @Override
    method onListLoad (line 195) | @Override
    method onCreateOptionsMenu (line 216) | @Override
    method onOptionsItemSelected (line 221) | @Override
    method onItemClick (line 228) | @Override

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/RecyclerViewFragment.java
  class RecyclerViewFragment (line 25) | public class RecyclerViewFragment extends Fragment implements SwipeRefre...
    method RecyclerViewFragment (line 33) | public RecyclerViewFragment() {
    method newInstance (line 36) | public static RecyclerViewFragment newInstance() {
    method onCreateView (line 41) | @Override
    method onViewCreated (line 47) | @Override
    method onActivityCreated (line 53) | @Override
    method onRefresh (line 71) | @Override
    method onListLoad (line 84) | @Override
    method onCreateOptionsMenu (line 104) | @Override
    method onOptionsItemSelected (line 109) | @Override
    class RecyclerViewAdapter (line 125) | class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.Vi...
      method getItemCount (line 127) | @Override
      method onCreateViewHolder (line 132) | @Override
      method onBindViewHolder (line 140) | @Override
      class MyViewHolder (line 145) | class MyViewHolder extends RecyclerView.ViewHolder {
        method MyViewHolder (line 148) | public MyViewHolder(View view) {

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/app/WebViewFragment.java
  class WebViewFragment (line 16) | public class WebViewFragment extends Fragment {
    method WebViewFragment (line 19) | public WebViewFragment() {
    method newInstance (line 22) | public static WebViewFragment newInstance() {
    method onCreateView (line 27) | @Override
    method onViewCreated (line 33) | @Override
    method onActivityCreated (line 39) | @Override
    class SampleWebViewClient (line 49) | private class SampleWebViewClient extends WebViewClient {
      method shouldOverrideUrlLoading (line 50) | @Override

FILE: sample/src/main/java/com/mylhyl/crlayout/sample/widget/MySwipeRefreshGridView.java
  class MySwipeRefreshGridView (line 12) | public class MySwipeRefreshGridView extends SwipeRefreshGridView {
    method MySwipeRefreshGridView (line 13) | public MySwipeRefreshGridView(Context context) {
    method MySwipeRefreshGridView (line 17) | public MySwipeRefreshGridView(Context context, AttributeSet attrs) {
    method getLoadLayoutResource (line 21) | @Override

FILE: sample/src/test/java/com/mylhyl/crlayout/sample/ExampleUnitTest.java
  class ExampleUnitTest (line 10) | public class ExampleUnitTest {
    method addition_isCorrect (line 11) | @Test
Condensed preview — 70 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (132K chars).
[
  {
    "path": ".gitignore",
    "chars": 103,
    "preview": "*.iml\n.gradle\n.idea\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": "README.md",
    "chars": 3463,
    "preview": "#### Android-CommonRefreshLayout\n基于`SwipeRefreshLayout`下拉刷新、上拉加载。支持的`AbsListView`、`RecycleView`、`WebView`\n\n####特点\n * 在布局"
  },
  {
    "path": "build.gradle",
    "chars": 566,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    r"
  },
  {
    "path": "commonrefreshlayout/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "commonrefreshlayout/build.gradle",
    "chars": 880,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'maven'\napply plugin: 'com.novoda.bintray-release'\n\nandroid {\n    comp"
  },
  {
    "path": "commonrefreshlayout/proguard-rules.pro",
    "chars": 661,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:"
  },
  {
    "path": "commonrefreshlayout/src/androidTest/java/com/mylhyl/crlayout/ApplicationTest.java",
    "chars": 350,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\""
  },
  {
    "path": "commonrefreshlayout/src/main/AndroidManifest.xml",
    "chars": 137,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.mylhyl.crlayout\">\n\n    <applicatio"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/BaseSwipeRefresh.java",
    "chars": 7736,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.conten"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/MultiSwipeRefreshLayout.java",
    "chars": 3951,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.support.annotation.ColorRes;\nimport android"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAbsListView.java",
    "chars": 4118,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.database.DataSetObserver;\nimport android.ut"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAdapterView.java",
    "chars": 10130,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.animation.Animator;\nimport android.animation.ValueAnimator;\nimport android."
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshExpandableListView.java",
    "chars": 2807,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.database.DataSetObserver;\nimport android.ut"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshGridView.java",
    "chars": 798,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.Gr"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshListView.java",
    "chars": 791,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.Li"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshRecyclerView.java",
    "chars": 7321,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.support.v7.widget.RecyclerView;\nimport andr"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshWebView.java",
    "chars": 1888,
    "preview": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.support.annotation.ColorRes;\nimport android"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/BaseSwipeRefreshFragment.java",
    "chars": 2169,
    "preview": "package com.mylhyl.crlayout.app;\n\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.s"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAbsListFragment.java",
    "chars": 1763,
    "preview": "package com.mylhyl.crlayout.app;\n\nimport android.view.View;\nimport android.widget.AbsListView;\nimport android.widget.Ada"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAdapterFragment.java",
    "chars": 1175,
    "preview": "package com.mylhyl.crlayout.app;\n\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\nimport com.mylhyl.crlayout.SwipeRe"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshExpandableListFragment.java",
    "chars": 2388,
    "preview": "package com.mylhyl.crlayout.app;\n\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.Exp"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshListFragment.java",
    "chars": 331,
    "preview": "package com.mylhyl.crlayout.app;\n\nimport com.mylhyl.crlayout.SwipeRefreshListView;\n\npublic abstract class SwipeRefreshLi"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ILoadSwipeRefresh.java",
    "chars": 1023,
    "preview": "package com.mylhyl.crlayout.internal;\n\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\n\n/**\n * Created by hupei on 2"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ISwipeRefresh.java",
    "chars": 1144,
    "preview": "package com.mylhyl.crlayout.internal;\n\nimport android.support.annotation.ColorRes;\nimport android.support.v4.widget.Swip"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadConfig.java",
    "chars": 1096,
    "preview": "package com.mylhyl.crlayout.internal;\n\nimport android.graphics.drawable.Drawable;\n\n/**\n * Created by hupei on 2016/5/19."
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayout.java",
    "chars": 1404,
    "preview": "package com.mylhyl.crlayout.internal;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.vie"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutBase.java",
    "chars": 2653,
    "preview": "package com.mylhyl.crlayout.internal;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutConvert.java",
    "chars": 907,
    "preview": "package com.mylhyl.crlayout.internal;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.view.Vie"
  },
  {
    "path": "commonrefreshlayout/src/main/res/values/attrs.xml",
    "chars": 617,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"crLayout\">\n        <!-- 自定义加载更多 res layo"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 233,
    "preview": "#Fri May 26 15:10:51 CST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 855,
    "preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
  },
  {
    "path": "gradlew",
    "chars": 4971,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2314,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "sample/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "sample/build.gradle",
    "chars": 967,
    "preview": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"23.0.3\"\n\n    defaultC"
  },
  {
    "path": "sample/proguard-rules.pro",
    "chars": 661,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:"
  },
  {
    "path": "sample/src/androidTest/java/com/mylhyl/crlayout/sample/ApplicationTest.java",
    "chars": 357,
    "preview": "package com.mylhyl.crlayout.sample;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a"
  },
  {
    "path": "sample/src/main/AndroidManifest.xml",
    "chars": 787,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/APP.java",
    "chars": 389,
    "preview": "package com.mylhyl.crlayout.sample;\n\nimport android.app.Application;\n\nimport com.bumptech.glide.request.target.ViewTarge"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/MainActivity.java",
    "chars": 2085,
    "preview": "package com.mylhyl.crlayout.sample;\n\nimport android.content.ContentUris;\nimport android.net.Uri;\nimport android.os.Bundl"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/TypesFragment.java",
    "chars": 2391,
    "preview": "package com.mylhyl.crlayout.sample;\n\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android."
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/AppExpandableListFragment.java",
    "chars": 6350,
    "preview": "package com.mylhyl.crlayout.sample.app;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.o"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/AppListFragment.java",
    "chars": 5658,
    "preview": "package com.mylhyl.crlayout.sample.app;\n\nimport android.os.Bundle;\nimport android.view.Menu;\nimport android.view.MenuInf"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/GridViewFragment.java",
    "chars": 4493,
    "preview": "package com.mylhyl.crlayout.sample.app;\n\nimport android.graphics.Color;\nimport android.os.Bundle;\nimport android.support"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/ListViewFragment.java",
    "chars": 8062,
    "preview": "package com.mylhyl.crlayout.sample.app;\n\nimport android.graphics.Color;\nimport android.os.Bundle;\nimport android.os.Hand"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/RecyclerViewFragment.java",
    "chars": 5125,
    "preview": "package com.mylhyl.crlayout.sample.app;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport an"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/WebViewFragment.java",
    "chars": 1866,
    "preview": "package com.mylhyl.crlayout.sample.app;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport an"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/widget/MySwipeRefreshGridView.java",
    "chars": 614,
    "preview": "package com.mylhyl.crlayout.sample.widget;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\n\nimport co"
  },
  {
    "path": "sample/src/main/res/drawable/footer_progressbar.xml",
    "chars": 647,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<animated-rotate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    a"
  },
  {
    "path": "sample/src/main/res/drawable/selector_list.xml",
    "chars": 294,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item a"
  },
  {
    "path": "sample/src/main/res/layout/fragment_grid_view.xml",
    "chars": 488,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.sample.widget.MySwipeRefreshGridView xmlns:android=\"http://s"
  },
  {
    "path": "sample/src/main/res/layout/fragment_list_view.xml",
    "chars": 632,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.SwipeRefreshListView xmlns:android=\"http://schemas.android.c"
  },
  {
    "path": "sample/src/main/res/layout/fragment_recycler_view.xml",
    "chars": 781,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.SwipeRefreshRecyclerView xmlns:android=\"http://schemas.andro"
  },
  {
    "path": "sample/src/main/res/layout/fragment_recycler_view_item.xml",
    "chars": 759,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v7.widget.CardView xmlns:android=\"http://schemas.android.com/apk"
  },
  {
    "path": "sample/src/main/res/layout/fragment_types.xml",
    "chars": 335,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ListView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:to"
  },
  {
    "path": "sample/src/main/res/layout/fragment_web_view.xml",
    "chars": 350,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.SwipeRefreshWebView xmlns:android=\"http://schemas.android.co"
  },
  {
    "path": "sample/src/main/res/layout/image_item.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ImageView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "sample/src/main/res/layout/swipe_refresh_footer.xml",
    "chars": 850,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "sample/src/main/res/menu/menu.xml",
    "chars": 334,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n     "
  },
  {
    "path": "sample/src/main/res/values/array.xml",
    "chars": 322,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string-array name=\"types\">\n        <item>ListView</item>\n       "
  },
  {
    "path": "sample/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"color"
  },
  {
    "path": "sample/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "chars": 211,
    "preview": "<resources>\n    <string name=\"app_name\">CommonRefreshLayout</string>\n\n    <!-- TODO: Remove or change this placeholder t"
  },
  {
    "path": "sample/src/main/res/values/styles.xml",
    "chars": 383,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "sample/src/main/res/values-w820dp/dimens.xml",
    "chars": 358,
    "preview": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as s"
  },
  {
    "path": "sample/src/test/java/com/mylhyl/crlayout/sample/ExampleUnitTest.java",
    "chars": 319,
    "preview": "package com.mylhyl.crlayout.sample;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit t"
  },
  {
    "path": "settings.gradle",
    "chars": 42,
    "preview": "include ':sample', ':commonrefreshlayout'\n"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the mylhyl/Android-CommonRefreshLayout GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 70 files (115.5 KB), approximately 29.8k tokens, and a symbol index with 324 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!