package com.sak.ultilviewlib;
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import com.sak.ultilviewlib.adapter.BaseFooterAdapter;
import com.sak.ultilviewlib.adapter.BaseHeaderAdapter;
import com.sak.ultilviewlib.adapter.InitFooterAdapter;
import com.sak.ultilviewlib.adapter.InitHeaderAdapter;
import com.sak.ultilviewlib.interfaces.OnFooterRefreshListener;
import com.sak.ultilviewlib.interfaces.OnHeaderRefreshListener;
import com.sak.ultilviewlib.util.MeasureTools;
/**
* Created by engineer on 2017/4/19.
*/
public class UltimateRefreshView extends LinearLayout {
private static final String TAG = UltimateRefreshView.class.getSimpleName();
// 刷新时状态
private static final int PULL_TO_REFRESH = 2;
private static final int RELEASE_TO_REFRESH = 3;
private static final int REFRESHING = 4;
// pull state
private static final int PULL_UP_STATE = 0;
private static final int PULL_DOWN_STATE = 1;
private int mPullState;
/**
* list or grid
*/
private AdapterView<?> mAdapterView;
/**
* RecyclerView
*/
private RecyclerView mRecyclerView;
/**
* ScrollView
*/
private ScrollView mScrollView;
/**
* WebView
*/
private WebView mWebView;
//Header
private int mHeaderState;
private View mHeaderView;
private int mHeadViewHeight;
//Footer
private int mFooterState;
private View mFooterView;
private int mFooterViewHeight;
//action
private int lastY;
private BaseHeaderAdapter mBaseHeaderAdapter;
private BaseFooterAdapter mBaseFooterAdapter;
private OnHeaderRefreshListener mOnHeaderRefreshListener;
private OnFooterRefreshListener mOnFooterRefreshListener;
private Context mContext;
public UltimateRefreshView(Context context) {
super(context);
init(context);
}
public UltimateRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public UltimateRefreshView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
//设置为垂直布局,避免每次在xml中修改(LinearLayout 默认为horizontal)
setOrientation(VERTICAL);
mContext = context;
}
public void setBaseHeaderAdapter(BaseHeaderAdapter baseHeaderAdapter) {
mBaseHeaderAdapter = baseHeaderAdapter;
initHeaderView();
initSubViewType();
}
public void setBaseHeaderAdapter() {
mBaseHeaderAdapter = new InitHeaderAdapter(mContext);
initHeaderView();
initSubViewType();
}
public void setBaseFooterAdapter(BaseFooterAdapter baseFooterAdapter) {
mBaseFooterAdapter = baseFooterAdapter;
initFooterView();
}
public void setBaseFooterAdapter() {
mBaseFooterAdapter = new InitFooterAdapter(mContext);
initFooterView();
}
/**
* 计算顶部view 高度,将其隐藏
*/
private void initHeaderView() {
mHeaderView = mBaseHeaderAdapter.getHeaderView();
MeasureTools.measureView(mHeaderView);
mHeadViewHeight = mHeaderView.getMeasuredHeight();
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mHeadViewHeight);
params.topMargin = -mHeadViewHeight;
addView(mHeaderView, 0, params);
}
private void initFooterView() {
mFooterView = mBaseFooterAdapter.getFooterView();
MeasureTools.measureView(mFooterView);
mFooterViewHeight = mFooterView.getMeasuredHeight();
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
mFooterViewHeight);
addView(mFooterView, params);
}
/**
* 确定UltimateRefreshView 内部子视图类型
*/
private void initSubViewType() {
int count = getChildCount();
if (count < 2) {
return;
}
View view = getChildAt(1);
if (view instanceof AdapterView<?>) {
mAdapterView = (AdapterView<?>) view;
}
if (view instanceof RecyclerView) {
mRecyclerView = (RecyclerView) view;
}
if (view instanceof ScrollView) {
mScrollView = (ScrollView) view;
}
if (view instanceof WebView) {
mWebView = (WebView) view;
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int y = (int) ev.getRawY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int deltaY = y - lastY;
if (isParentViewScroll(deltaY)) {
Log.e(TAG, "onInterceptTouchEvent: belong to ParentView");
return true; //此时,触发onTouchEvent事件
}
break;
default:
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
int deltaY = y - lastY;
if (mPullState == PULL_DOWN_STATE) {
Log.e(TAG, "onTouchEvent: pull down begin-->" + deltaY);
initHeaderViewToRefresh(deltaY);
} else if (mPullState == PULL_UP_STATE) {
initFooterViewToRefresh(deltaY);
}
lastY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
int topMargin = getHeaderTopMargin();
Log.e(TAG, "onTouchEvent: topMargin==" + topMargin);
if (mPullState == PULL_DOWN_STATE) {
if (topMargin >= 0) {
headerRefreshing();
} else {
reSetHeaderTopMargin(-mHeadViewHeight);
}
} else if (mPullState == PULL_UP_STATE) {
if (Math.abs(topMargin) >= mHeadViewHeight
+ mFooterViewHeight) {
// 开始执行footer 刷新
footerRefreshing();
} else {
// 还没有执行刷新,重新隐藏
reSetHeaderTopMargin(-mHeadViewHeight);
}
}
break;
}
return super.onTouchEvent(event);
}
private void initHeaderViewToRefresh(int deltaY) {
if (mBaseHeaderAdapter == null) {
return;
}
int topDistance = UpdateHeadViewMarginTop(deltaY);
if (topDistance < 0 && topDistance > -mHeadViewHeight) {
mBaseHeaderAdapter.pullViewToRefresh(deltaY);
mHeaderState = PULL_TO_REFRESH;
} else if (topDistance > 0 && mHeaderState != RELEASE_TO_REFRESH) {
mBaseHeaderAdapter.releaseViewToRefresh(deltaY);
mHeaderState = RELEASE_TO_REFRESH;
}
}
private void initFooterViewToRefresh(int deltaY) {
if (mBaseFooterAdapter == null) {
return;
}
int topDistance = UpdateHeadViewMarginTop(deltaY);
Log.e("zzz", "the distance is " + topDistance);
// 如果header view topMargin 的绝对值大于或等于(header + footer) 四分之一 的高度
// 说明footer view 完全显示出来了,修改footer view 的提示状态
if (Math.abs(topDistance) >= (mHeadViewHeight + mFooterViewHeight)/4
&& mFooterState != RELEASE_TO_REFRESH) {
mBaseFooterAdapter.pullViewToRefresh(deltaY);
mFooterState = RELEASE_TO_REFRESH;
} else if (Math.abs(topDistance) < (mHeadViewHeight + mFooterViewHeight)/4) {
mBaseFooterAdapter.releaseViewToRefresh(deltaY);
mFooterState = PULL_TO_REFRESH;
}
}
private int UpdateHeadViewMarginTop(int deltaY) {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
float topMargin = params.topMargin + deltaY * 0.3f;
params.topMargin = (int) topMargin;
mHeaderView.setLayoutParams(params);
invalidate();
return params.topMargin;
}
private void headerRefreshing() {
if (mBaseHeaderAdapter == null) {
return;
}
mHeaderState = REFRESHING;
setHeaderTopMargin(0);
mBaseHeaderAdapter.headerRefreshing();
if (mOnHeaderRefreshListener != null) {
mOnHeaderRefreshListener.onHeaderRefresh(this);
}
}
private void footerRefreshing() {
if (mBaseFooterAdapter == null) {
return;
}
mFooterState = REFRESHING;
int top = mHeadViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
mBaseFooterAdapter.footerRefreshing();
if (mOnFooterRefreshListener != null) {
mOnFooterRefreshListener.onFooterRefresh(this);
}
}
public void onHeaderRefreshComplete() {
if (mBaseHeaderAdapter == null) {
return;
}
setHeaderTopMargin(-mHeadViewHeight);
mBaseHeaderAdapter.headerRefreshComplete();
mHeaderState = PULL_TO_REFRESH;
}
public void onFooterRefreshComplete() {
if (mBaseFooterAdapter == null) {
return;
}
setHeaderTopMargin(-mHeadViewHeight);
mBaseFooterAdapter.footerRefreshComplete();
mFooterState = PULL_TO_REFRESH;
}
/**
* 滑动由父View(当前View)处理
*
* @param deltaY
* @return
*/
private boolean isParentViewScroll(int deltaY) {
boolean belongToParentView = false;
if (mHeaderState == REFRESHING) {
belongToParentView = false;
}
if (mAdapterView != null) {
if (deltaY > 0) {
View child = mAdapterView.getChildAt(0);
if (child == null) {
belongToParentView = false;
}
if (mAdapterView.getFirstVisiblePosition() == 0 && child.getTop() == 0) {
mPullState = PULL_DOWN_STATE;
belongToParentView = true;
}
} else if (deltaY < 0) {
View lastChild = mAdapterView.getChildAt(mAdapterView
.getChildCount() - 1);
if (lastChild == null) {
// 如果mAdapterView中没有数据,不拦截
belongToParentView = false;
}
// 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,
// 等于父View的高度说明mAdapterView已经滑动到最后
if (lastChild.getBottom() <= getHeight()
&& mAdapterView.getLastVisiblePosition() == mAdapterView
.getCount() - 1) {
mPullState = PULL_UP_STATE;
belongToParentView = true;
}
}
}
if (mRecyclerView != null) {
if (deltaY > 0) {
View child = mRecyclerView.getChildAt(0);
if (child == null) {
belongToParentView = false;
}
LinearLayoutManager mLinearLayoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
int firstPosition = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition();
if (firstPosition == 0) {
mPullState = PULL_DOWN_STATE;
belongToParentView = true;
}
} else if (deltaY < 0) {
View child = mRecyclerView.getChildAt(0);
if (child == null) {
belongToParentView = false;
}
if (mRecyclerView.computeVerticalScrollExtent() + mRecyclerView.computeVerticalScrollOffset()
>= mRecyclerView.computeVerticalScrollRange()){
belongToParentView = true;
mPullState = PULL_UP_STATE;
}else {
belongToParentView = false;
}
}
}
if (mScrollView != null) {
View child = mScrollView.getChildAt(0);
if (deltaY > 0) {
if (child == null) {
belongToParentView = false;
}
int distance = mScrollView.getScrollY();
if (distance == 0) {
mPullState = PULL_DOWN_STATE;
belongToParentView = true;
}
} else if (deltaY < 0
&& child.getMeasuredHeight() <= getHeight()
+ mScrollView.getScrollY()) {
mPullState = PULL_UP_STATE;
belongToParentView = true;
}
}
if (mWebView != null) {
View child = mWebView.getChildAt(0);
if (deltaY > 0) {
if (child == null) {
belongToParentView = false;
}
int distance = mWebView.getScrollY();
if (distance == 0) {
mPullState = PULL_DOWN_STATE;
belongToParentView = true;
}
}
}
return belongToParentView;
}
/**
* 获取当前header view 的topMargin
*
* @return
* @description
*/
private int getHeaderTopMargin() {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
return params.topMargin;
}
/**
* 设置header view 的topMargin的值
*
* @param topMargin ,为0时,说明header view 刚好完全显示出来; 为-mHeaderViewHeight时,说明完全隐藏了
* @description
*/
private void setHeaderTopMargin(int topMargin) {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
params.topMargin = topMargin;
mHeaderView.setLayoutParams(params);
invalidate();
}
/**
* //上拉或下拉至一半时,放弃下来,视为完成一次下拉统一处理,初始化所有内容
*
* @param topMargin
*/
private void reSetHeaderTopMargin(int topMargin) {
if (mBaseHeaderAdapter != null) {
mBaseHeaderAdapter.headerRefreshComplete();
}
if (mBaseFooterAdapter != null) {
mBaseFooterAdapter.footerRefreshComplete();
}
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
params.topMargin = topMargin;
mHeaderView.setLayoutParams(params);
invalidate();
}
public void setOnHeaderRefreshListener(OnHeaderRefreshListener onHeaderRefreshListener) {
mOnHeaderRefreshListener = onHeaderRefreshListener;
}
public void setOnFooterRefreshListener(OnFooterRefreshListener onFooterRefreshListener) {
mOnFooterRefreshListener = onFooterRefreshListener;
}
}