XRecyclerView是一个对recycleview二次封装的框架,不了解的可以查看这篇文章拆解轮子之XRecyclerView,本人使用了下感觉蛮好用的,但是如何实现自动上拉刷新的操作时,由于fragment预加载的问题,会初始化附近的fragment导致没进去这个fragment就会调用这个fragment里面的onCreateView方法导致XRecyclerView设置的自动下拉刷新的操作被提取执行到了,当我们真正点击进去后就看不到这个效果了,时机不对。
先看源码XRecyclerView类
private void init() {
if (pullRefreshEnabled) {
mRefreshHeader = new ArrowRefreshHeader(getContext());
mRefreshHeader.setProgressStyle(mRefreshProgressStyle);
}
LoadingMoreFooter footView = new LoadingMoreFooter(getContext());
footView.setProgressStyle(mLoadingMoreProgressStyle);
mFootView = footView;
mFootView.setVisibility(GONE);
}
在这个初始化方法中我们看到创建出来了下拉刷新头对象mRefreshHeader 并且设置了默认的样式以及脚布局对象及样式,然后我们点进去看ArrowRefreshHeader方法的实现:
private void initView() {
// 初始情况,设置下拉刷新view高度为0
mContainer = (LinearLayout) LayoutInflater.from(getContext()).inflate(
R.layout.listview_header, null);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(0, 0, 0, 0);
this.setLayoutParams(lp);
this.setPadding(0, 0, 0, 0);
addView(mContainer, new LayoutParams(LayoutParams.MATCH_PARENT, 0));
setGravity(Gravity.BOTTOM);
mArrowImageView = (ImageView)findViewById(R.id.listview_header_arrow);
mStatusTextView = (TextView)findViewById(R.id.refresh_status_textview);
//init the progress view
mProgressBar = (SimpleViewSwitcher)findViewById(R.id.listview_header_progressbar);
AVLoadingIndicatorView progressView = new AVLoadingIndicatorView(getContext());
progressView.setIndicatorColor(0xffB5B5B5);
progressView.setIndicatorId(ProgressStyle.BallSpinFadeLoader);
mProgressBar.setView(progressView);
mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateUpAnim.setFillAfter(true);
mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateDownAnim.setFillAfter(true);
mHeaderTimeView = (TextView)findViewById(R.id.last_refresh_time);
measure(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
mMeasuredHeight = getMeasuredHeight();
}
在ArrowRefreshHeader类的构造方法中调用了initView()这个方法来执行初始化,我们看到了倒数第二行进行了手动测试所以下面可以直接获得下拉刷新头的高度,把mMeasuredHeight 定义成一个成员变量。
回到最开始的当我们调用XRecyclerView的setRefreshing(boolean)就可以设置是否自动刷新
public void setRefreshing(boolean refreshing) {
if (refreshing && pullRefreshEnabled && mLoadingListener != null) {
mRefreshHeader.setState(ArrowRefreshHeader.STATE_REFRESHING);
LogUtils.debug("b高度1",mRefreshHeader.getMeasuredHeight()+"");
// mRefreshHeader.onMove(mRefreshHeader.getMeasuredHeight());
mRefreshHeader.onMove(mRefreshHeader.mMeasuredHeight);
mLoadingListener.onRefresh();
}
}
这个时候会调用onmove方法来显示出头部,关键就在这儿,源码采用的是再次测量的方法来获取这个高度,一般情况下的确是没有任何问题的,但是上文我说到的那个情况就不适用了,当初次刷新完成后我们看到会调用到这个方法
private void smoothScrollTo(int destHeight) {
ValueAnimator animator = ValueAnimator.ofInt(getVisibleHeight(), destHeight);
animator.setDuration(300).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
setVisibleHeight((int) animation.getAnimatedValue());
}
});
animator.start();
}
利用值动画将高度慢慢设置成了0,所以导致我们再次测量的时候测量的这个高度也就为0。既然这样那我们如何获得这个高度值呢,上文提到的保存的成员变量mMeasuredHeight 就派上用场了,所以我们按照下面的那种写法就没有问题了。