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