做瀑布流一般比较好的开源项目有:
StaggeredGridView、AndroidStaggeredGrid和PinterestLikeAdapterView
其中PinterestLikeAdapterView和AndroidStaggeredGrid 都是继承自AbsListView,而StaggeredGridView是直接集成ViewGroup得来的。
在项目中我使用了StaggeredGridView,后来加入Android-PullToRefresh来实现下拉刷新,上拉加载更多,但是发现每次加载更多调用adapter.notifyDataSetChanged()后,瀑布流都跑到position = 0的位置,视图没能在当期位置下。
好了不罗嗦了,下面说下两种解决方式,一种是改变源代码,另一种则是在每次调用notifyDataSetChanged时处理。
(1、)改变源代码,我们找到AdapterDataSetObserver这个地方,大约在2030行左右。
其中代码是
private class AdapterDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
mDataChanged = true;
mItemCount = mAdapter.getCount();
// TODO: Consider matching these back up if we have stable IDs.
mRecycler.clearTransientViews();
if (!mHasStableIds) {
// Clear all layout records and recycle the views
mLayoutRecords.clear();
recycleAllViews();
// Reset item bottoms to be equal to item tops
final int colCount = mColCount;
for (int i = 0; i < colCount; i++) {
mItemBottoms[i] = mItemTops[i];
}
}
// reset list if position does not exist or id for position has changed
if(mFirstPosition > mItemCount-1 || mAdapter.getItemId(mFirstPosition) != mFirstAdapterId){
mFirstPosition = 0;
Arrays.fill(mItemTops, 0);
Arrays.fill(mItemBottoms, 0);
if(mRestoreOffsets!=null)
Arrays.fill(mRestoreOffsets, 0);
}
// TODO: consider repopulating in a deferred runnable instead
// (so that successive changes may still be batched)
requestLayout();
}
@Override
public void onInvalidated() {
}
}
我们做的是把下面这些代码屏蔽掉就可以了
// reset list if position does not exist or id for position has changed
if(mFirstPosition > mItemCount-1 || mAdapter.getItemId(mFirstPosition) != mFirstAdapterId){
mFirstPosition = 0;
Arrays.fill(mItemTops, 0);
Arrays.fill(mItemBottoms, 0);
if(mRestoreOffsets!=null)
Arrays.fill(mRestoreOffsets, 0);
}
(2、)是在每次调用
notifyDataSetChanged做处理,
代码如下:
private Parcelable state;
// state = staggeredGridView.onSaveInstanceState();
adapter.notifyDataSetChanged();
pullToRefreshStaggeredGrid.onRefreshComplete();
// staggeredGridView.onRestoreInstanceState(state);
以上是解决方式,大家如果有更好的可以回复我!