1.0.4
修复添加Header后Pinned吸顶闪动一下问题
原因:
由于在代码中获取PinnedView下方的View的position代码这样实现的
/**
* @param c
* @param parent
* @param state
*/
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
createPinnedHeader(parent);
if (mPinnedHeaderView != null) {
// check overlap section view.
//TODO support only vertical header currently.
final int headerEndAt = mPinnedHeaderView.getTop() + mPinnedHeaderView.getHeight() + 1;
final View v = parent.findChildViewUnder(c.getWidth() / 2, headerEndAt);
if (isPinnedView(parent, v)) {
mPinnedHeaderTop = v.getTop() - mPinnedHeaderView.getHeight();
} else {
mPinnedHeaderTop = 0;
}
if (isHeaderView(mFirstVisiblePosition)) {
return;
}
mClipBounds = c.getClipBounds();
mClipBounds.top = mPinnedHeaderTop + mPinnedHeaderView.getHeight();
c.clipRect(mClipBounds);
}
}
在isPinnedView(parent, v)方法里增加了这段操作
private boolean isPinnedView(RecyclerView parent, View v) {
final int position = parent.getChildAdapterPosition(v) - mBuilder.mStickProvider.getHeaderCount();
if (position == RecyclerView.NO_POSITION) {
return false;
}
final int viewType = mBuilder.mStickProvider.getItemViewType(position);
return isPinnedViewType(viewType);
}
那么问题出在这,假设我们添加了2个Header
效果图是这样的,我在activity中获取itemtype这样操作的
@Override
public int getItemViewType(int position) {
if(position<headers.size()){
return SimpleBean.TYPE_HEADER+position;
}
int realPosition=position-headers.size();
SimpleBean simpleBean = mList.get(realPosition);
return simpleBean.getType();
}
一般网上框架也是这么操作的,封装的Adapter都会将position-(header总长度)然后传递给自己的Adapter
而我滑动到这个位置时
final int headerEndAt = mPinnedHeaderView.getTop() + mPinnedHeaderView.getHeight() + 1;
final View v = parent.findChildViewUnder(c.getWidth() / 2, headerEndAt);
final int position = parent.getChildAdapterPosition(v) - mBuilder.mStickProvider.getHeaderCount();
此时这个v所在的position等于4,也就是 i=2 的position
而我们减去header后就等于2然后传递给了我们自己的Adapter,用来获取itemtype
ok,这样导致的问题在于我们自己的Adapter又拿这个2-header总长度,然后就等于0了,
等于0时这个Type返回的getItemViewType等于true
这样就会走上面源码中的if
if (isPinnedView(parent, v)) {
mPinnedHeaderTop = v.getTop() - mPinnedHeaderView.getHeight();
}
所以mPinnedHeaderTop 此时就不等于0了,在下面onDrawOver中就会根据mPinnedHeaderTop 这个值垂直移动canvas,造成了顶部的pinned向上滑动也就是闪动那个问题,而继续滑动到i==2刚好消失时,这个时候传给我们Adapter的position又等于3了,我们减去header总长度后等于1,所以这个时候getItemViewType返回false,就会走上面源码中的else,这样mPinnedHeaderTop 为0,onDrawOver中移动canvas也为0,等于不移动,所以滑动到这个位置时pinned又消失回来了.
else {
mPinnedHeaderTop = 0;
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mPinnedHeaderView != null && !isHeaderView(mFirstVisiblePosition)) {
c.save();
mClipBounds.top = 0;
c.clipRect(mClipBounds, Region.Op.UNION);
c.translate(0, mPinnedHeaderTop);
mPinnedHeaderView.draw(c);
c.restore();
}
}
这个问题分析清楚就好解决啦,把- mBuilder.mStickProvider.getHeaderCount();这段去掉就好了