[
  {
    "path": ".gitignore",
    "content": "*.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",
    "content": "#### Android-CommonRefreshLayout\n基于`SwipeRefreshLayout`下拉刷新、上拉加载。支持的`AbsListView`、`RecycleView`、`WebView`\n\n####特点\n * 在布局`layout`中使用，支持`xml`属性\n * 支持自动下拉刷新，什么用呢？比如进入界面时，只需要调用`autoRefresh()`方法即可，显示上拉动画同时刷新回调`onRefresh`将会被调用\n * 上拉加载支持自定义`View`或设置加载文字、动画、加载完成\n * 轻松设置`Adapter`空数据视图，默认为`TextView`支持更文字，也可自定义`View`\n * 对于简单的界面，例如只有`ListView`可以继承 [SwipeRefreshListFragment](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshListFragment.java)\n   轻松搞定\n\n####效果图\n<img src=\"preview/gif.gif\" width=\"240px\"/>\n\n####使用\n  仔细看`listSelector`属性，我们是支持的，效果见`sample`\n```xml\n    <com.mylhyl.crlayout.SwipeRefreshListView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:crl=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:id=\"@+id/swipeRefresh\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:listSelector=\"@drawable/selector_list\"\n        crl:load_text=\"数据正在加载中\"\n        crl:load_indeterminate_drawable=\"@drawable/footer_progressbar\"\n        tools:context=\".app.ListViewFragment\" />\n```\n 设置上拉加载，更多方法见 [LoadConfig](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadConfig.java)\n```java\n        LoadConfig loadConfig = swipeRefreshListView.getLoadConfig();\n        loadConfig.setLoadText(\"set自定义加载\");\n        loadConfig.setIndeterminateDrawable(getResources().getDrawable(R.drawable.footer_progressbar));\n```\n或 xml属性配置，更多属生见[attrs](commonrefreshlayout/src/main/res/values/attrs.xml)\n```xml\n            crl:load_text=\"数据正在加载中\"\n            crl:load_indeterminate_drawable=\"@drawable/footer_progressbar\"\n```\n\n 自定义上拉加载\n \n * 方式一：代码配置\n \n```java\n        getSwipeRefreshLayout().setLoadLayoutResource(R.layout.swipe_refresh_footer);\n```\n * 方式二：xml属性配置\n \n```xml\n        crl:load_layout=\"@layout/swipe_refresh_footer\"\n```\n * 方式三：继承重写`getLoadLayoutResource()`方法\n \n```java\n        public class MySwipeRefreshGridView extends SwipeRefreshGridView {\n        \n            @Override\n            protected int getLoadLayoutResource() {\n                return R.layout.swipe_refresh_footer;\n            }\n        }\n```\n设置adapter空数据视图文字\n```java\n        swipeRefreshListView.setEmptyText(\"数据呢？\");\n```\n 自定义adapter空数据视图\n```java\n        ImageView emptyView = new ImageView(getContext());\n        emptyView.setImageResource(R.mipmap.empty);\n        swipeRefreshGridView.setEmptyView(emptyView);\n```\n注册`ListView`长按事件怎么办？好说好说提供了方法`getScrollView()`，既然能获取`ListView`那`SwipeRefreshLayout`是不是也可以获取到呢？答案是肯定的，方法`getSwipeRefreshLayout`，你可以随心所欲设置下拉圆圈的颜色、大小等。\n关于更多公开方法见 [ISwipeRefresh](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ISwipeRefresh.java)、[ILoadSwipeRefresh](commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ILoadSwipeRefresh.java)\n\n#### 注意事项\n`setLoadAnimator`、`setLoadLayoutResource`方法须在`setOnListLoadListener`之前调用 \n\n#### 使用Gradle构建时添加一下依赖即可:\n```javascript\ncompile 'com.mylhyl:commonrefreshlayout:2.4'\n```\n#### 如果使用eclipse\n只能`clone`源码，然后在 eclipse 中用`library`方式引用\n     \n#### [下载APK体验](preview/sample-debug.apk)\n\n#### 更新日志\n> 2.4 修复第二次setAdapter崩溃的问题，修改已知BUG\n\n> 2.1 修复空数据视图不显示\n\n> 2.0 UI编辑支持预览\n\n> 1.9 优化代码\n\n> 1.8 优化加载更多显示效果\n\n> 1.7 新增`setEnabled`禁用下拉刷新\n\n> 1.6 新增加载完成，命名`footer`修改为`load`\n\n> 1.5 优化`SwipeRefreshWebView`的`autoRefresh`方法\n\n> 1.4 优化`SwipeRefreshWebView`显示下拉动画\n\n> 1.3 增加`autoRefresh(@ColorRes int... colorResIds)`方法，指定动画颜色\n\n> 1.2 修复滑动到底部会上拉加载多次\n\n> 1.1 修改为`recyclerview-v7:23.4.0`\n\n> 1.0 初始版本\n"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.2.3'\n        classpath 'com.novoda:bintray-release:0.3.4'\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n    tasks.withType(Javadoc) {\n        options {\n            encoding \"UTF-8\"\n            charSet 'UTF-8'\n            links \"http://docs.oracle.com/javase/7/docs/api\"\n            failOnError false\n        }\n    }\n}"
  },
  {
    "path": "commonrefreshlayout/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "commonrefreshlayout/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'maven'\napply plugin: 'com.novoda.bintray-release'\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"23.0.3\"\n\n    defaultConfig {\n        minSdkVersion 15\n        targetSdkVersion 23\n        versionCode 1\n        versionName \"2017.5.26\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    lintOptions {\n        abortOnError false\n        checkReleaseBuilds false\n    }\n}\n\ndependencies {\n    compile 'com.android.support:recyclerview-v7:23.4.0'\n}\n\npublish {\n    userOrg = 'mylhyl'\n    groupId = 'com.mylhyl'\n    artifactId = 'commonrefreshlayout'\n    version = '2.4'\n    description = 'android pull refresh layout'\n    website = \"https://github.com/mylhyl/Android-CommonRefreshLayout\"\n}"
  },
  {
    "path": "commonrefreshlayout/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:\\android\\android-sdk-windows/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "commonrefreshlayout/src/androidTest/java/com/mylhyl/crlayout/ApplicationTest.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "commonrefreshlayout/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.mylhyl.crlayout\">\n\n    <application />\n</manifest>\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/BaseSwipeRefresh.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.os.Build;\nimport android.support.annotation.ColorRes;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewParent;\nimport android.widget.FrameLayout;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\n\nimport com.mylhyl.crlayout.internal.ISwipeRefresh;\n\n/**\n * android v4 兼容包 中 SwipeRefreshLayout 刷新控件，支持上拉加载\n * <p/>\n * <pre>\n * 此处主要封装以下几点：\n * 1.手动刷新 {@link #autoRefresh() autoRefresh}\n * 2.支持上拉加载，并可自定义\n * 3.解决 SwipeRefreshLayout 与可滑动控件使用过程中冲突的问题\n * </pre>\n * Created by hupei on 2016/5/12.\n */\npublic abstract class BaseSwipeRefresh<T extends View> extends FrameLayout implements ISwipeRefresh {\n\n    /**\n     * 创建可滑动 View，子类实现\n     *\n     * @param context\n     * @param attrs\n     * @return\n     */\n    protected abstract T createScrollView(Context context, AttributeSet attrs);\n\n    private FrameLayout mRefreshLayoutWrapper;\n    protected MultiSwipeRefreshLayout mLoadSwipeRefresh;\n    private T mScrollView;\n    private View mEmptyView;\n    private String mEmptyViewText = \"\";\n    private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener;\n\n    protected boolean isLoadCompleted;\n\n    public BaseSwipeRefresh(Context context) {\n        this(context, null);\n    }\n\n    public BaseSwipeRefresh(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public BaseSwipeRefresh(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        if (!isInEditMode())\n            init(context, attrs, defStyleAttr, 0);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public BaseSwipeRefresh(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        if (!isInEditMode())\n            init(context, attrs, defStyleAttr, defStyleRes);\n    }\n\n    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        int[] crLayout = R.styleable.crLayout;\n        if (crLayout != null && crLayout.length > 0) {\n            final TypedArray a = context.obtainStyledAttributes(attrs, crLayout, defStyleAttr, defStyleRes);\n            if (a != null) {\n                mEmptyViewText = a.getString(R.styleable.crLayout_empty_text);\n                a.recycle();\n            }\n        }\n        mLoadSwipeRefresh = new MultiSwipeRefreshLayout(context, attrs);\n        mScrollView = createScrollView(context, attrs);\n        mEmptyView = createEmptyView(context);\n        addSwipeRefreshView(context, mLoadSwipeRefresh, mScrollView, mEmptyView);\n    }\n\n    @SuppressWarnings(\"ResourceType\")\n    private View createEmptyView(Context context) {\n        TextView emptyView = new TextView(context);\n        emptyView.setId(android.R.id.empty);\n        emptyView.setTextAppearance(context, android.R.attr.textAppearanceSmall);\n        emptyView.setGravity(Gravity.CENTER);\n        emptyView.setVisibility(View.GONE);\n        emptyView.setText(mEmptyViewText);\n        return emptyView;\n    }\n\n    private void addSwipeRefreshView(Context context, MultiSwipeRefreshLayout loadSwipeRefresh, T scrollView, View emptyView) {\n        mRefreshLayoutWrapper = new FrameLayout(context);\n        mRefreshLayoutWrapper.addView(scrollView,\n                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));\n        mRefreshLayoutWrapper.addView(emptyView,\n                new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));\n\n        loadSwipeRefresh.addView(mRefreshLayoutWrapper, new LayoutParams(LayoutParams.MATCH_PARENT,\n                LayoutParams.MATCH_PARENT));\n\n        addView(loadSwipeRefresh, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1));\n        loadSwipeRefresh.setSwipeableChildren(scrollView, emptyView);\n    }\n\n    @Override\n    public void autoRefresh() {\n        mLoadSwipeRefresh.showProgressView();\n        this.setRefreshing(true);\n    }\n\n    @Override\n    public void autoRefresh(@ColorRes int... colorResIds) {\n        mLoadSwipeRefresh.showProgressView(colorResIds);\n        this.setRefreshing(true);\n    }\n\n    @Override\n    public final void autoRefresh(boolean scale, int start, int end, @ColorRes int... colorResIds) {\n        mLoadSwipeRefresh.showProgressView(scale, start, end, colorResIds);\n        this.setRefreshing(true);\n    }\n\n    @Override\n    public final void setEmptyText(int resId) {\n        setEmptyText(getContext().getString(resId));\n    }\n\n    @Override\n    public final void setEmptyText(CharSequence text) {\n        if (mEmptyView != null && mEmptyView instanceof TextView) {\n            TextView textView = (TextView) mEmptyView;\n            textView.setText(text);\n        }\n    }\n\n    @Override\n    public final void setEmptyView(View newEmptyView) {\n        if (null != newEmptyView) {\n            if (mEmptyView != null && mRefreshLayoutWrapper != null) {\n                mRefreshLayoutWrapper.removeView(mEmptyView);\n            }\n            newEmptyView.setVisibility(GONE);\n            mEmptyView = newEmptyView;\n            newEmptyView.setClickable(true);\n\n            ViewParent newEmptyViewParent = newEmptyView.getParent();\n            if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {\n                ((ViewGroup) newEmptyViewParent).removeView(newEmptyView);\n            }\n            FrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams());\n            if (null != lp) {\n                mRefreshLayoutWrapper.addView(newEmptyView, lp);\n            } else {\n                mRefreshLayoutWrapper.addView(newEmptyView);\n            }\n        }\n    }\n\n    private static FrameLayout.LayoutParams convertEmptyViewLayoutParams(ViewGroup.LayoutParams lp) {\n        FrameLayout.LayoutParams newLp = null;\n        if (null != lp) {\n            newLp = new FrameLayout.LayoutParams(lp);\n            if (lp instanceof LinearLayout.LayoutParams)\n                newLp.gravity = ((LinearLayout.LayoutParams) lp).gravity;\n            else newLp.gravity = Gravity.CENTER;\n        }\n        return newLp;\n    }\n\n    @Override\n    public final View getEmptyView() {\n        return mEmptyView;\n    }\n\n    final void updateEmptyViewShown(boolean shown) {\n        /*\n         * ListView不能设置隐藏，否则下拉刷新动画无法跟随手势，因为 SwipeRefreshLayout 必须有滚动的view。\n\t\t * mListView.setVisibility(!shown ? View.VISIBLE : View.GONE);\n\t\t */\n        if (mEmptyView != null)\n            mEmptyView.setVisibility(shown ? View.VISIBLE : View.GONE);\n    }\n\n    @Override\n    public final void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener) {\n        mOnRefreshListener = listener;\n        mLoadSwipeRefresh.setOnRefreshListener(listener);\n    }\n\n    @Override\n    public final void setRefreshing(boolean refreshing) {\n        isLoadCompleted = false;\n        mLoadSwipeRefresh.setRefreshing(refreshing);\n        // 下拉刷新中，此处目的是为了手动调用 setRefreshing(true)时，响应下拉刷新事件\n        if (mLoadSwipeRefresh.isRefreshing() && mOnRefreshListener != null)\n            mOnRefreshListener.onRefresh();\n    }\n\n    @Override\n    public void setEnabled(boolean enabled) {\n        getSwipeRefreshLayout().setEnabled(enabled);\n    }\n\n    @Override\n    public final T getScrollView() {\n        return mScrollView;\n    }\n\n    @Override\n    public final SwipeRefreshLayout getSwipeRefreshLayout() {\n        return mLoadSwipeRefresh;\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/MultiSwipeRefreshLayout.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.support.annotation.ColorRes;\nimport android.support.v4.view.ViewCompat;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.util.AttributeSet;\nimport android.util.DisplayMetrics;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.ViewConfiguration;\nimport android.widget.AbsListView;\n\npublic final class MultiSwipeRefreshLayout extends SwipeRefreshLayout {\n    // Default offset in dips from the top of the view to where the progress spinner should stop\n    private static final int DEFAULT_CIRCLE_TARGET = 64;\n    private float mSpinnerFinalOffset;\n    private static final int[] DEFAULT_COLOR_RES = new int[]{android.R.color.holo_blue_light, android.R.color.holo_red_light,\n            android.R.color.holo_orange_light, android.R.color.holo_green_light};\n\n    private int mTouchSlop;\n    private float mPrevX;// 上一次触摸时的X坐标\n    private View[] mSwipeableChildren;\n    private int[] mColorResIds;\n\n    public MultiSwipeRefreshLayout(Context context) {\n        this(context, null);\n    }\n\n    public MultiSwipeRefreshLayout(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        final DisplayMetrics metrics = getResources().getDisplayMetrics();\n        mSpinnerFinalOffset = DEFAULT_CIRCLE_TARGET * metrics.density;\n        // 触发移动事件的最短距离，如果小于这个距离就不触发移动控件\n        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();\n    }\n\n    public final void showProgressView() {\n        if (mColorResIds == null)\n            mColorResIds = DEFAULT_COLOR_RES;\n        showProgressView(mColorResIds);\n    }\n\n    public final void showProgressView(@ColorRes int... colorResIds) {\n        showProgressView(false, 0, (int) mSpinnerFinalOffset, colorResIds);\n    }\n\n    public final void showProgressView(boolean scale, int start, int end, @ColorRes int... colorResIds) {\n        this.mColorResIds = colorResIds;\n        setColorSchemeResources(colorResIds);\n        // 显示下拉动画，关键在于源码中的 mUsingCustomStart = true\n        //有二种方法显示动画，我的文章：http://blog.csdn.net/hupei/article/details/51953370\n        setProgressViewOffset(scale, start, end);\n    }\n\n    @Override\n    public boolean onInterceptTouchEvent(MotionEvent event) {\n        switch (event.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mPrevX = event.getX();\n                break;\n            case MotionEvent.ACTION_MOVE:\n                final float eventX = event.getX();\n                float xDiff = Math.abs(eventX - mPrevX);\n                // 增加容差，让下拉刷新在竖直滑动时就可以触发\n                if (xDiff > mTouchSlop + DEFAULT_CIRCLE_TARGET) {\n                    return false;\n                }\n        }\n        return super.onInterceptTouchEvent(event);\n    }\n\n    final void setSwipeableChildren(final View... views) {\n        assert views != null;\n        mSwipeableChildren = views;\n    }\n\n\n    @Override\n    public boolean canChildScrollUp() {\n        if (mSwipeableChildren != null && mSwipeableChildren.length > 0) {\n            for (View view : mSwipeableChildren) {\n                if (view != null && view.isShown() && !canViewScrollUp(view)) {\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    private static boolean canViewScrollUp(View target) {\n        if (android.os.Build.VERSION.SDK_INT < 14) {\n            if (target instanceof AbsListView) {\n                final AbsListView absListView = (AbsListView) target;\n                return absListView.getChildCount() > 0\n                        && (absListView.getFirstVisiblePosition() > 0\n                        || absListView.getChildAt(0).getTop() < absListView.getPaddingTop());\n            } else {\n                return ViewCompat.canScrollVertically(target, -1) || target.getScrollY() > 0;\n            }\n        } else {\n            return ViewCompat.canScrollVertically(target, -1);\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAbsListView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.database.DataSetObserver;\nimport android.util.AttributeSet;\nimport android.widget.AbsListView;\nimport android.widget.AdapterView;\nimport android.widget.ListAdapter;\n\nimport com.mylhyl.crlayout.internal.ILoadSwipeRefresh;\n\n/**\n * SwipeRefreshLayout 加 AbsListView 布局<br>\n * 子类必须实现 {@linkplain BaseSwipeRefresh#createScrollView(Context, AttributeSet)}  createScrollView}方法\n * <p> Created by hupei on 2016/5/12.\n */\npublic abstract class SwipeRefreshAbsListView<T extends AbsListView> extends\n        SwipeRefreshAdapterView<T> {\n    private ListAdapter mEmptyDataSetAdapter;\n    private EmptyDataSetObserver mDataSetObserver;\n\n    public SwipeRefreshAbsListView(Context context) {\n        super(context);\n    }\n\n    public SwipeRefreshAbsListView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public final void setOnItemClickListener(AdapterView.OnItemClickListener listener) {\n        getScrollView().setOnItemClickListener(listener);\n    }\n\n    /**\n     * 为 AbsListView 设置适配器\n     *\n     * @param adapter\n     */\n    public final void setAdapter(ListAdapter adapter) {\n        if (adapter == null)\n            throw new NullPointerException(\"mAdapter is null please call SwipeRefreshAbsListView\" +\n                    \".setAdapter\");\n        getScrollView().setOnScrollListener(new OnScrollAbsListListener(this));\n        getScrollView().setAdapter(adapter);\n        registerDataSetObserver(adapter);\n    }\n\n    final void registerDataSetObserver(ListAdapter adapter) {\n        if (mEmptyDataSetAdapter != null && mDataSetObserver != null)\n            mEmptyDataSetAdapter.unregisterDataSetObserver(mDataSetObserver);\n\n        mEmptyDataSetAdapter = adapter;\n        if (mEmptyDataSetAdapter != null) {\n            mDataSetObserver = new EmptyDataSetObserver();\n            mEmptyDataSetAdapter.registerDataSetObserver(mDataSetObserver);\n            mDataSetObserver.onChanged();\n        }\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        if (mEmptyDataSetAdapter != null && mDataSetObserver != null) {\n            mEmptyDataSetAdapter.unregisterDataSetObserver(mDataSetObserver);\n            mDataSetObserver = null;\n        }\n    }\n\n    public static class OnScrollAbsListListener implements AbsListView.OnScrollListener {\n        private ILoadSwipeRefresh mILoadSwipeRefresh;\n        private AbsListView.OnScrollListener mOnScrollListener;\n\n        public OnScrollAbsListListener(ILoadSwipeRefresh loadSwipeRefresh) {\n            mILoadSwipeRefresh = loadSwipeRefresh;\n        }\n\n        public OnScrollAbsListListener(ILoadSwipeRefresh loadSwipeRefresh, AbsListView\n                .OnScrollListener onScrollListener) {\n            mILoadSwipeRefresh = loadSwipeRefresh;\n            mOnScrollListener = onScrollListener;\n        }\n\n        @Override\n        public void onScrollStateChanged(AbsListView view, int scrollState) {\n            // 只有在闲置状态情况下检查\n            if (scrollState == SCROLL_STATE_IDLE) {\n                // 如果满足允许上拉加载、非加载状态中、最后一个显示的 item 与数据源的大小一样，则表示滑动入底部\n                if (mILoadSwipeRefresh.isEnabledLoad() && !mILoadSwipeRefresh.isLoading()\n                        && view.getLastVisiblePosition() == (view.getCount() - 1)) {\n                    mILoadSwipeRefresh.loadData();// 执行上拉加载数据\n                }\n            }\n            if (null != mOnScrollListener)\n                mOnScrollListener.onScrollStateChanged(view, scrollState);\n        }\n\n        @Override\n        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int\n                totalItemCount) {\n            if (null != mOnScrollListener)\n                mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,\n                        totalItemCount);\n        }\n    }\n\n    private class EmptyDataSetObserver extends DataSetObserver {\n        @Override\n        public void onChanged() {\n            updateEmptyViewShown(mEmptyDataSetAdapter == null || mEmptyDataSetAdapter.isEmpty());\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshAdapterView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.animation.Animator;\nimport android.animation.ValueAnimator;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build;\nimport android.text.TextUtils;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.View;\n\nimport com.mylhyl.crlayout.internal.ILoadSwipeRefresh;\nimport com.mylhyl.crlayout.internal.LoadConfig;\nimport com.mylhyl.crlayout.internal.LoadLayout;\nimport com.mylhyl.crlayout.internal.LoadLayoutBase;\nimport com.mylhyl.crlayout.internal.LoadLayoutConvert;\n\npublic abstract class SwipeRefreshAdapterView<T extends View> extends BaseSwipeRefresh<T>\n        implements ILoadSwipeRefresh {\n\n    private static final String DEFAULT_FOOTER_TEXT = \"加载数据中...\";\n    private static final String DEFAULT_FOOTER_COMPLETED_TEXT = \"没有更多了\";\n    private static final int mLoadAnimatorDuration = 300;\n\n    private boolean mLoading;// 是否处于上拉加载状态中\n    private boolean mEnabledLoad;// 是否允许上拉加载\n    private LoadLayoutBase mLoadLayout;\n    private int mLoadResource;\n    private String mLoadText;\n    private String mCompletedText;\n    private Drawable mLoadIndeterminateDrawable;\n\n    private OnListLoadListener mOnListLoadListener;\n\n    private ValueAnimator mShowLoadAnimator;\n    private ValueAnimator mHideLoadAnimator;\n    private int mLoadLayoutHeight;\n    private boolean isLoadAnimator;\n\n    public SwipeRefreshAdapterView(Context context) {\n        this(context, null);\n    }\n\n    public SwipeRefreshAdapterView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public SwipeRefreshAdapterView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs, defStyleAttr, 0);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public SwipeRefreshAdapterView(Context context, AttributeSet attrs, int defStyleAttr, int\n            defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        init(context, attrs, defStyleAttr, defStyleRes);\n    }\n\n    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        int[] crLayout = R.styleable.crLayout;\n        if (crLayout != null && crLayout.length > 0) {\n            final TypedArray a = context.obtainStyledAttributes(attrs, crLayout, defStyleAttr,\n                    defStyleRes);\n            if (a != null) {\n                mLoadResource = a.getResourceId(R.styleable.crLayout_load_layout, 0);\n                mLoadText = a.getString(R.styleable.crLayout_load_text);\n                mLoadIndeterminateDrawable = a.getDrawable(R.styleable\n                        .crLayout_load_indeterminate_drawable);\n                mCompletedText = a.getString(R.styleable.crLayout_load_completed_text);\n                isLoadAnimator = a.getBoolean(R.styleable.crLayout_load_animator, false);\n                a.recycle();\n            }\n        }\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        if (isLoadAnimator && mLoadLayout != null && mLoadLayoutHeight == 0) {\n            mLoadLayoutHeight = mLoadLayout.getMeasuredHeight();\n            if (mLoadLayoutHeight > 0) {\n                mLoadLayout.setVisibility(GONE);\n                initShowLoadAnimator();\n                initHideLoadAnimator();\n            }\n        }\n    }\n\n    private void initShowLoadAnimator() {\n        mShowLoadAnimator = ValueAnimator.ofFloat(0, mLoadLayoutHeight);\n        mShowLoadAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                LayoutParams lp = (LayoutParams) mLoadLayout.getLayoutParams();\n                lp.height = (int) ((Float) animation.getAnimatedValue()).floatValue();\n                mLoadLayout.setLayoutParams(lp);\n                getScrollView().setTranslationY(-lp.height);\n            }\n        });\n        mShowLoadAnimator.addListener(new SimpleAnimatorListener() {\n            @Override\n            public void onAnimationEnd(Animator animation) {\n                if (mOnListLoadListener != null && !isLoadCompleted) {\n                    mOnListLoadListener.onListLoad();\n                }\n            }\n        });\n        mShowLoadAnimator.setDuration(mLoadAnimatorDuration);\n    }\n\n    private void initHideLoadAnimator() {\n        mHideLoadAnimator = ValueAnimator.ofFloat(mLoadLayoutHeight, 0);\n        mHideLoadAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                LayoutParams lp = (LayoutParams) mLoadLayout.getLayoutParams();\n                lp.height = (int) ((Float) animation.getAnimatedValue()).floatValue();\n                mLoadLayout.setLayoutParams(lp);\n                getScrollView().setTranslationY(-lp.height);\n            }\n        });\n        mHideLoadAnimator.setDuration(mLoadAnimatorDuration);\n    }\n\n    @Override\n    public final void setOnListLoadListener(OnListLoadListener onListLoadListener) {\n        this.mOnListLoadListener = onListLoadListener;\n        setEnabledLoad(mOnListLoadListener != null);\n        if (mEnabledLoad) addLoadLayout();\n    }\n\n    private void addLoadLayout() {\n        if (mLoadLayout == null) {\n            createLoadLayout();//创建上拉加载 View\n            LayoutParams layoutParams = new LayoutParams(mLoadLayout.getLayoutParams());\n            layoutParams.gravity = Gravity.BOTTOM;\n            //永远处于第二节点，防止 mLoadLayout 遮挡其它控件\n            addView(mLoadLayout, 1, layoutParams);\n        }\n    }\n\n    private void createLoadLayout() {\n        if ((mLoadResource = getLoadLayoutResource()) > 0) {\n            View view = LayoutInflater.from(getContext()).inflate(mLoadResource, this, false);\n            mLoadLayout = new LoadLayoutConvert(getContext(), view);\n        } else {\n            LoadLayout footerLayout = new LoadLayout(getContext());\n            mLoadLayout = footerLayout;\n        }\n        if (mLoadLayout == null)\n            throw new NullPointerException(\"mLoadLayout is null\");\n\n        if (!isLoadAnimator) mLoadLayout.setVisibility(GONE);\n\n        if (TextUtils.isEmpty(mCompletedText))\n            mCompletedText = DEFAULT_FOOTER_COMPLETED_TEXT;\n        mLoadLayout.setLoadCompletedText(mCompletedText);\n\n        if (TextUtils.isEmpty(mLoadText))\n            mLoadText = DEFAULT_FOOTER_TEXT;\n        mLoadLayout.setLoadText(mLoadText);\n\n        if (mLoadIndeterminateDrawable != null)\n            mLoadLayout.setIndeterminateDrawable(mLoadIndeterminateDrawable);\n    }\n\n    @Override\n    public final void setLoadLayoutResource(int resource) {\n        mLoadResource = resource;\n        if (mLoadLayout != null)\n            throw new RuntimeException(\"please call setLoadLayoutResource before \" +\n                    \"setOnListLoadListener\");\n    }\n\n    /**\n     * 获取自定义上拉加载 layoutResource，子类可重写\n     *\n     * @return\n     */\n    protected int getLoadLayoutResource() {\n        return mLoadResource;\n    }\n\n\n    @Override\n    public final void loadData() {\n        setLoading(true);\n    }\n\n    @Override\n    public final void setLoading(boolean loading) {\n        if (mLoading == loading) return;\n        this.mLoading = loading;\n        if (mLoading) showLoadLayout();\n        else hideLoadLayout();\n    }\n\n    private void showLoadLayout() {\n        if (mLoadLayout != null) {\n            LoadConfig footerLayout = getLoadConfig();\n            if (isLoadCompleted) {\n                footerLayout.setLoadCompletedText(mLoadLayout.getCompletedText());\n                footerLayout.setProgressBarVisibility(View.GONE);\n                mLoadLayout.postDelayed(new Runnable() {\n                    @Override\n                    public void run() {\n                        setLoading(false);\n                    }\n                }, 1000);\n            } else {\n                footerLayout.setLoadText(mLoadLayout.getFooterText());\n                footerLayout.setProgressBarVisibility(View.VISIBLE);\n            }\n            mLoadLayout.setVisibility(View.VISIBLE);\n\n            if (isLoadAnimator && mShowLoadAnimator != null) mShowLoadAnimator.start();\n            else if (!isLoadAnimator && !isLoadCompleted && mOnListLoadListener != null)\n                mOnListLoadListener.onListLoad();\n        }\n    }\n\n    private void hideLoadLayout() {\n        if (isLoadAnimator && mHideLoadAnimator != null) mHideLoadAnimator.start();\n        else mLoadLayout.setVisibility(GONE);\n    }\n\n    @Override\n    public final void setEnabledLoad(boolean enabled) {\n        mEnabledLoad = enabled;\n    }\n\n    @Override\n    public final boolean isLoading() {\n        return mLoading;\n    }\n\n    @Override\n    public final boolean isEnabledLoad() {\n        return mEnabledLoad;\n    }\n\n    @Override\n    public void setLoadCompleted(boolean loadCompleted) {\n        isLoadCompleted = loadCompleted;\n    }\n\n    @Override\n    public LoadConfig getLoadConfig() {\n        if (mLoadLayout == null) addLoadLayout();\n        return mLoadLayout;\n    }\n\n    @Override\n    public void setLoadAnimator(boolean loadAnimator) {\n        isLoadAnimator = loadAnimator;\n        if (mLoadLayout != null)\n            throw new RuntimeException(\"please call setLoadAnimator before setOnListLoadListener\");\n    }\n\n    public interface OnListLoadListener {\n        /**\n         * 当上拉加载时，此方法将被调用\n         */\n        void onListLoad();\n    }\n\n    static class SimpleAnimatorListener implements Animator.AnimatorListener {\n        @Override\n        public void onAnimationStart(Animator animation) {\n\n        }\n\n        @Override\n        public void onAnimationEnd(Animator animation) {\n\n        }\n\n        @Override\n        public void onAnimationCancel(Animator animation) {\n\n        }\n\n        @Override\n        public void onAnimationRepeat(Animator animation) {\n\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshExpandableListView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.database.DataSetObserver;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ExpandableListAdapter;\nimport android.widget.ExpandableListView;\n\n/**\n * SwipeRefreshLayout 包含 ExpandableListView 布局<br>\n * 如须自定义加载框，可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}\n * <p>Created by hupei on 2016/5/16.\n */\npublic class SwipeRefreshExpandableListView extends SwipeRefreshAbsListView<ExpandableListView> {\n    private ExpandableListAdapter mAdapter;\n\n    public SwipeRefreshExpandableListView(Context context) {\n        super(context);\n    }\n\n    public SwipeRefreshExpandableListView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    /**\n     * 为 ExpandableListView 设置适配器\n     *\n     * @param adapter\n     */\n    public final void setAdapter(ExpandableListAdapter adapter) {\n        mAdapter = adapter;\n        if (mAdapter == null)\n            throw new NullPointerException(\"mAdapter is null please call SwipeRefreshExpandableListView.setAdapter\");\n        getScrollView().setOnScrollListener(new OnScrollAbsListListener(this));\n        getScrollView().setAdapter(mAdapter);\n        registerDataSetObserver(new ExpandableListConnector(mAdapter));\n    }\n\n    @Override\n    protected ExpandableListView createScrollView(Context context, AttributeSet attrs) {\n        ExpandableListView expandableListView = new ExpandableListView(context, attrs);\n        expandableListView.setId(android.R.id.list);\n        return expandableListView;\n    }\n\n    private class ExpandableListConnector extends BaseAdapter {\n        private ExpandableListAdapter mExpandableListAdapter;\n\n        public ExpandableListConnector(ExpandableListAdapter expandableListAdapter) {\n            this.mExpandableListAdapter = expandableListAdapter;\n        }\n\n        @Override\n        public int getCount() {\n            if (mExpandableListAdapter == null) return 0;\n            return mExpandableListAdapter.getGroupCount();\n        }\n\n        @Override\n        public void registerDataSetObserver(DataSetObserver observer) {\n            mExpandableListAdapter.registerDataSetObserver(observer);\n        }\n\n        @Override\n        public void unregisterDataSetObserver(DataSetObserver observer) {\n            mExpandableListAdapter.unregisterDataSetObserver(observer);\n        }\n\n        @Override\n        public Object getItem(int position) {\n            return null;\n        }\n\n        @Override\n        public long getItemId(int position) {\n            return 0;\n        }\n\n        @Override\n        public View getView(int position, View convertView, ViewGroup parent) {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshGridView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.GridView;\n\n/**\n * SwipeRefreshLayout 包含 HeaderGridView 布局<br>\n * 如须自定义加载框，可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}方法\n * <p>Created by hupei on 2016/5/17.\n */\npublic class SwipeRefreshGridView extends SwipeRefreshAbsListView<GridView> {\n\n    @Override\n    protected GridView createScrollView(Context context, AttributeSet attrs) {\n        GridView gridView = new GridView(context, attrs);\n        gridView.setId(android.R.id.list);\n        return gridView;\n    }\n\n    public SwipeRefreshGridView(Context context) {\n        super(context);\n    }\n\n    public SwipeRefreshGridView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshListView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.ListView;\n\n/**\n * SwipeRefreshLayout 包含 ListView 布局<br>\n * 如须自定义加载框，可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}方法\n * <p>Created by hupei on 2016/5/12.\n */\npublic class SwipeRefreshListView extends SwipeRefreshAbsListView<ListView> {\n\n    public SwipeRefreshListView(Context context) {\n        super(context);\n    }\n\n    public SwipeRefreshListView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    @Override\n    protected ListView createScrollView(Context context, AttributeSet attrs) {\n        ListView listView = new ListView(context, attrs);\n        listView.setId(android.R.id.list);\n        return listView;\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshRecyclerView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.AttributeSet;\nimport android.view.View;\n\nimport com.mylhyl.crlayout.internal.ILoadSwipeRefresh;\n\n/**\n * SwipeRefreshLayout 加 RecyclerView 布局<br>\n * 如须自定义加载框，可继承此类重写 {@link #getLoadLayoutResource()}  getLoadLayoutResource}方法\n * <p> Created by hupei on 2016/5/12.\n */\npublic class SwipeRefreshRecyclerView extends SwipeRefreshAdapterView<RecyclerView> {\n    private RecyclerView.Adapter mEmptyDataSetAdapter;\n    private EmptyDataSetObserver mDataSetObserver;\n\n    public SwipeRefreshRecyclerView(Context context) {\n        super(context);\n    }\n\n    public SwipeRefreshRecyclerView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    /**\n     * 为 RecyclerView 设置适配器\n     *\n     * @param adapter\n     */\n    public final void setAdapter(RecyclerView.Adapter adapter) {\n        if (adapter == null)\n            throw new NullPointerException(\"mAdapter is null please call CygSwipeRefreshLayout\" +\n                    \".setAdapter\");\n        getScrollView().setOnScrollListener(new OnScrollRecyclerViewListener(this));\n        getScrollView().setAdapter(adapter);\n        registerAdapterDataObserver(adapter);\n    }\n\n    public void setLayoutManager(RecyclerView.LayoutManager layout) {\n        getScrollView().setLayoutManager(layout);\n    }\n\n    @Override\n    protected RecyclerView createScrollView(Context context, AttributeSet attrs) {\n        RecyclerView recyclerView = new RecyclerView(context, attrs);\n        recyclerView.setId(android.R.id.list);\n        return recyclerView;\n    }\n\n    private void registerAdapterDataObserver(RecyclerView.Adapter adapter) {\n        if (mEmptyDataSetAdapter != null && mDataSetObserver != null)\n            mEmptyDataSetAdapter.unregisterAdapterDataObserver(mDataSetObserver);\n\n        mEmptyDataSetAdapter = adapter;\n        if (mEmptyDataSetAdapter != null){\n            mDataSetObserver = new EmptyDataSetObserver();\n            mEmptyDataSetAdapter.registerAdapterDataObserver(mDataSetObserver);\n            mDataSetObserver.onChanged();\n        }\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        if (mEmptyDataSetAdapter != null && mDataSetObserver != null) {\n            mEmptyDataSetAdapter.unregisterAdapterDataObserver(mDataSetObserver);\n            mDataSetObserver = null;\n        }\n    }\n\n    public static class OnScrollRecyclerViewListener extends RecyclerView.OnScrollListener {\n        private ILoadSwipeRefresh mILoadSwipeRefresh;\n        private RecyclerView.OnScrollListener mOnScrollListener;\n\n        public OnScrollRecyclerViewListener(ILoadSwipeRefresh loadSwipeRefresh) {\n            mILoadSwipeRefresh = loadSwipeRefresh;\n        }\n\n        public OnScrollRecyclerViewListener(ILoadSwipeRefresh loadSwipeRefresh, RecyclerView\n                .OnScrollListener onScrollListener) {\n            mILoadSwipeRefresh = loadSwipeRefresh;\n            mOnScrollListener = onScrollListener;\n        }\n\n        @Override\n        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {\n            super.onScrollStateChanged(recyclerView, newState);\n            // 只有在闲置状态情况下检查\n            if (newState == RecyclerView.SCROLL_STATE_IDLE) {\n                // 如果满足允许上拉加载、非加载状态中、最后一个显示的 item 与数据源的大小一样，则表示滑动入底部\n                if (!isFirstItemVisible(recyclerView) && mILoadSwipeRefresh.isEnabledLoad()\n                        && !mILoadSwipeRefresh.isLoading() && isLastItemVisible(recyclerView)) {\n                    mILoadSwipeRefresh.loadData();// 执行上拉加载数据\n                }\n            }\n            if (null != mOnScrollListener)\n                mOnScrollListener.onScrollStateChanged(recyclerView, newState);\n        }\n\n        @Override\n        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {\n            super.onScrolled(recyclerView, dx, dy);\n            if (null != mOnScrollListener)\n                mOnScrollListener.onScrolled(recyclerView, dx, dy);\n        }\n\n        /**\n         * 判断第一个条目是否完全可见\n         *\n         * @param recyclerView\n         * @return\n         */\n        private boolean isFirstItemVisible(RecyclerView recyclerView) {\n            final RecyclerView.Adapter<?> adapter = recyclerView.getAdapter();\n            // 如果未设置Adapter或者Adapter没有数据可以下拉刷新\n            if (null == adapter || adapter.getItemCount() == 0) {\n                return true;\n            }\n            // 第一个条目完全展示,可以刷新\n            if (getFirstVisiblePosition(recyclerView) == 0) {\n                return recyclerView.getChildAt(0).getTop() >= recyclerView.getTop();\n            }\n            return false;\n        }\n\n        /**\n         * 获取第一个可见子View的位置下标\n         *\n         * @param recyclerView\n         * @return\n         */\n        private int getFirstVisiblePosition(RecyclerView recyclerView) {\n            View firstVisibleChild = recyclerView.getChildAt(0);\n            return firstVisibleChild != null ?\n                    recyclerView.getChildAdapterPosition(firstVisibleChild) : -1;\n        }\n\n        /**\n         * 判断最后一个条目是否完全可见\n         *\n         * @param recyclerView\n         * @return\n         */\n        private boolean isLastItemVisible(RecyclerView recyclerView) {\n            final RecyclerView.Adapter<?> adapter = recyclerView.getAdapter();\n            // 如果未设置Adapter或者Adapter没有数据可以上拉刷新\n            if (null == adapter || adapter.getItemCount() == 0) {\n                return true;\n            }\n            // 最后一个条目View完全展示,可以刷新\n            int lastVisiblePosition = getLastVisiblePosition(recyclerView);\n            if (lastVisiblePosition >= recyclerView.getAdapter().getItemCount() - 1) {\n                return recyclerView.getChildAt(recyclerView.getChildCount() - 1).getBottom()\n                        <= recyclerView.getBottom();\n            }\n            return false;\n        }\n\n        /**\n         * 获取最后一个可见子View的位置下标\n         *\n         * @param recyclerView\n         * @return\n         */\n        private int getLastVisiblePosition(RecyclerView recyclerView) {\n            View lastVisibleChild = recyclerView.getChildAt(recyclerView.getChildCount() - 1);\n            return lastVisibleChild != null ? recyclerView.getChildAdapterPosition\n                    (lastVisibleChild) : -1;\n        }\n    }\n\n    private class EmptyDataSetObserver extends RecyclerView.AdapterDataObserver {\n        @Override\n        public void onChanged() {\n            updateEmptyViewShown(mEmptyDataSetAdapter == null || mEmptyDataSetAdapter\n                    .getItemCount() == 0);\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount) {\n            onChanged();\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {\n            onChanged();\n        }\n\n        @Override\n        public void onItemRangeInserted(int positionStart, int itemCount) {\n            onChanged();\n        }\n\n        @Override\n        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {\n            onChanged();\n        }\n\n        @Override\n        public void onItemRangeRemoved(int positionStart, int itemCount) {\n            onChanged();\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/SwipeRefreshWebView.java",
    "content": "package com.mylhyl.crlayout;\n\nimport android.content.Context;\nimport android.support.annotation.ColorRes;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.util.AttributeSet;\nimport android.webkit.WebChromeClient;\nimport android.webkit.WebView;\n\n/**\n * SwipeRefreshLayout 加 WebView 布局<br>\n * <p> Created by hupei on 2016/5/12.\n */\npublic class SwipeRefreshWebView extends BaseSwipeRefresh<WebView> {\n    private final SwipeRefreshLayout.OnRefreshListener refreshListener = new SwipeRefreshLayout.OnRefreshListener() {\n        @Override\n        public void onRefresh() {\n            getScrollView().reload();\n        }\n    };\n    private final WebChromeClient defaultWebChromeClient = new WebChromeClient() {\n\n        @Override\n        public void onProgressChanged(WebView view, int newProgress) {\n            if (newProgress == 100) {\n                setRefreshing(false);\n            }\n        }\n    };\n\n    public SwipeRefreshWebView(Context context) {\n        this(context, null);\n    }\n\n    public SwipeRefreshWebView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        if (!isInEditMode()) {\n            setOnRefreshListener(refreshListener);\n            getScrollView().setWebChromeClient(defaultWebChromeClient);\n        }\n    }\n\n    @Override\n    public final void autoRefresh() {\n        mLoadSwipeRefresh.showProgressView();\n        mLoadSwipeRefresh.setRefreshing(true);\n    }\n\n    @Override\n    public final void autoRefresh(@ColorRes int... colorResIds) {\n        //重写主要是为了显示动画时，不响应 onRefresh() 方法\n        mLoadSwipeRefresh.showProgressView(colorResIds);\n        mLoadSwipeRefresh.setRefreshing(true);\n    }\n\n    @Override\n    protected WebView createScrollView(Context context, AttributeSet attrs) {\n        WebView webView = new WebView(context, attrs);\n        webView.setId(android.R.id.list);\n        return webView;\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/BaseSwipeRefreshFragment.java",
    "content": "package com.mylhyl.crlayout.app;\n\nimport android.os.Bundle;\nimport android.support.annotation.ColorRes;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.mylhyl.crlayout.BaseSwipeRefresh;\nimport com.mylhyl.crlayout.internal.ISwipeRefresh;\n\n/**\n * Google自家下拉刷新 SwipeRefreshLayout <br>\n * <p/>\n * 注：SwipeRefreshLayout 只能有一个 childView，childView自身必须是可滚动的view<br>\n * 或 childView 必须包含可滚动的view，如ScrollView或者AbsListView<br>\n * 子类继承重写 onCreateView 必须 super\n */\nabstract class BaseSwipeRefreshFragment<T extends BaseSwipeRefresh> extends Fragment\n        implements SwipeRefreshLayout.OnRefreshListener {\n\n    /**\n     * 创建下拉刷新控件子类重写\n     *\n     * @return\n     */\n    public abstract T createSwipeRefreshLayout();\n\n    protected T mSwipeRefresh;\n\n    @Override\n    public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        return mSwipeRefresh = createSwipeRefreshLayout();\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        // 注册下拉刷新\n        mSwipeRefresh.setOnRefreshListener(this);\n    }\n\n    public final void autoRefresh() {\n        getSwipeRefreshLayout().autoRefresh();\n    }\n\n    public final void autoRefresh(@ColorRes int... colorResIds) {\n        getSwipeRefreshLayout().autoRefresh(colorResIds);\n    }\n\n    /**\n     * {@link ISwipeRefresh#setRefreshing(boolean)}\n     */\n    public final void setRefreshing(boolean refreshing) {\n        getSwipeRefreshLayout().setRefreshing(refreshing);\n    }\n\n\n    public final void setEmptyText(int resId) {\n        setEmptyText(getString(resId));\n    }\n\n    public final void setEmptyText(CharSequence text) {\n        getSwipeRefreshLayout().setEmptyText(text);\n    }\n\n    public final void setEmptyView(View emptyView) {\n        getSwipeRefreshLayout().setEmptyView(emptyView);\n    }\n\n    public final T getSwipeRefreshLayout() {\n        return mSwipeRefresh;\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAbsListFragment.java",
    "content": "package com.mylhyl.crlayout.app;\n\nimport android.view.View;\nimport android.widget.AbsListView;\nimport android.widget.AdapterView;\nimport android.widget.ExpandableListView;\nimport android.widget.ListAdapter;\n\nimport com.mylhyl.crlayout.SwipeRefreshAbsListView;\n\n\nabstract class SwipeRefreshAbsListFragment<T extends SwipeRefreshAbsListView> extends SwipeRefreshAdapterFragment<T> {\n    private final AdapterView.OnItemClickListener mOnItemClickListener = new AdapterView.OnItemClickListener() {\n\n        @Override\n        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n            /**\n             * ListView or GridView 单点事件\n             */\n            onListItemClick(parent, view, position, id);\n        }\n    };\n\n\n    /**\n     * Item 点击时此方法调用，子类可重写\n     *\n     * @param parent\n     * @param view\n     * @param position\n     * @param id\n     */\n    public void onListItemClick(AdapterView<?> parent, View view, int position, long id) {\n    }\n\n    /**\n     * 适配器设置数据源\n     *\n     * @param adapter\n     * @author hupei\n     * @date 2015年7月31日 上午9:06:14\n     */\n    public final void setListAdapter(ListAdapter adapter) {\n        AbsListView absListView = (AbsListView) getSwipeRefreshLayout().getScrollView();\n        if (absListView instanceof ExpandableListView) {\n            new RuntimeException(\"please call SwipeRefreshExpandableListFragment.setListAdapter()\");\n        }\n        T swipeRefreshLayout = getSwipeRefreshLayout();\n        if (swipeRefreshLayout != null && swipeRefreshLayout instanceof SwipeRefreshAbsListView) {\n            absListView.setVisibility(View.VISIBLE);\n            absListView.setOnItemClickListener(mOnItemClickListener);\n\n            swipeRefreshLayout.setAdapter(adapter);\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshAdapterFragment.java",
    "content": "package com.mylhyl.crlayout.app;\n\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\nimport com.mylhyl.crlayout.SwipeRefreshListView;\n\n/**\n * 如果开启{@linkplain SwipeRefreshAdapterFragment#setEnabledLoad(boolean) 上拉加载}功能\n * 必须重写 {@linkplain SwipeRefreshAdapterFragment#onListLoad() onListLoad()}方法<br>\n */\nabstract class SwipeRefreshAdapterFragment<T extends SwipeRefreshAdapterView> extends BaseSwipeRefreshFragment<T>\n        implements SwipeRefreshAdapterView.OnListLoadListener {\n\n\n    /**\n     * 设置允许上拉加载，重写{@link #onListLoad() onListLoad 方法实现上拉加载数据}\n     *\n     * @param enabled\n     * @see SwipeRefreshListView#setEnabledLoad(boolean)\n     * @see SwipeRefreshListView#setOnListLoadListener(SwipeRefreshAdapterView.OnListLoadListener)\n     */\n    public final void setEnabledLoad(boolean enabled) {\n        if (enabled)\n            mSwipeRefresh.setOnListLoadListener(this);\n        mSwipeRefresh.setEnabledLoad(enabled);\n    }\n\n\n    /**\n     * {@link SwipeRefreshAdapterView#setLoading(boolean)}\n     */\n    public final void setLoading(boolean loading) {\n        getSwipeRefreshLayout().setLoading(loading);\n    }\n\n    @Override\n    public void onListLoad() {\n\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshExpandableListFragment.java",
    "content": "package com.mylhyl.crlayout.app;\n\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.ExpandableListAdapter;\nimport android.widget.ExpandableListView;\n\nimport com.mylhyl.crlayout.SwipeRefreshExpandableListView;\n\n/**\n * Created by hupei on 2016/5/16.\n */\npublic abstract class SwipeRefreshExpandableListFragment extends SwipeRefreshAbsListFragment<SwipeRefreshExpandableListView> {\n    private final ExpandableListView.OnGroupClickListener mOnGroupClickListener = new ExpandableListView.OnGroupClickListener() {\n        @Override\n        public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {\n            return onListGroupClick(parent, v, groupPosition, id);\n        }\n    };\n    private final ExpandableListView.OnChildClickListener mOnChildClickListener = new ExpandableListView.OnChildClickListener() {\n\n        @Override\n        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {\n            return onListChildClick(parent, v, groupPosition, childPosition, id);\n        }\n    };\n\n    public boolean onListChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {\n        return false;\n    }\n\n    public boolean onListGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {\n        return false;\n    }\n\n    @Override\n    public final void onListItemClick(AdapterView<?> parent, View view, int position, long id) {\n        //子类不允许重写\n        super.onListItemClick(parent, view, position, id);\n    }\n\n    @Override\n    public SwipeRefreshExpandableListView createSwipeRefreshLayout() {\n        return new SwipeRefreshExpandableListView(getActivity());\n    }\n\n    public final void setListAdapter(ExpandableListAdapter adapter) {\n        ExpandableListView expandableListView = getSwipeRefreshLayout().getScrollView();\n        SwipeRefreshExpandableListView swipeRefreshExpandableListView = getSwipeRefreshLayout();\n        if (expandableListView != null && swipeRefreshExpandableListView != null) {\n            expandableListView.setVisibility(View.VISIBLE);\n\n            expandableListView.setOnGroupClickListener(mOnGroupClickListener);\n            expandableListView.setOnChildClickListener(mOnChildClickListener);\n\n            swipeRefreshExpandableListView.setAdapter(adapter);\n        }\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/app/SwipeRefreshListFragment.java",
    "content": "package com.mylhyl.crlayout.app;\n\nimport com.mylhyl.crlayout.SwipeRefreshListView;\n\npublic abstract class SwipeRefreshListFragment extends SwipeRefreshAbsListFragment<SwipeRefreshListView> {\n\n    @Override\n    public SwipeRefreshListView createSwipeRefreshLayout() {\n        return new SwipeRefreshListView(getActivity());\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ILoadSwipeRefresh.java",
    "content": "package com.mylhyl.crlayout.internal;\n\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\n\n/**\n * Created by hupei on 2016/5/18.\n */\npublic interface ILoadSwipeRefresh {\n\n    void setOnListLoadListener(SwipeRefreshAdapterView.OnListLoadListener onListLoadListener);\n\n    void setLoadLayoutResource(int resource);\n\n    void loadData();\n\n    /**\n     * 设置是否处于上拉加载状态\n     *\n     * @param loading 为true加载状态，false结束加载\n     */\n    void setLoading(boolean loading);\n\n    /**\n     * 允许上拉加载\n     *\n     * @param enabled\n     */\n    void setEnabledLoad(boolean enabled);\n\n    /**\n     * 是否在上拉加载中\n     *\n     * @return\n     */\n    boolean isLoading();\n\n    /**\n     * 是否允许上拉加载\n     *\n     * @return\n     */\n    boolean isEnabledLoad();\n\n    /**\n     * 设置加载完成\n     *\n     * @param loadCompleted\n     */\n    void setLoadCompleted(boolean loadCompleted);\n\n    LoadConfig getLoadConfig();\n\n    /**\n     * 设置加载Layout有动画显示效果,默认false\n     *\n     * @param isLoadAnimator true 启用动画\n     */\n    void setLoadAnimator(boolean isLoadAnimator);\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/ISwipeRefresh.java",
    "content": "package com.mylhyl.crlayout.internal;\n\nimport android.support.annotation.ColorRes;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.view.View;\n\n/**\n * Created by hupei on 2016/5/18.\n */\npublic interface ISwipeRefresh<T> {\n    /**\n     * 显示刷新动画，颜色随系统\n     */\n    void autoRefresh();\n\n    /**\n     * 显示刷新动画，可指定颜色\n     *\n     * @param colorResIds 动画颜色\n     */\n    void autoRefresh(@ColorRes int... colorResIds);\n\n    void autoRefresh(boolean scale, int start, int end, @ColorRes int... colorResIds);\n\n    void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener);\n\n    void setEmptyText(CharSequence text);\n\n    void setEmptyText(int resId);\n\n    void setEmptyView(View emptyView);\n\n    View getEmptyView();\n\n    /**\n     * 设置下拉刷新状态\n     *\n     * @param refreshing true=刷新中；false=刷新完成\n     */\n    void setRefreshing(boolean refreshing);\n\n    /**\n     * 禁用下拉刷新\n     *\n     * @param enabled\n     */\n    void setEnabled(boolean enabled);\n\n    /**\n     * 获取可滑动的 ListView、ExpandableListView、GridView、RecyclerView\n     *\n     * @return\n     */\n    T getScrollView();\n\n\n    SwipeRefreshLayout getSwipeRefreshLayout();\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadConfig.java",
    "content": "package com.mylhyl.crlayout.internal;\n\nimport android.graphics.drawable.Drawable;\n\n/**\n * Created by hupei on 2016/5/19.\n */\npublic interface LoadConfig {\n    /**\n     * 设置加载文字\n     *\n     * @param label\n     */\n    void setLoadText(String label);\n\n    /**\n     * 设置加载文字大小\n     *\n     * @param size\n     */\n    void setLoadTextSize(float size);\n\n    /**\n     * 设置加载文字颜色\n     *\n     * @param color\n     */\n    void setLoadTextColor(int color);\n\n    /**\n     * 设置菊花显示或隐藏\n     *\n     * @param v\n     */\n    void setProgressBarVisibility(int v);\n\n    /**\n     * 设置菊花样式\n     *\n     * @param d\n     */\n    void setIndeterminateDrawable(Drawable d);\n\n    /**\n     * 设置加载完成文字\n     *\n     * @param text\n     */\n    void setLoadCompletedText(String text);\n\n    /**\n     * 设置加载更多 Layout 高度\n     *\n     * @param height\n     */\n    void setLoadViewHeight(int height);\n\n    /**\n     * 设置加载更多 Layout 资源背景\n     *\n     * @param resId\n     */\n    void setLoadViewBackgroundResource(int resId);\n\n    /**\n     * 设置加载更多 Layout 颜色背景\n     *\n     * @param color\n     */\n    void setLoadViewBackgroundColor(int color);\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayout.java",
    "content": "package com.mylhyl.crlayout.internal;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.view.Gravity;\nimport android.view.ViewGroup;\nimport android.widget.AbsListView;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\n/**\n * 上拉加载 layout 包含 ProgressBar 与 TextView\n * Created by hupei on 2016/5/19.\n */\npublic final class LoadLayout extends LoadLayoutBase {\n    public LoadLayout(Context context) {\n        super(context);\n    }\n\n    @Override\n    void createFooter(ViewGroup v) {\n        LinearLayout root = (LinearLayout) v;\n        root.setOrientation(HORIZONTAL);\n        root.setGravity(Gravity.CENTER);\n        root.setBackgroundColor(Color.WHITE);\n        root.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, pxTdp(50)));\n\n        mProgressBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmallInverse);\n        root.addView(mProgressBar, new AbsListView.LayoutParams(\n                AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT));\n\n        mTextView = new TextView(getContext());\n        mTextView.setTextAppearance(getContext(), android.R.attr.textAppearanceMedium);\n        root.addView(mTextView, new LayoutParams(\n                AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT));\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutBase.java",
    "content": "package com.mylhyl.crlayout.internal;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.ColorInt;\nimport android.support.annotation.DrawableRes;\nimport android.util.TypedValue;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.LinearLayout;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\n/**\n * 上拉加载 layout 基类\n * Created by hupei on 2016/5/19.\n */\npublic abstract class LoadLayoutBase extends LinearLayout implements LoadConfig {\n\n    private String mFooterText;\n    private String mCompletedText;\n\n    protected ProgressBar mProgressBar;\n    protected TextView mTextView;\n\n    abstract void createFooter(ViewGroup v);\n\n    public LoadLayoutBase(Context context) {\n        super(context);\n        createFooter(this);\n    }\n\n    public LoadLayoutBase(Context context, View v) {\n        super(context);\n        createFooter((ViewGroup) v);\n    }\n\n    protected int pxTdp(int size) {\n        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, getResources().getDisplayMetrics());\n    }\n\n    @Override\n    public void setLoadViewHeight(int height) {\n        ViewGroup.LayoutParams params = getLayoutParams();\n        params.height = pxTdp(height);\n        setLayoutParams(params);\n    }\n\n    @Override\n    public void setLoadText(String text) {\n        mFooterText = text;\n        if (mTextView != null)\n            mTextView.setText(text);\n    }\n\n    @Override\n    public void setLoadTextSize(float size) {\n        if (mTextView != null)\n            mTextView.setTextSize(size);\n    }\n\n    @Override\n    public void setLoadTextColor(@ColorInt int color) {\n        if (mTextView != null)\n            mTextView.setTextColor(color);\n    }\n\n    @Override\n    public void setLoadViewBackgroundResource(@DrawableRes int resId) {\n        setBackgroundResource(resId);\n    }\n\n    @Override\n    public void setLoadViewBackgroundColor(@ColorInt int color) {\n        setBackgroundColor(color);\n    }\n\n    @Override\n    public void setProgressBarVisibility(int v) {\n        if (mProgressBar != null)\n            mProgressBar.setVisibility(v);\n    }\n\n    @Override\n    public void setIndeterminateDrawable(Drawable d) {\n        if (mProgressBar != null)\n            mProgressBar.setIndeterminateDrawable(d);\n    }\n\n    @Override\n    public void setLoadCompletedText(String text) {\n        mCompletedText = text;\n        if (mTextView != null)\n            mTextView.setText(text);\n    }\n\n    public String getFooterText() {\n        return mFooterText;\n    }\n\n    public String getCompletedText() {\n        return mCompletedText;\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/java/com/mylhyl/crlayout/internal/LoadLayoutConvert.java",
    "content": "package com.mylhyl.crlayout.internal;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\n/**\n * 转换自定义上拉加载 View\n * Created by hupei on 2016/5/19.\n */\npublic final class LoadLayoutConvert extends LoadLayoutBase {\n\n    public LoadLayoutConvert(Context context, View v) {\n        super(context, v);\n    }\n\n    @Override\n    void createFooter(ViewGroup v) {\n        //查找 mProgressBar 与 mTextView\n        int count = v.getChildCount();\n        for (int i = 0; i < count; i++) {\n            View childAt = v.getChildAt(i);\n            if (childAt instanceof ProgressBar)\n                mProgressBar = (ProgressBar) childAt;\n            else if (childAt instanceof TextView)\n                mTextView = (TextView) childAt;\n        }\n        setLayoutParams(v.getLayoutParams());\n        addView(v);\n    }\n}\n"
  },
  {
    "path": "commonrefreshlayout/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"crLayout\">\n        <!-- 自定义加载更多 res layout id-->\n        <attr name=\"load_layout\" format=\"reference\" />\n        <!--加载更多显示的文字-->\n        <attr name=\"load_text\" format=\"string\" />\n        <!--加载更多的进度菊花-->\n        <attr name=\"load_indeterminate_drawable\" format=\"reference\" />\n        <!--加载更多完成显示的文字-->\n        <attr name=\"load_completed_text\" format=\"string\" />\n        <!--加载更多layout有动画显示效果-->\n        <attr name=\"load_animator\" format=\"boolean\"/>\n        <attr name=\"empty_text\" format=\"string\"/>\n    </declare-styleable>\n</resources>\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri May 26 15:10:51 CST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "sample/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "sample/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"23.0.3\"\n\n    defaultConfig {\n        applicationId \"com.mylhyl.prlayout.sample\"\n        minSdkVersion 15\n        targetSdkVersion 23\n        versionCode 1\n        versionName \"1.0\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    lintOptions {\n        abortOnError false\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile project(':commonrefreshlayout')\n    compile 'com.android.support:appcompat-v7:23.3.0'\n    compile 'com.android.support:support-v4:23.3.0'\n    compile 'com.github.bumptech.glide:glide:3.7.0'\n    compile 'com.mylhyl:cygadapter:1.0.0'\n    compile files('libs/lite-http-3.0.0.jar')\n    compile 'com.android.support:cardview-v7:23.3.0'\n}\n"
  },
  {
    "path": "sample/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in E:\\android\\android-sdk-windows/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "sample/src/androidTest/java/com/mylhyl/crlayout/sample/ApplicationTest.java",
    "content": "package com.mylhyl.crlayout.sample;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "sample/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.mylhyl.crlayout.sample\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <application\n        android:name=\".APP\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\"com.mylhyl.crlayout.sample.MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/APP.java",
    "content": "package com.mylhyl.crlayout.sample;\n\nimport android.app.Application;\n\nimport com.bumptech.glide.request.target.ViewTarget;\n\npublic class APP extends Application {\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        //因为Glide加载图片的源码中也使用了setTag和getTag模式而\n        //https://github.com/bumptech/glide/issues/370\n        ViewTarget.setTagId(R.string.app_name);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/MainActivity.java",
    "content": "package com.mylhyl.crlayout.sample;\n\nimport android.content.ContentUris;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport android.support.v7.app.AppCompatActivity;\n\nimport com.mylhyl.crlayout.sample.app.AppExpandableListFragment;\nimport com.mylhyl.crlayout.sample.app.AppListFragment;\nimport com.mylhyl.crlayout.sample.app.GridViewFragment;\nimport com.mylhyl.crlayout.sample.app.ListViewFragment;\nimport com.mylhyl.crlayout.sample.app.RecyclerViewFragment;\nimport com.mylhyl.crlayout.sample.app.WebViewFragment;\n\npublic class MainActivity extends AppCompatActivity implements TypesFragment.OnFragmentInteractionListener {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (savedInstanceState == null) {\n            getSupportFragmentManager().beginTransaction()\n                    .add(android.R.id.content, TypesFragment.newInstance())\n                    .commitAllowingStateLoss();\n        }\n    }\n\n    @Override\n    public void onFragmentInteraction(Uri uri) {\n        Fragment fragment = null;\n        int typeId = (int) ContentUris.parseId(uri);\n        switch (typeId) {\n            case 0:\n                fragment = ListViewFragment.newInstance();\n                break;\n            case 1:\n                fragment = GridViewFragment.newInstance();\n                break;\n            case 2:\n                fragment = RecyclerViewFragment.newInstance();\n                break;\n            case 3:\n                fragment = WebViewFragment.newInstance();\n                break;\n            case 4:\n                fragment = AppListFragment.newInstance();\n                break;\n            case 5:\n                fragment = AppExpandableListFragment.newInstance();\n                break;\n        }\n        if (fragment != null)\n            getSupportFragmentManager().beginTransaction()\n                    .replace(android.R.id.content, fragment)\n                    .addToBackStack(null)\n                    .commitAllowingStateLoss();\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/TypesFragment.java",
    "content": "package com.mylhyl.crlayout.sample;\n\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android.net.Uri;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.ArrayAdapter;\nimport android.widget.ListView;\n\n\npublic class TypesFragment extends Fragment implements AdapterView.OnItemClickListener {\n\n    private OnFragmentInteractionListener mListener;\n    private Uri mUri = Uri.parse(\"content://com.mylhyl.crlayout.sample/types\");\n\n    public TypesFragment() {\n    }\n\n    public static TypesFragment newInstance() {\n        return new TypesFragment();\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_types, container, false);\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        ListView listView = (ListView) view.findViewById(R.id.listView);\n        listView.setOnItemClickListener(this);\n        listView.setAdapter(new ArrayAdapter<>(getContext(),\n                android.R.layout.simple_list_item_1, getResources().getStringArray(R.array.types)));\n    }\n\n    @Override\n    public void onAttach(Context context) {\n        super.onAttach(context);\n        if (context instanceof OnFragmentInteractionListener) {\n            mListener = (OnFragmentInteractionListener) context;\n        } else {\n            throw new RuntimeException(context.toString()\n                    + \" must implement OnFragmentInteractionListener\");\n        }\n    }\n\n    @Override\n    public void onDetach() {\n        super.onDetach();\n        mListener = null;\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        Uri uri = ContentUris.withAppendedId(mUri, position);\n        onButtonPressed(uri);\n    }\n\n    public void onButtonPressed(Uri uri) {\n        if (mListener != null) {\n            mListener.onFragmentInteraction(uri);\n        }\n    }\n\n    public interface OnFragmentInteractionListener {\n        void onFragmentInteraction(Uri uri);\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/AppExpandableListFragment.java",
    "content": "package com.mylhyl.crlayout.sample.app;\n\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.os.Bundle;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseExpandableListAdapter;\nimport android.widget.ExpandableListView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.mylhyl.crlayout.SwipeRefreshExpandableListView;\nimport com.mylhyl.crlayout.app.SwipeRefreshExpandableListFragment;\nimport com.mylhyl.crlayout.sample.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by hupei on 2016/5/13.\n */\npublic class AppExpandableListFragment extends SwipeRefreshExpandableListFragment {\n    private MyExpandableListAdapter adapter;\n    private List<String> groups = new ArrayList<>();\n    private List<List<String>> childs = new ArrayList<>();\n    private int index;\n    private int footerIndex = 20;\n\n    public static AppExpandableListFragment newInstance() {\n        return new AppExpandableListFragment();\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        setHasOptionsMenu(true);\n        setEnabledLoad(true);\n        for (int i = 0; i < footerIndex; i++) {\n            groups.add(\"group = \" + i);\n            List<String> child = new ArrayList<>();\n            for (int j = 0; j < 3; j++) {\n                child.add(\"child = \" + i + \":\" + j);\n            }\n            childs.add(child);\n        }\n        adapter = new MyExpandableListAdapter(this.getContext());\n        setListAdapter(adapter);\n        setEmptyText(\"什么也没有！\");\n    }\n\n    @Override\n    public SwipeRefreshExpandableListView createSwipeRefreshLayout() {\n        return new SwipeRefreshExpandableListView(getActivity());\n    }\n\n    @Override\n    public boolean onListGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {\n        Toast.makeText(getContext(), \"groupPosition：\" + groupPosition, Toast.LENGTH_SHORT).show();\n        return false;\n    }\n\n    @Override\n    public boolean onListChildClick(ExpandableListView parent, View v,\n                                    int groupPosition, int childPosition, long id) {\n        Toast.makeText(getContext(), \"groupPosition：\"\n                + groupPosition + \" | childPosition：\" + childPosition, Toast.LENGTH_SHORT).show();\n        return true;\n    }\n\n    @Override\n    public void onRefresh() {\n        getSwipeRefreshLayout().getScrollView().postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                int count = --index;\n                groups.add(0, \"下拉group = \" + count);\n                List<String> child = new ArrayList<>();\n                for (int j = 0; j < 3; j++) {\n                    child.add(\"下拉child = \" + count + \":\" + j);\n                }\n                childs.add(child);\n                adapter.notifyDataSetChanged();\n                setRefreshing(false);\n            }\n        }, 1000);\n    }\n\n    @Override\n    public void onListLoad() {\n        getSwipeRefreshLayout().getScrollView().postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                int count = footerIndex + 3;\n                for (int i = footerIndex; i < count; i++) {\n                    groups.add(\"上拉group = \" + count);\n                    List<String> child = new ArrayList<>();\n                    for (int j = 0; j < 3; j++) {\n                        child.add(\"上拉child = \" + count + \":\" + j);\n                    }\n                    childs.add(0, child);\n                }\n                footerIndex = count;\n                adapter.notifyDataSetChanged();\n                setLoading(false);\n            }\n        }, 2000);\n    }\n\n    @Override\n    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        inflater.inflate(R.menu.menu, menu);\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        groups.clear();\n        childs.clear();\n        adapter.notifyDataSetChanged();\n        return super.onOptionsItemSelected(item);\n    }\n\n    class MyExpandableListAdapter extends BaseExpandableListAdapter {\n        private LayoutInflater inflater;\n\n        public MyExpandableListAdapter(Context context) {\n            inflater = LayoutInflater.from(context);\n        }\n\n        @Override\n        public int getGroupCount() {\n            return groups.size();\n        }\n\n        @Override\n        public int getChildrenCount(int groupPosition) {\n            return childs.get(groupPosition).size();\n        }\n\n        @Override\n        public String getGroup(int groupPosition) {\n            return groups.get(groupPosition);\n        }\n\n        @Override\n        public String getChild(int groupPosition, int childPosition) {\n            return childs.get(groupPosition).get(childPosition);\n        }\n\n        @Override\n        public long getGroupId(int groupPosition) {\n            return 0;\n        }\n\n        @Override\n        public long getChildId(int groupPosition, int childPosition) {\n            return 0;\n        }\n\n        @Override\n        public boolean hasStableIds() {\n            return false;\n        }\n\n        @Override\n        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {\n            View view = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false);\n            TextView tv = (TextView) view.findViewById(android.R.id.text1);\n            tv.setText(getGroup(groupPosition));\n            return view;\n        }\n\n        @Override\n        public View getChildView(int groupPosition, int childPosition,\n                                 boolean isLastChild, View convertView, ViewGroup parent) {\n            View view = inflater.inflate(android.R.layout.simple_expandable_list_item_2, parent, false);\n            TextView tv = (TextView) view.findViewById(android.R.id.text1);\n            tv.setText(getChild(groupPosition, childPosition));\n            tv.setTextColor(Color.RED);\n            return view;\n        }\n\n        @Override\n        public boolean isChildSelectable(int groupPosition, int childPosition) {\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/AppListFragment.java",
    "content": "package com.mylhyl.crlayout.sample.app;\n\nimport android.os.Bundle;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.ImageView;\nimport android.widget.Toast;\n\nimport com.bumptech.glide.Glide;\nimport com.litesuits.http.LiteHttp;\nimport com.litesuits.http.listener.HttpListener;\nimport com.litesuits.http.request.AbstractRequest;\nimport com.litesuits.http.request.StringRequest;\nimport com.litesuits.http.request.param.HttpMethods;\nimport com.litesuits.http.response.Response;\nimport com.mylhyl.crlayout.internal.LoadConfig;\nimport com.mylhyl.crlayout.app.SwipeRefreshListFragment;\nimport com.mylhyl.crlayout.sample.R;\nimport com.mylhyl.cygadapter.CygAdapter;\nimport com.mylhyl.cygadapter.CygViewHolder;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * Created by hupei on 2016/5/13.\n */\npublic class AppListFragment extends SwipeRefreshListFragment {\n    private static final String URL = \"http://image.baidu.com/\";\n    private static final String REGEX_IMG = \"<img.*?src=\\\"http://(.*?).jpg\\\"\";\n    private CygAdapter<String> adapter;\n    private List<String> objects = new ArrayList<>();\n    private LiteHttp liteHttp;\n    private int index;\n\n    public static AppListFragment newInstance() {\n        return new AppListFragment();\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        setHasOptionsMenu(true);\n\n        getSwipeRefreshLayout().setLoadAnimator(true);\n        setEnabledLoad(true);\n\n        adapter = new CygAdapter<String>(getContext(), R.layout.image_item, objects) {\n            @Override\n            public void onBindData(CygViewHolder viewHolder, String item, int position) {\n                ImageView imageView = viewHolder.findViewById(R.id.img_item);\n                Glide.with(mContext)\n                        .load(item.toString())\n                        .into(imageView);\n            }\n        };\n        setListAdapter(adapter);\n        setEmptyText(\"无数据\");\n        LoadConfig loadConfig = getSwipeRefreshLayout().getLoadConfig();\n        loadConfig.setLoadCompletedText(\"亲，数据加载完了！\");\n        if (liteHttp == null) {\n            liteHttp = LiteHttp.build(getContext())\n                    .setSocketTimeout(5000)\n                    .setConnectTimeout(5000)\n                    .create();\n        } else {\n            liteHttp.getConfig()\n                    .setSocketTimeout(5000)\n                    .setConnectTimeout(5000);\n        }\n        autoRefresh(R.color.colorPrimary);\n    }\n\n    @Override\n    public void onListItemClick(AdapterView<?> parent, View view, int position, long id) {\n        super.onListItemClick(parent, view, position, id);\n        Toast.makeText(getContext(), \"\" + position, Toast.LENGTH_SHORT).show();\n    }\n\n    @Override\n    public void onRefresh() {\n        index = 0;\n        adapter.clear(true);\n        executeAsync(URL);\n        getSwipeRefreshLayout().postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                setRefreshing(false);\n            }\n        }, 1000);\n    }\n\n    @Override\n    public void onListLoad() {\n        executeAsync(URL);\n        getSwipeRefreshLayout().postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                setLoading(false);\n                ++index;\n                if (index == 1) {\n                    getSwipeRefreshLayout().setLoadCompleted(true);\n                }\n            }\n        }, 1000);\n    }\n\n    private void executeAsync(String url) {\n        StringRequest stringRequest = new StringRequest(url).setMethod(HttpMethods.Get)\n                .setHttpListener(new HttpListener<String>() {\n                    @Override\n                    public void onLoading(AbstractRequest<String> request, long total, long len) {\n                        super.onLoading(request, total, len);\n                    }\n\n                    @Override\n                    public void onSuccess(String s, Response<String> response) {\n                        String result = response.getResult();\n                        List<String> imgSrcList = getImgSrcList(result);\n                        adapter.addAll(imgSrcList);\n                    }\n\n                    @Override\n                    public void onStart(AbstractRequest<String> request) {\n                        super.onStart(request);\n                    }\n\n                    @Override\n                    public void onUploading(AbstractRequest<String> request, long total, long len) {\n                        super.onUploading(request, total, len);\n                    }\n                });\n        liteHttp.executeAsync(stringRequest);\n    }\n\n    @Override\n    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        inflater.inflate(R.menu.menu, menu);\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        objects.clear();\n        adapter.notifyDataSetChanged();\n        return super.onOptionsItemSelected(item);\n    }\n\n    private static List<String> getImgSrcList(String htmlStr) {\n        List<String> pics = new ArrayList<>();\n        Pattern pImage = Pattern.compile(REGEX_IMG, Pattern.CASE_INSENSITIVE);\n        Matcher mImage = pImage.matcher(htmlStr);\n        while (mImage.find()) {\n            String src = mImage.group(1);\n            if (src.length() < 100) {\n                pics.add(\"http://\" + src + \".jpg\");\n            }\n        }\n        return pics;\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/GridViewFragment.java",
    "content": "package com.mylhyl.crlayout.sample.app;\n\nimport android.graphics.Color;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AdapterView;\nimport android.widget.ArrayAdapter;\nimport android.widget.ImageView;\nimport android.widget.Toast;\n\nimport com.mylhyl.crlayout.internal.LoadConfig;\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\nimport com.mylhyl.crlayout.SwipeRefreshGridView;\nimport com.mylhyl.crlayout.sample.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\npublic class GridViewFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,\n        SwipeRefreshAdapterView.OnListLoadListener, AdapterView.OnItemClickListener {\n    private SwipeRefreshGridView swipeRefreshGridView;\n    private ArrayAdapter<String> adapter;\n    private List<String> objects = new ArrayList<>();\n    private int index;\n    private int footerIndex = 38;\n\n    public GridViewFragment() {\n    }\n\n    public static GridViewFragment newInstance() {\n        GridViewFragment fragment = new GridViewFragment();\n        return fragment;\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_grid_view, container, false);\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        swipeRefreshGridView = (SwipeRefreshGridView) view.findViewById(R.id.swipeRefresh);\n        ImageView emptyView = new ImageView(getContext());\n        emptyView.setImageResource(R.mipmap.empty);\n        swipeRefreshGridView.setEmptyView(emptyView);\n        swipeRefreshGridView.setLoadAnimator(true);\n        swipeRefreshGridView.setLoadLayoutResource(R.layout.swipe_refresh_footer);\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        setHasOptionsMenu(true);\n        swipeRefreshGridView.setOnItemClickListener(this);\n        swipeRefreshGridView.setOnListLoadListener(this);\n        swipeRefreshGridView.setOnRefreshListener(this);\n\n        LoadConfig loadConfig = swipeRefreshGridView.getLoadConfig();\n        loadConfig.setLoadText(\"加载更多数据...\");\n        loadConfig.setLoadTextSize(18);\n        loadConfig.setLoadTextColor(Color.GREEN);\n\n        for (int i = 0; i < footerIndex; i++) {\n            objects.add(\"Grid数据 = \" + i);\n        }\n        adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, objects);\n        swipeRefreshGridView.setAdapter(adapter);\n    }\n\n\n    @Override\n    public void onRefresh() {\n        index = 0;\n        swipeRefreshGridView.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                objects.add(0, \"下拉 = \" + (--index));\n                adapter.notifyDataSetChanged();\n                swipeRefreshGridView.setRefreshing(false);\n            }\n        }, 1000);\n    }\n\n    @Override\n    public void onListLoad() {\n        ++index;\n        swipeRefreshGridView.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                int count = footerIndex + 15;\n                for (int i = footerIndex; i < count; i++) {\n                    objects.add(\"上拉 = \" + i);\n                }\n                footerIndex = count;\n                adapter.notifyDataSetChanged();\n                swipeRefreshGridView.setLoading(false);\n                if (index == 1) {\n                    swipeRefreshGridView.setLoadCompleted(true);\n                }\n            }\n        }, 2000);\n    }\n\n    @Override\n    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        inflater.inflate(R.menu.menu, menu);\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        objects.clear();\n        adapter.notifyDataSetChanged();\n        return super.onOptionsItemSelected(item);\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        Toast.makeText(getContext(), \"\" + position, Toast.LENGTH_SHORT).show();\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/ListViewFragment.java",
    "content": "package com.mylhyl.crlayout.sample.app;\n\nimport android.graphics.Color;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.os.Message;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.view.PagerAdapter;\nimport android.support.v4.view.ViewPager;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.util.TypedValue;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.AbsListView;\nimport android.widget.AdapterView;\nimport android.widget.ArrayAdapter;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\nimport com.mylhyl.crlayout.SwipeRefreshListView;\nimport com.mylhyl.crlayout.internal.LoadConfig;\nimport com.mylhyl.crlayout.sample.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\npublic class ListViewFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,\n        SwipeRefreshAdapterView.OnListLoadListener, AdapterView.OnItemClickListener {\n    private SwipeRefreshListView swipeRefreshListView;\n    private ArrayAdapter<String> adapter;\n    private List<String> objects = new ArrayList<>();\n    private int index;\n    private int pagerSize = 20;\n\n    public ListViewFragment() {\n    }\n\n    public static ListViewFragment newInstance() {\n        ListViewFragment fragment = new ListViewFragment();\n        return fragment;\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_list_view, container, false);\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        swipeRefreshListView = (SwipeRefreshListView) view.findViewById(R.id.swipeRefresh);\n        swipeRefreshListView.getSwipeRefreshLayout().setColorSchemeResources(R.color.colorPrimary);\n        swipeRefreshListView.setEnabled(false);\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        setHasOptionsMenu(true);\n        swipeRefreshListView.setOnItemClickListener(this);\n        swipeRefreshListView.setOnListLoadListener(this);\n        swipeRefreshListView.setOnRefreshListener(this);\n\n        initListViewHead();\n\n        LoadConfig loadConfig = swipeRefreshListView.getLoadConfig();\n        loadConfig.setLoadViewBackgroundColor(getResources().getColor(android.R.color.darker_gray));\n//        swipeRefreshListView.setEmptyText(\"数据呢？\");\n\n        for (int i = 0; i < pagerSize; i++) {\n            objects.add(\"数据 = \" + i);\n        }\n        adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, objects);\n        swipeRefreshListView.setAdapter(adapter);\n\n    }\n\n    private int mCurrentPosition;\n    private ViewPager mViewPager;\n    private final Handler mAutoPlayHandler = new Handler() {\n        @Override\n        public void handleMessage(Message msg) {\n            mCurrentPosition++;\n            if (mViewPager != null)\n                mViewPager.setCurrentItem(mCurrentPosition);\n            mAutoPlayHandler.sendEmptyMessageDelayed(1000, 3000);\n        }\n    };\n\n    private void initListViewHead() {\n        if (mViewPager == null) {\n            mViewPager = new ViewPager(getContext());\n            mViewPager.setLayoutParams(new AbsListView.LayoutParams(\n                    AbsListView.LayoutParams.MATCH_PARENT, (int) TypedValue.applyDimension(\n                    TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics())));\n        }\n        mViewPager.setAdapter(new PagerAdapter() {\n            @Override\n            public int getCount() {\n                return 4 + 2;\n            }\n\n            @Override\n            public boolean isViewFromObject(View view, Object object) {\n                return view == object;\n            }\n\n            @Override\n            public void destroyItem(ViewGroup container, int position, Object object) {\n            }\n\n            @Override\n            public Object instantiateItem(ViewGroup container, int position) {\n                int toRealPosition = toRealPosition(position);\n                TextView textView = (TextView) container.getChildAt(toRealPosition);\n                if (textView == null) {\n                    textView = new TextView(getContext());\n                    textView.setTextColor(Color.RED);\n                    textView.setTextSize(18);\n                    textView.setGravity(Gravity.CENTER);\n                    container.addView(textView);\n                }\n                textView.setText(\"position=\" + toRealPosition);\n                return textView;\n            }\n        });\n\n        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {\n            @Override\n            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n\n            }\n\n            @Override\n            public void onPageSelected(int position) {\n                mCurrentPosition = position % (4 + 2);\n            }\n\n            @Override\n            public void onPageScrollStateChanged(int state) {\n                if (state == ViewPager.SCROLL_STATE_IDLE) {\n                    int current = mViewPager.getCurrentItem();\n                    int last = mViewPager.getAdapter().getCount() - 2;\n                    if (current == 0) {\n                        mViewPager.setCurrentItem(last, false);\n                    } else if (current == last + 1) {\n                        mViewPager.setCurrentItem(1, false);\n                    }\n                }\n            }\n        });\n        mViewPager.setCurrentItem(1, false);\n        swipeRefreshListView.getScrollView().addHeaderView(mViewPager);\n        mAutoPlayHandler.sendEmptyMessageDelayed(1000, 3000);\n    }\n\n    private int toRealPosition(int position) {\n        int realPosition = (position - 1) % 4;\n        if (realPosition < 0)\n            realPosition += 4;\n\n        return realPosition;\n    }\n\n    @Override\n    public void onDestroyView() {\n        if (mAutoPlayHandler != null)\n            mAutoPlayHandler.removeMessages(1000);\n        super.onDestroyView();\n    }\n\n\n    @Override\n    public void onRefresh() {\n        index = 0;\n        swipeRefreshListView.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                objects.add(0, \"下拉 = \" + (--index));\n                adapter.notifyDataSetChanged();\n                swipeRefreshListView.setRefreshing(false);\n            }\n        }, 1000);\n    }\n\n    @Override\n    public void onListLoad() {\n        ++index;\n        swipeRefreshListView.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                int count = pagerSize + 10;\n                for (int i = pagerSize; i < count; i++) {\n                    objects.add(\"上拉 = \" + i);\n                }\n                pagerSize = count;\n                adapter.notifyDataSetChanged();\n                swipeRefreshListView.setLoading(false);\n\n                if (index == 1) {\n                    swipeRefreshListView.setLoadCompleted(true);\n                }\n            }\n        }, 1000);\n    }\n\n    @Override\n    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        inflater.inflate(R.menu.menu, menu);\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        objects.clear();\n        adapter.notifyDataSetChanged();\n        return super.onOptionsItemSelected(item);\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        //有head，position-1才是真实item\n        Toast.makeText(getContext(), \"\" + (position - 1), Toast.LENGTH_SHORT).show();\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/RecyclerViewFragment.java",
    "content": "package com.mylhyl.crlayout.sample.app;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuInflater;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport com.mylhyl.crlayout.SwipeRefreshAdapterView;\nimport com.mylhyl.crlayout.SwipeRefreshRecyclerView;\nimport com.mylhyl.crlayout.sample.R;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n\npublic class RecyclerViewFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,\n        SwipeRefreshAdapterView.OnListLoadListener {\n    private SwipeRefreshRecyclerView swipeRefreshRecyclerView;\n    private RecyclerViewAdapter adapter;\n    private List<String> objects = new ArrayList<>();\n    private int index;\n    private int footerIndex = 10;\n\n    public RecyclerViewFragment() {\n    }\n\n    public static RecyclerViewFragment newInstance() {\n        RecyclerViewFragment fragment = new RecyclerViewFragment();\n        return fragment;\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_recycler_view, container, false);\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        swipeRefreshRecyclerView = (SwipeRefreshRecyclerView) view.findViewById(R.id.swipeRefresh);\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        setHasOptionsMenu(true);\n        swipeRefreshRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(),\n                LinearLayoutManager.VERTICAL, false));\n        swipeRefreshRecyclerView.setOnListLoadListener(this);\n        swipeRefreshRecyclerView.setOnRefreshListener(this);\n\n        for (int i = 0; i < footerIndex; i++) {\n            objects.add(\"数据 = \" + i);\n        }\n        adapter = new RecyclerViewAdapter();\n        swipeRefreshRecyclerView.setAdapter(adapter);\n        swipeRefreshRecyclerView.setEmptyText(\"数据又没有了!\");\n    }\n\n\n    @Override\n    public void onRefresh() {\n        index = 0;\n        swipeRefreshRecyclerView.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                objects.add(0, \"下拉 = \" + (--index));\n                adapter.notifyDataSetChanged();\n                swipeRefreshRecyclerView.setRefreshing(false);\n            }\n        }, 1000);\n    }\n\n    @Override\n    public void onListLoad() {\n        ++index;\n//        swipeRefreshRecyclerView.postDelayed(new Runnable() {\n//            @Override\n//            public void run() {\n        int count = footerIndex + 5;\n        for (int i = footerIndex; i < count; i++) {\n            objects.add(\"上拉 = \" + i);\n        }\n        footerIndex = count;\n        adapter.notifyDataSetChanged();\n        swipeRefreshRecyclerView.setLoading(false);\n//                if (index == 1) {\n//                    swipeRefreshRecyclerView.setLoadCompleted(true);\n//                }\n//            }\n//        }, 2000);\n    }\n\n    @Override\n    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        inflater.inflate(R.menu.menu, menu);\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        if (item.getItemId() == R.id.menu) {\n            objects.clear();\n            adapter.notifyDataSetChanged();\n        } else if (item.getItemId() == R.id.menu_reset) {\n            objects.clear();\n            for (int i = 0; i < 5; i++) {\n                objects.add(\"重置数据 = \" + i);\n            }\n            adapter = new RecyclerViewAdapter();\n            swipeRefreshRecyclerView.setAdapter(adapter);\n        }\n        return super.onOptionsItemSelected(item);\n    }\n\n    class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {\n\n        @Override\n        public int getItemCount() {\n            return objects.size();\n        }\n\n        @Override\n        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n            MyViewHolder holder = new MyViewHolder(LayoutInflater.from(\n                    getContext()).inflate(R.layout.fragment_recycler_view_item, parent,\n                    false));\n            return holder;\n        }\n\n        @Override\n        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {\n            ((MyViewHolder) holder).tv.setText(objects.get(position));\n        }\n\n        class MyViewHolder extends RecyclerView.ViewHolder {\n            TextView tv;\n\n            public MyViewHolder(View view) {\n                super(view);\n                tv = (TextView) view.findViewById(android.R.id.text1);\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/app/WebViewFragment.java",
    "content": "package com.mylhyl.crlayout.sample.app;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.webkit.WebView;\nimport android.webkit.WebViewClient;\n\nimport com.mylhyl.crlayout.SwipeRefreshWebView;\nimport com.mylhyl.crlayout.sample.R;\n\n\npublic class WebViewFragment extends Fragment {\n    private SwipeRefreshWebView swipeRefreshWebView;\n\n    public WebViewFragment() {\n    }\n\n    public static WebViewFragment newInstance() {\n        WebViewFragment fragment = new WebViewFragment();\n        return fragment;\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        return inflater.inflate(R.layout.fragment_web_view, container, false);\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        swipeRefreshWebView = (SwipeRefreshWebView) view.findViewById(R.id.swipeRefresh);\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        setHasOptionsMenu(true);\n        swipeRefreshWebView.autoRefresh(R.color.colorPrimary);\n        WebView scrollView = swipeRefreshWebView.getScrollView();\n        scrollView.loadUrl(\"https://github.com/mylhyl\");\n        scrollView.setWebViewClient(new SampleWebViewClient());\n    }\n\n    private class SampleWebViewClient extends WebViewClient {\n        @Override\n        public boolean shouldOverrideUrlLoading(WebView view, String url) {\n            swipeRefreshWebView.autoRefresh();\n            view.loadUrl(url);\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "sample/src/main/java/com/mylhyl/crlayout/sample/widget/MySwipeRefreshGridView.java",
    "content": "package com.mylhyl.crlayout.sample.widget;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\n\nimport com.mylhyl.crlayout.SwipeRefreshGridView;\nimport com.mylhyl.crlayout.sample.R;\n\n/**\n * Created by hupei on 2016/5/16.\n */\npublic class MySwipeRefreshGridView extends SwipeRefreshGridView {\n    public MySwipeRefreshGridView(Context context) {\n        super(context);\n    }\n\n    public MySwipeRefreshGridView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    @Override\n    protected int getLoadLayoutResource() {\n        return R.layout.swipe_refresh_footer;\n    }\n}\n"
  },
  {
    "path": "sample/src/main/res/drawable/footer_progressbar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<animated-rotate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:fromDegrees=\"0\"\n    android:pivotX=\"50%\"\n    android:pivotY=\"50%\"\n    android:toDegrees=\"360\">\n    <shape\n        android:innerRadiusRatio=\"3\"\n        android:shape=\"ring\"\n        android:thicknessRatio=\"8\"\n        android:useLevel=\"false\">\n        <gradient\n            android:centerColor=\"#FF7121\"\n            android:centerY=\"0.50\"\n            android:endColor=\"#FFFF00\"\n            android:startColor=\"#6BD3FF\"\n            android:type=\"sweep\"\n            android:useLevel=\"false\" />\n    </shape>\n</animated-rotate>"
  },
  {
    "path": "sample/src/main/res/drawable/selector_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@android:color/holo_red_light\" android:state_pressed=\"true\" />\n    <item android:drawable=\"@android:color/white\" android:state_pressed=\"false\" />\n</selector>"
  },
  {
    "path": "sample/src/main/res/layout/fragment_grid_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.sample.widget.MySwipeRefreshGridView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:crl=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/swipeRefresh\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:numColumns=\"2\"\n    crl:load_completed_text=\"全部加载完成\"\n    tools:context=\".app.GridViewFragment\" />\n"
  },
  {
    "path": "sample/src/main/res/layout/fragment_list_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.SwipeRefreshListView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:crl=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/swipeRefresh\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"@android:color/darker_gray\"\n    android:listSelector=\"@drawable/selector_list\"\n    crl:load_text=\"数据正在加载中\"\n    crl:empty_text=\"数据呢？\"\n    crl:load_indeterminate_drawable=\"@drawable/footer_progressbar\"\n    tools:context=\".app.ListViewFragment\" />\n"
  },
  {
    "path": "sample/src/main/res/layout/fragment_recycler_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.SwipeRefreshRecyclerView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:crl=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/swipeRefresh\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    crl:load_animator=\"true\"\n    tools:context=\".app.RecyclerViewFragment\">\n\n    <RadioButton\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"right|bottom\"\n        android:layout_marginBottom=\"20dp\"\n        android:layout_marginRight=\"20dp\"\n        android:background=\"@color/colorPrimary\" />\n</com.mylhyl.crlayout.SwipeRefreshRecyclerView>\n"
  },
  {
    "path": "sample/src/main/res/layout/fragment_recycler_view_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v7.widget.CardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"120dp\"\n    android:layout_marginBottom=\"2dp\"\n    android:layout_marginLeft=\"5dp\"\n    android:layout_marginRight=\"5dp\"\n    android:layout_marginTop=\"2dp\"\n    app:cardCornerRadius=\"5dp\"\n    app:elevation=\"1dp\">\n\n    <TextView\n        android:id=\"@android:id/text1\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:gravity=\"left|center_vertical\"\n        android:padding=\"5dp\"\n        android:textSize=\"21sp\" />\n\n</android.support.v7.widget.CardView>"
  },
  {
    "path": "sample/src/main/res/layout/fragment_types.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ListView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/listView\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.mylhyl.crlayout.sample.TypesFragment\" />\n"
  },
  {
    "path": "sample/src/main/res/layout/fragment_web_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.mylhyl.crlayout.SwipeRefreshWebView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/swipeRefresh\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".app.WebViewFragment\" />\n"
  },
  {
    "path": "sample/src/main/res/layout/image_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ImageView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/img_item\"\n    android:layout_width=\"200dp\"\n    android:layout_height=\"200dp\"/>"
  },
  {
    "path": "sample/src/main/res/layout/swipe_refresh_footer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"80dp\"\n    android:background=\"@android:color/holo_red_light\"\n    android:gravity=\"center\"\n    android:padding=\"10dp\">\n\n    <ProgressBar\n        style=\"@android:style/Widget.ProgressBar.Small.Inverse\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:indeterminate=\"true\" />\n\n    <TextView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"xml自定义加载\"\n        android:textAppearance=\"?android:attr/textAppearanceMedium\"\n        android:textColor=\"@android:color/darker_gray\"\n        android:textSize=\"14sp\"\n        android:textStyle=\"bold\" />\n</LinearLayout>"
  },
  {
    "path": "sample/src/main/res/menu/menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:id=\"@+id/menu\"\n        android:showAsAction=\"always\"\n        android:title=\"清空\"/>\n    <item\n        android:id=\"@+id/menu_reset\"\n        android:showAsAction=\"always\"\n        android:title=\"重置\"/>\n</menu>"
  },
  {
    "path": "sample/src/main/res/values/array.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string-array name=\"types\">\n        <item>ListView</item>\n        <item>GridView</item>\n        <item>RecyclerView</item>\n        <item>WebView</item>\n        <item>AppListFragment</item>\n        <item>AppExpandableListFragment</item>\n    </string-array>\n</resources>"
  },
  {
    "path": "sample/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">CommonRefreshLayout</string>\n\n    <!-- TODO: Remove or change this placeholder text -->\n    <string name=\"hello_blank_fragment\">Hello blank fragment</string>\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "sample/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "sample/src/test/java/com/mylhyl/crlayout/sample/ExampleUnitTest.java",
    "content": "package com.mylhyl.crlayout.sample;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "settings.gradle",
    "content": "include ':sample', ':commonrefreshlayout'\n"
  }
]