Android仿材料设计实现京东上推隐藏头部
程序员文章站
2022-05-25 08:18:32
...
Android仿材料设计实现京东上推隐藏头部
最近写的一个项目的实现类似于京东商品的展示,不bb先上图
- 动画
- 事件拦截
- 对滑动的监听
动画
我这里是主要是使用了两个动画ObjectAnimator,就是让绿色区域上去,然后让下面的区域上来,注意这里有几点:
1.当我们下面滑动视图的第一个条目没有显示时,不让绿色出来;
2.当绿色的出来时,我们向上滑动滚动视图时就要让绿色上去,滑动区域也上来。
我这里加入了上拉加载和下拉刷新,所以也要注意两点:
1.当滚动试图的第一个条目可见且绿色可见是,下滑的事件给包裹的刷新控件;
2.当滚动的视图的第一个条码不可见且绿色不可见时,下滑的事件还是给滑动控件处理;
这里我使用的滑动控件是RecyclerView,因人而异
布局
注意这里的下拉刷新上拉加载(我的小伙伴使用的02年的一个控件)我吓得眼泪都掉下来了,但是由于是属于app开源sdk多个项目在改,所以我只有在原有基础是改,大家可以使用新的,用过的应该比较清楚。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/rl_title"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@color/color_24cf5f">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="我的积分" />
<TextView
android:id="@+id/tv_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="2.00" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_below="@+id/tv_num"
android:orientation="horizontal"
>
<LinearLayout
android:layout_width="wrap_content"
android:background="@drawable/lb_hslib_shape_integralmall"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:id="@+id/ll_jfcj"
android:layout_marginRight="20dp"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="积分抽奖"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:background="@drawable/lb_hslib_shape_integralmall"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:id="@+id/ll_zqjf"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="赚取积分"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:id="@+id/ll_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:id="@+id/tv_fenlei"
android:text="分类"/>
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:id="@+id/tv_redian"
android:text="热点"/>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<commonlib.view.AbPullToRefreshView
android:id="@+id/act_integramall_ablv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<commonlib.view.HsTopRecyclerView
android:id="@+id/act_integramall_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
<commonlib.view.EmptyLayout
android:id="@+id/act_integramall_error_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_ffffff"
android:visibility="gone" />
</commonlib.view.AbPullToRefreshView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ll_masking"
android:orientation="vertical"
android:visibility="gone"
android:clickable="true"
android:background="#66000000"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
刷新控件
这是那个刷新控件(不需要可以忽略)
public class AbPullToRefreshView extends LinearLayout {
/**
* 日志标记.
*/
private static final String TAG = "AbPullToRefreshView";
/**
* 上下文.
*/
private Context mContext = null;
/**
* 下拉刷新的开关.
*/
private boolean mEnablePullRefresh = true;
/**
* 加载更多的开关.
*/
private boolean mEnableLoadMore = true;
/**
* y上一次保存的.
*/
private int mLastMotionY;
/**
* header view.
*/
private AbListViewHeader mHeaderView;
/**
* footer view.
*/
private AbListViewFooter mFooterView;
/**
* list or grid.
*/
private AdapterView<?> mAdapterView;
/**
* 是否允许在list或grid模式下没有子项时刷新和加载
*/
private boolean mEnablePullAndLoadWithNoChild = true;
/**
* Scrollview.
*/
private ScrollView mScrollView;
/**
* RecyclerView.
*/
private RecyclerView mRecyclerView;
/**
* 对recyclerview上的头部视图的拦截
* 见HsIntegralMallActivity界面
*/
private boolean topVisibility=true;
/**
* header view 高度.
*/
private int mHeaderViewHeight;
/**
* footer view 高度.
*/
private int mFooterViewHeight;
/**
* 滑动状态.
*/
private int mPullState;
/**
* 上滑动作.
*/
private static final int PULL_UP_STATE = 0;
/**
* 下拉动作.
*/
private static final int PULL_DOWN_STATE = 1;
/**
* 上一次的数量.
*/
private int mCount = 0;
/**
* 是否还有数据.
*/
private boolean isAll = false;
/**
* 正在下拉刷新.
*/
public boolean mPullRefreshing = false;
/**
* 正在加载更多.
*/
public boolean mPullLoading = false;
/**
* Footer加载更多监听器.
*/
private OnFooterLoadListener mOnFooterLoadListener;
/**
* Header下拉刷新监听器.
*/
private OnHeaderRefreshListener mOnHeaderRefreshListener;
/**
* 用于控制延时收回Header和Footer
*/
private Timer mTimer;
/**
* UI线程的句柄
*/
private Handler mHandler;
/**
* 构造.
*
* @param context the context
* @param attrs the attrs
*/
public AbPullToRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* 构造.
*
* @param context the context
*/
public AbPullToRefreshView(Context context) {
super(context);
init(context);
}
/**
* 初始化View.
*
* @param context the context
*/
private void init(Context context) {
mContext = context;
mHandler = new Handler(context.getMainLooper());
mTimer = new Timer();
// 增加HeaderView
addHeaderView();
}
/**
* add HeaderView.
*/
private void addHeaderView() {
mHeaderView = new AbListViewHeader(mContext);
mHeaderViewHeight = mHeaderView.getHeaderHeight();
mHeaderView.setGravity(Gravity.BOTTOM);
// mHeaderView.setBackgroundColor(Color.TRANSPARENT);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
mHeaderViewHeight);
// 设置topMargin的值为负的header View高度,即将其隐藏在最上方
params.topMargin = -(mHeaderViewHeight);
addView(mHeaderView, params);
}
/**
* add FooterView.
*/
private void addFooterView() {
mFooterView = new AbListViewFooter(mContext);
mFooterViewHeight = mFooterView.getFooterHeight();
// mFooterView.setBackgroundColor(Color.TRANSPARENT);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
mFooterViewHeight);
addView(mFooterView, params);
}
/**
* 在此添加footer view保证添加到linearlayout中的最后.
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
addFooterView();
initContentAdapterView();
}
/**
* init AdapterView like ListView, GridView and so on; or init ScrollView.
*/
private void initContentAdapterView() {
int count = getChildCount();
if (count < 3) {
throw new IllegalArgumentException(
"this layout must contain 3 child views,and AdapterView or ScrollView must in the second position!");
}
View view = null;
for (int i = 0; i < count - 1; ++i) {
view = getChildAt(i);
if (view instanceof AdapterView<?>) {
mAdapterView = (AdapterView<?>) view;
}
if (view instanceof ScrollView) {
// finish later
mScrollView = (ScrollView) view;
}
if(view instanceof RecyclerView){
mRecyclerView= (RecyclerView) view;
}
}
if (mAdapterView == null && mScrollView == null&&mRecyclerView==null) {
throw new IllegalArgumentException(
"must contain a AdapterView or ScrollView in this layout!");
}
}
/*
* (non-Javadoc)
*
* @see
* android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
int y = (int) e.getRawY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
// 首先拦截down事件,记录y坐标
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
// deltaY > 0 是向下运动,< 0是向上运动
int deltaY = y - mLastMotionY;
if (isRefreshViewScroll(deltaY)) {
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
}
return false;
}
/*
* 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return
* false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由PullToRefreshView自己来处理)
*/
/*
* (non-Javadoc)
*
* @see android.view.View#onTouchEvent(android.view.MotionEvent)
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// onInterceptTouchEvent已经记录 mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
int deltaY = y - mLastMotionY;
if (mPullState == PULL_DOWN_STATE) {
// 执行下拉
headerPrepareToRefresh(deltaY);
} else if (mPullState == PULL_UP_STATE) {
// 执行上拉
footerPrepareToRefresh(deltaY);
}
mLastMotionY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
int topMargin = getHeaderTopMargin();
if (mPullState == PULL_DOWN_STATE) {
if (topMargin >= 0) {
// 开始刷新
headerRefreshing();
} else {
// 还没有执行刷新,重新隐藏
setHeaderTopMargin(-mHeaderViewHeight);
}
} else if (mPullState == PULL_UP_STATE) {
if (Math.abs(topMargin) >= mHeaderViewHeight
+ mFooterViewHeight) {
// 开始执行footer 刷新
footerLoading();
} else {
// 还没有执行刷新,重新隐藏
setHeaderTopMargin(-mHeaderViewHeight);
}
}
break;
}
return super.onTouchEvent(event);
}
/**
* 判断滑动方向,和是否响应事件.
*
* @param deltaY deltaY > 0 是向下运动,< 0是向上运动
* @return true, if is refresh view scroll
*/
private boolean isRefreshViewScroll(int deltaY) {
if (mPullRefreshing || mPullLoading) {
return false;
}
// 对于ListView和GridView
if (mAdapterView != null) {
// 子view(ListView or GridView)滑动到最顶端
if (deltaY > 0) {
// 判断是否禁用下拉刷新操作
if (!mEnablePullRefresh) {
return false;
}
View child = mAdapterView.getChildAt(0);
if (!mEnablePullAndLoadWithNoChild && child == null) {
// 如果mAdapterView中没有数据,不拦截
return false;
}
if (child == null)
child = mAdapterView;
if (mAdapterView.getFirstVisiblePosition() == 0
&& child.getTop() == 0) {
mPullState = PULL_DOWN_STATE;
return true;
}
int top = child.getTop();
int padding = mAdapterView.getPaddingTop();
if (mAdapterView.getFirstVisiblePosition() == 0
&& Math.abs(top - padding) <= 11) {// 这里之前用3可以判断,但现在不行,还没找到原因
mPullState = PULL_DOWN_STATE;
return true;
}
} else if (deltaY < -10) {
// 判断是否禁用上拉加载更多操作
if (!mEnableLoadMore) {
return false;
}
View lastChild = mAdapterView.getChildAt(mAdapterView
.getChildCount() - 1);
if (lastChild == null) {
// 如果mAdapterView中没有数据,不拦截
return false;
}
// 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,
// 等于父View的高度说明mAdapterView已经滑动到最后
if (lastChild.getBottom() <= getHeight()
&& mAdapterView.getLastVisiblePosition() == mAdapterView
.getCount() - 1) {
mPullState = PULL_UP_STATE;
return true;
}
}
}
// 对于ScrollView
if (mScrollView != null) {
// 子scroll view滑动到最顶端
View child = mScrollView.getChildAt(0);
if (deltaY > 0 && mScrollView.getScrollY() == 0) {
mPullState = PULL_DOWN_STATE;
// 判断是否禁用下拉刷新操作
return mEnablePullRefresh;
} else if (deltaY < 0
&& child.getMeasuredHeight() <= getHeight()
+ mScrollView.getScrollY()) {
// 判断是否禁用上拉加载更多操作
if (!mEnableLoadMore) {
return false;
}
mPullState = PULL_UP_STATE;
return true;
}
}
if(mRecyclerView!=null){
LinearLayoutManager manager= (LinearLayoutManager) mRecyclerView.getLayoutManager();
if (deltaY > 0) {
// 判断是否禁用下拉刷新操作
if (!mEnablePullRefresh) {
return false;
}
if(!topVisibility){
return false;
}
View child = mRecyclerView.getChildAt(0);
if (!mEnablePullAndLoadWithNoChild && child == null) {
// 如果mAdapterView中没有数据,不拦截
return false;
}
if (manager.findFirstCompletelyVisibleItemPosition() == 0) {
mPullState = PULL_DOWN_STATE;
return true;
}
}else if (deltaY < -10) {
// 判断是否禁用上拉加载更多操作
if (!mEnableLoadMore) {
return false;
}
View lastChild = mRecyclerView.getChildAt(mRecyclerView
.getChildCount() - 1);
if (lastChild == null) {
// 如果mAdapterView中没有数据,不拦截
return false;
}
if (mRecyclerView.computeVerticalScrollExtent() + mRecyclerView.computeVerticalScrollOffset()
>= mRecyclerView.computeVerticalScrollRange()){
mPullState = PULL_UP_STATE;
return true;
}
}
}
return false;
}
/**
* header 准备刷新,手指移动过程,还没有释放.
*
* @param deltaY 手指滑动的距离
*/
private void headerPrepareToRefresh(int deltaY) {
if (mPullRefreshing || mPullLoading) {
return;
}
int newTopMargin = updateHeaderViewTopMargin(deltaY);
// 当header view的topMargin>=0时,说明header view完全显示出来了 ,修改header view 的提示状态
if (newTopMargin >= 0
&& mHeaderView.getState() != AbListViewHeader.STATE_REFRESHING) {
// 提示松开刷新
mHeaderView.setState(AbListViewHeader.STATE_READY);
} else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {
// 提示下拉刷新
mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
}
}
/**
* footer 准备刷新,手指移动过程,还没有释放 移动footer view高度同样和移动header view
* 高度是一样,都是通过修改header view的topmargin的值来达到.
*
* @param deltaY 手指滑动的距离
*/
private void footerPrepareToRefresh(int deltaY) {
if (mPullRefreshing || mPullLoading) {
return;
}
int newTopMargin = updateHeaderViewTopMargin(deltaY);
// 如果header view topMargin 的绝对值大于或等于header + footer 的高度
// 说明footer view 完全显示出来了,修改footer view 的提示状态
if (Math.abs(newTopMargin) >= (mHeaderViewHeight + mFooterViewHeight)
&& mFooterView.getState() != AbListViewFooter.STATE_LOADING) {
mFooterView.setState(AbListViewFooter.STATE_READY);
} else if (Math.abs(newTopMargin) < (mHeaderViewHeight + mFooterViewHeight)) {
mFooterView.setState(AbListViewFooter.STATE_LOADING);
}
}
/**
* 修改Header view top margin的值.
*
* @param deltaY the delta y
* @return the int
*/
private int updateHeaderViewTopMargin(int deltaY) {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
float newTopMargin = params.topMargin + deltaY * 0.3f;
// 这里对上拉做一下限制,因为当前上拉后然后不释放手指直接下拉,会把下拉刷新给触发了
// 表示如果是在上拉后一段距离,然后直接下拉
if (deltaY > 0 && mPullState == PULL_UP_STATE
&& Math.abs(params.topMargin) <= mHeaderViewHeight) {
return params.topMargin;
}
// 同样地,对下拉做一下限制,避免出现跟上拉操作时一样的bug
if (deltaY < 0 && mPullState == PULL_DOWN_STATE
&& Math.abs(params.topMargin) >= mHeaderViewHeight) {
return params.topMargin;
}
params.topMargin = (int) newTopMargin;
mHeaderView.setLayoutParams(params);
invalidate();
return params.topMargin;
}
/**
* 下拉刷新.
*/
public void headerRefreshing() {
mPullRefreshing = true;
mHeaderView.setState(AbListViewHeader.STATE_REFRESHING);
setHeaderTopMargin(0);
if (mOnHeaderRefreshListener != null) {
// lzd 网络判断
if (AbAppUtil.isNetworkAvailable()) {
mOnHeaderRefreshListener.onHeaderRefresh(this);
} else {
onHeaderRefreshFinish();
ToastUtils.showToast(HstationInstance.C().getString(R.string.lianbi_hslib_netfail_refresh));
}
}
}
/**
* 加载更多.
*/
private void footerLoading() {
mPullLoading = true;
int top = mHeaderViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
if (mOnFooterLoadListener != null) {
// lzd 网络判断
if (AbAppUtil.isNetworkAvailable()) {
mOnFooterLoadListener.onFooterLoad(this);
} else {
onFooterLoadFinish(true);
ToastUtils.showToast(HstationInstance.C().getString(R.string.lianbi_hslib_netfail_refresh));
}
}
}
/**
* 设置header view 的topMargin的值.
*
* @param topMargin the new header top margin
*/
private void setHeaderTopMargin(int topMargin) {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
params.topMargin = topMargin;
mHeaderView.setLayoutParams(params);
invalidate();
}
/**
* header view 完成更新后恢复初始状态.
*/
public void onHeaderRefreshFinish() {
setHeaderTopMargin(-mHeaderViewHeight);
mHeaderView.setState(AbListViewHeader.STATE_READY);
if (mAdapterView != null) {
mCount = mAdapterView.getCount();
// 判断有没有数据
if (mCount > 0) {
mFooterView.setState(AbListViewFooter.STATE_READY);
} else {
mFooterView.setState(AbListViewFooter.STATE_EMPTY);
}
} else {
mFooterView.setState(AbListViewFooter.STATE_READY);
}
mPullRefreshing = false;
}
/**
* footer view 完成更新后恢复初始状态.
*/
public void onFooterLoadFinish() {
setHeaderTopMargin(-mHeaderViewHeight);
mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
if (mAdapterView != null) {
int countNew = mAdapterView.getCount();
// 判断有没有更多数据了
if (countNew > mCount) {
mFooterView.setState(AbListViewFooter.STATE_READY);
mPullLoading = false;
mCount = countNew;
} else {
mFooterView.setState(AbListViewFooter.STATE_NO);
int top = mHeaderViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
setHeaderTopMargin(-mHeaderViewHeight);
isAll = true;
mPullLoading = false;
}
}, 2000);
}
} else {
mFooterView.setState(AbListViewFooter.STATE_READY);
mPullLoading = false;
}
}
/**
* 咨询带广告没有更多数据
*/
public void setNodata(){
mFooterView.setState(AbListViewFooter.STATE_NO);
int top = mHeaderViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
setHeaderTopMargin(-mHeaderViewHeight);
isAll = true;
mPullLoading = false;
}
}, 2000);
}
/**
* footer view 完成更新后恢复初始状态.
*/
public void onFooterLoadFinish(boolean hasnext) {
setHeaderTopMargin(-mHeaderViewHeight);
mHeaderView.setState(AbListViewHeader.STATE_NORMAL);
if (mAdapterView != null && !hasnext) {
int countNew = mAdapterView.getCount();
// 判断有没有更多数据了
if (countNew > mCount) {
mFooterView.setState(AbListViewFooter.STATE_READY);
mPullLoading = false;
mCount = countNew;
} else {
mFooterView.setState(AbListViewFooter.STATE_NO);
int top = mHeaderViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
setHeaderTopMargin(-mHeaderViewHeight);
isAll = true;
mPullLoading = false;
}
}, 2000);
}
} else {
if (!hasnext) {
mFooterView.setState(AbListViewFooter.STATE_NO);
int top = mHeaderViewHeight + mFooterViewHeight;
setHeaderTopMargin(-top);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
setHeaderTopMargin(-mHeaderViewHeight);
isAll = true;
mPullLoading = false;
}
}, 2000);
} else {
mFooterView.setState(AbListViewFooter.STATE_READY);
mPullLoading = false;
}
}
}
/**
* 获取当前header view 的topMargin.
*
* @return the header top margin
*/
private int getHeaderTopMargin() {
LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
return params.topMargin;
}
/**
* 设置下拉刷新的监听器.
*
* @param headerRefreshListener the new on header refresh listener
*/
public void setOnHeaderRefreshListener(
OnHeaderRefreshListener headerRefreshListener) {
mOnHeaderRefreshListener = headerRefreshListener;
}
/**
* 设置加载更多的监听器.
*
* @param footerLoadListener the new on footer load listener
*/
public void setOnFooterLoadListener(OnFooterLoadListener footerLoadListener) {
mOnFooterLoadListener = footerLoadListener;
}
/**
* 打开或者关闭下拉刷新功能.
*
* @param enable 开关标记
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
}
/**
* 打开或者关闭加载更多功能.
*
* @param enable 开关标记
*/
public void setLoadMoreEnable(boolean enable) {
mEnableLoadMore = enable;
}
/**
* 下拉刷新是打开的吗.
*
* @return true, if is enable pull refresh
*/
public boolean isEnablePullRefresh() {
return mEnablePullRefresh;
}
/**
* 加载更多是打开的吗.
*
* @return true, if is enable load more
*/
public boolean isEnableLoadMore() {
return mEnableLoadMore;
}
/**
* 设置是否允许没有子控件时刷新/加载
*
* @param mEnablePullAndLoadWithNoChild
*/
public void setmEnablePullAndLoadWithNoChild(
boolean mEnablePullAndLoadWithNoChild) {
this.mEnablePullAndLoadWithNoChild = mEnablePullAndLoadWithNoChild;
}
/**
* 描述:获取Header View.
*
* @return the header view
*/
public AbListViewHeader getHeaderView() {
return mHeaderView;
}
/**
* 描述:获取Footer View.
*
* @return the footer view
*/
public AbListViewFooter getFooterView() {
return mFooterView;
}
/**
* 描述:获取Header ProgressBar,用于设置自定义样式.
*
* @return the header progress bar
*/
public GifView getHeaderProgressBar() {
return mHeaderView.getHeaderProgressBar();
}
/**
* 描述:获取Footer ProgressBar,用于设置自定义样式.
*
* @return the footer progress bar
*/
public GifView getFooterProgressBar() {
return mFooterView.getFooterProgressBar();
}
public interface OnFooterLoadListener {
/**
* On footer load.
*
* @param view the view
*/
void onFooterLoad(AbPullToRefreshView view);
}
public interface OnHeaderRefreshListener {
/**
* On header refresh.
*
* @param view the view
*/
void onHeaderRefresh(AbPullToRefreshView view);
}
/**
* 对recyclerview上的头部空间可见性的设置
* @param topVisibility
*/
public void setTopVisibility(boolean topVisibility) {
this.topVisibility = topVisibility;
}
}
RecyclerView
public class HsTopRecyclerView extends RecyclerView {
private float mpoint,mcurent;
private TestTouchEvent testTouchEvent;
public void setTestTouchEvent(TestTouchEvent testTouchEvent) {
this.testTouchEvent = testTouchEvent;
}
public HsTopRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
switch (e.getAction()){
case MotionEvent.ACTION_DOWN:
mpoint=e.getRawY();
break;
case MotionEvent.ACTION_MOVE:
mcurent=e.getRawY();
if(mcurent-mpoint>4){
if(testTouchEvent!=null){
testTouchEvent.event(true);
}
}else {
if(testTouchEvent!=null){
testTouchEvent.event(false);
}
}
break;
}
return super.onTouchEvent(e);
}
public interface TestTouchEvent{
void event(boolean isDown);
}
}
Activity
由于有封装,请*发挥
public class HsIntegralMallActivity extends BaseActivity {
private AbPullToRefreshView mAddPlatformAblv;
private HsTopRecyclerView recyclerView;
private RecyclerView popu_recyclerview;
private EmptyLayout emptyLayout;
private RelativeLayout relativeLayout;
private HsIntegralMallAdapter adapter;
private LinearLayout ll_content, popu_ll_content, ll_masking,ll_zqjf,ll_jfcj;
private ObjectAnimator animatorGone, animatorShow, animatorUp, animatorDown;
private boolean visibility = true;
private ViewTreeObserver vto;
private GridLayoutManager layoutManager;
private int wheight, statusBarHeight1, height;
private PopupWindow popupWindow;
private TextView tv_fenlei, tv_redian, tv_title;
private ArrayList<String> listTest;
private HsEasyRecyclerAdapterHs<String> popu_adapter;
private boolean sortClick = false, classClick = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lb_hslib_integramall_activity);
initView();
initEvent();
initData();
initData(true);
initPopuWindow();
}
/**
* 初始化控件
*/
private void initView() {
mAddPlatformAblv = findView(R.id.act_integramall_ablv);
recyclerView = findView(R.id.act_integramall_recyclerview);
emptyLayout = findView(R.id.act_integramall_error_layout);
relativeLayout = findView(R.id.rl_title);
ll_content = findView(R.id.ll_content);
tv_fenlei = findView(R.id.tv_fenlei);
tv_redian = findView(R.id.tv_redian);
tv_title = findView(R.id.tv_title);
ll_masking = findView(R.id.ll_masking);
ll_zqjf=findView(R.id.ll_zqjf);
ll_jfcj=findView(R.id.ll_jfcj);
}
/**
* 初始化监听
*/
private void initEvent() {
mAddPlatformAblv.setOnHeaderRefreshListener(new AbPullToRefreshView.OnHeaderRefreshListener() {
@Override
public void onHeaderRefresh(AbPullToRefreshView view) {
initData(true);
}
});
mAddPlatformAblv.setOnFooterLoadListener(new AbPullToRefreshView.OnFooterLoadListener() {
@Override
public void onFooterLoad(AbPullToRefreshView view) {
initData(false);
}
});
vto = relativeLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
relativeLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
height = relativeLayout.getHeight();
initAnimator(relativeLayout, ll_content);
}
});
WindowManager wm = this.getWindowManager();
wheight = wm.getDefaultDisplay().getHeight();
statusBarHeight1 = -1;
//获取status_bar_height资源的ID
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
//根据资源ID获取响应的尺寸值
statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);
}
mAddPlatformAblv.setLoadMoreEnable(true);
mAddPlatformAblv.setPullRefreshEnable(true);
recyclerView.setTestTouchEvent(new HsTopRecyclerView.TestTouchEvent() {
@Override
public void event(boolean isDown) {
if (isDown && layoutManager.findFirstCompletelyVisibleItemPosition() == 0 && !visibility) {
if (!animatorShow.isRunning() && !animatorDown.isRunning() && !animatorGone.isRunning() && !animatorUp.isRunning()) {
animatorShow.start();
animatorDown.start();
}
} else if (!isDown && visibility && !animatorGone.isRunning() && !animatorUp.isRunning() && !animatorShow.isRunning() && !animatorDown.isRunning()) {
animatorGone.start();
animatorUp.start();
}
}
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
//不可以下滚
if (!recyclerView.canScrollVertically(-1) && !visibility) {
animatorShow.start();
animatorDown.start();
}
}
}
});
tv_fenlei.setOnClickListener(this);
tv_redian.setOnClickListener(this);
ll_masking.setOnClickListener(this);
tv_title.setOnClickListener(this);
ll_zqjf.setOnClickListener(this);
ll_jfcj.setOnClickListener(this);
}
@Override
protected void onChildClick(View view) {
super.onChildClick(view);
Intent intent;
if (view == tv_fenlei) {
if (classClick) {
popupWindow.dismiss();
classClick=false;
}else {
if (popupWindow.isShowing()) {
initPopuData(0);
sortClick=false;
}
if (!popupWindow.isShowing()) {
initPopuData(0);
popupWindow.showAsDropDown(view);
ll_masking.setVisibility(View.VISIBLE);
}
classClick=true;
}
} else if (view == tv_redian) {
if(sortClick){
popupWindow.dismiss();
sortClick=false;
}else {
if (popupWindow.isShowing()) {
initPopuData(1);
classClick=false;
}
if (!popupWindow.isShowing()) {
initPopuData(1);
popupWindow.showAsDropDown(view);
ll_masking.setVisibility(View.VISIBLE);
}
sortClick=true;
}
} else if (view == ll_masking) {
popupWindow.dismiss();
} else if (view == tv_title) {
intent=new Intent();
intent.setClass(getWeakContext(),HsWinningRecordingActivity.class);
startActivity(intent);
}else if(view==ll_zqjf){
intent=new Intent();
intent.setClass(getWeakContext(),HsGetIntegralActivity.class);
startActivity(intent);
}else if(view==ll_jfcj){
intent=new Intent();
intent.setClass(getWeakContext(),HsLotteryWebActivity.class);
startActivity(intent);
}
}
/**
* 初始化动画
*
* @param rl
* @param ll
*/
public void initAnimator(RelativeLayout rl, LinearLayout ll) {
animatorGone = ObjectAnimator.ofFloat(rl, "translationY", 0, -height);
animatorGone.setDuration(200);
animatorShow = ObjectAnimator.ofFloat(rl, "translationY", -height, 0);
animatorShow.setDuration(200);
animatorUp = ObjectAnimator.ofFloat(ll, "translationY", 0, -height);
animatorUp.setDuration(200);
animatorDown = ObjectAnimator.ofFloat(ll, "translationY", -height, 0);
animatorDown.setDuration(200);
Animator.AnimatorListener listener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
visibility = !visibility;
mAddPlatformAblv.setTopVisibility(visibility);
if (visibility) {
layoutManager.scrollToPositionWithOffset(0, 0);
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
};
animatorShow.addListener(listener);
animatorGone.addListener(listener);
}
/**
* 初始化数据
*/
private void initData() {
ll_content.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, wheight - ScreenUtils.dp2px(getWeakContext(), 48) - statusBarHeight1));
recyclerView.setLayoutManager(layoutManager = new GridLayoutManager(getWeakContext(), 2));
adapter = new HsIntegralMallAdapter(getWeakContext());
popu_adapter = new HsEasyRecyclerAdapterHs<String>(getWeakContext(), R.layout.lb_hslib_integrapopuwindow_item) {
TextView poputv_title;
@Override
public void onBind(HsBaseViewHolder holder, int position) {
poputv_title = holder.get(R.id.tv_content);
poputv_title.setText(get(position));
System.out.println("初始化了");
poputv_title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (popupWindow.isShowing()) {
popupWindow.dismiss();
Toast.makeText(getWeakContext(), "点击了", Toast.LENGTH_SHORT).show();
}
}
});
}
};
recyclerView.setAdapter(adapter);
}
/**
* 下载
*
* @param isRefresh
*/
private void initData(boolean isRefresh) {
ArrayList<Records> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(new Records());
}
adapter.addAll(list);
AbPullHide.hideRefreshView(isRefresh, mAddPlatformAblv);
}
/**
* 初始化弹窗
*/
private void initPopuWindow() {
View view = LayoutInflater.from(getWeakContext()).inflate(R.layout.lb_hslib_integrallmall_popu_layout, null);
popu_recyclerview = (RecyclerView) view.findViewById(R.id.rv);
popu_recyclerview.setLayoutManager(new LinearLayoutManager(getWeakContext()));
popu_recyclerview.setAdapter(popu_adapter);
popu_ll_content = (LinearLayout) view.findViewById(R.id.ll_content);
popupWindow = new PopupWindow(view, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(new ColorDrawable(0xffffffff));
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
ll_masking.setVisibility(View.GONE);
sortClick=false;
classClick=false;
}
});
}
/**
* 初始化弹窗数据
*/
private void initPopuData(int type) {
listTest = new ArrayList<>();
popu_adapter.clear();
switch (type) {
case 0:
for (int i = 0; i < 7; i++) {
listTest.add("测试" + i);
}
popu_adapter.addAll(listTest);
if (listTest.size() > 6) {
popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 300));
} else {
popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
break;
case 1:
for (int i = 0; i < 2; i++) {
listTest.add("测试" + i);
}
popu_adapter.addAll(listTest);
if (listTest.size() > 6) {
popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 300));
} else {
popu_ll_content.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
break;
}
}
}
事件拦截
主要就是对数据以及是否第一个条码可见来判断
if(mRecyclerView!=null){
LinearLayoutManager manager= (LinearLayoutManager) mRecyclerView.getLayoutManager();
if (deltaY > 0) {
// 判断是否禁用下拉刷新操作
if (!mEnablePullRefresh) {
return false;
}
if(!topVisibility){
return false;
}
View child = mRecyclerView.getChildAt(0);
if (!mEnablePullAndLoadWithNoChild && child == null) {
// 如果mAdapterView中没有数据,不拦截
return false;
}
if (manager.findFirstCompletelyVisibleItemPosition() == 0) {
mPullState = PULL_DOWN_STATE;
return true;
}
}else if (deltaY < -10) {
// 判断是否禁用上拉加载更多操作
if (!mEnableLoadMore) {
return false;
}
View lastChild = mRecyclerView.getChildAt(mRecyclerView
.getChildCount() - 1);
if (lastChild == null) {
// 如果mAdapterView中没有数据,不拦截
return false;
}
if (mRecyclerView.computeVerticalScrollExtent() + mRecyclerView.computeVerticalScrollOffset()
>= mRecyclerView.computeVerticalScrollRange()){
mPullState = PULL_UP_STATE;
return true;
}
}
对滑动的监听
recyclerView.setTestTouchEvent(new HsTopRecyclerView.TestTouchEvent() {
@Override
public void event(boolean isDown) {
if (isDown && layoutManager.findFirstCompletelyVisibleItemPosition() == 0 && !visibility) {
if (!animatorShow.isRunning() && !animatorDown.isRunning() && !animatorGone.isRunning() && !animatorUp.isRunning()) {
animatorShow.start();
animatorDown.start();
}
} else if (!isDown && visibility && !animatorGone.isRunning() && !animatorUp.isRunning() && !animatorShow.isRunning() && !animatorDown.isRunning()) {
animatorGone.start();
animatorUp.start();
}
}
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
//不可以下滚
if (!recyclerView.canScrollVertically(-1) && !visibility) {
animatorShow.start();
animatorDown.start();
}
}
}
});
效果在最上面,抠脚来的不喜勿喷