Skip to content

Commit

Permalink
Fix the bug when clearing item.
Browse files Browse the repository at this point in the history
  • Loading branch information
TellH committed May 11, 2017
1 parent d5441e3 commit 8423bbf
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 41 deletions.
Expand Up @@ -13,13 +13,15 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

import tellh.com.stickyheaderview_rv.adapter.DataBean;
import tellh.com.stickyheaderview_rv.adapter.StickyHeaderViewAdapter;

public class MainActivity extends AppCompatActivity {
private RecyclerView rv;
private StickyHeaderViewAdapter adapter;
private Random random = new Random(System.currentTimeMillis());

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -74,9 +76,11 @@ public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add_view:
User user = new User("Sticky View", 123, "https://avatars.githubusercontent.com/u/15800681?v=3");
user.setShouldSticky(true);
adapter.getDisplayList().add(3, user);
adapter.notifyItemInserted(3);
user.setShouldSticky(random.nextBoolean());
adapter.append(user);
break;
case R.id.action_clear_all:
adapter.clear(rv);
break;
default:
break;
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/menu/menu_main.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="Add Sticky view"
android:id="@+id/action_add_view" />
<item android:title="Add Sticky view" android:id="@+id/action_add_view" />
<item android:title="Clear All" android:id="@+id/action_clear_all" />
</menu>
@@ -0,0 +1,42 @@
package tellh.com.stickyheaderview_rv;

import java.util.EmptyStackException;
import java.util.LinkedList;

/**
* Created by tlh on 2017/5/11 :)
*/

public class LinkListStack<E> {
private LinkedList<E> list = new LinkedList<>();

public E push(E item) {
list.addLast(item);
return item;
}

public E pop() {
if (list.isEmpty())
return null;
return list.removeLast();
}

public synchronized E peek() {
if (list.size() == 0)
throw new EmptyStackException();
return list.peekLast();
}

public boolean isEmpty() {
return list.size() == 0;
}

public void clear() {
list.clear();
}

public boolean remove(E item) {
return list.remove(item);
}

}
Expand Up @@ -11,9 +11,6 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;

import java.util.List;
import java.util.Stack;

import tellh.com.stickyheaderview_rv.adapter.DataBean;
import tellh.com.stickyheaderview_rv.adapter.StickyHeaderViewAdapter;
import tellh.com.stickyheaderview_rv.adapter.ViewBinder;
Expand All @@ -22,14 +19,15 @@
* Created by tlh on 2017/1/21 :)
*/

public class StickyHeaderView extends FrameLayout {
public class StickyHeaderView extends FrameLayout
implements StickyHeaderViewAdapter.DataSetChangeListener {
private boolean hasInit = false;
private FrameLayout mHeaderContainer;
private RecyclerView mRecyclerView;
private int mHeaderHeight = -1;
private StickyHeaderViewAdapter adapter;
private LinearLayoutManager layoutManager;
private Stack<Integer> stickyHeaderPositionStack = new Stack<>();
private LinkListStack<DataBean> stickyHeaderStack = new LinkListStack<>();
private SparseArray<RecyclerView.ViewHolder> mViewHolderCache;

public StickyHeaderView(Context context) {
Expand Down Expand Up @@ -70,6 +68,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
throw new RuntimeException
("Your RecyclerView.Adapter should be the type of StickyHeaderViewAdapter.");
StickyHeaderView.this.adapter = (StickyHeaderViewAdapter) adapter;
StickyHeaderView.this.adapter.setDataSetChangeListener(StickyHeaderView.this);
layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
mViewHolderCache = new SparseArray<>();
} /*else if (mHeaderHeight == 0) {
Expand All @@ -83,17 +82,19 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mHeaderHeight == -1 || adapter == null || layoutManager == null)
return;
List<DataBean> displayList = adapter.getDisplayList();
if (stickyHeaderPositionStack.isEmpty())
stickyHeaderPositionStack.push(findFirstVisibleStickyHeaderPosition(displayList, 0));
if (stickyHeaderStack.isEmpty() && adapter.getDisplayListSize() != 0)
stickyHeaderStack.push(adapter.get(findFirstVisibleStickyHeaderPosition(0)));
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
int firstVisibleStickyHeaderPosition = findFirstVisibleStickyHeaderPosition(displayList, firstVisibleItemPosition);
int currentStickyHeaderPosition = stickyHeaderPositionStack.peek();
if (firstVisibleItemPosition == -1)
return;
int firstVisibleStickyHeaderPosition = findFirstVisibleStickyHeaderPosition(firstVisibleItemPosition);
int currentStickyHeaderPosition = adapter.getPosition(stickyHeaderStack.peek());
if (firstVisibleStickyHeaderPosition - firstVisibleItemPosition > 1) {
return;
}
// 如果两个连续两个都是StickyView, 取下面那个View
if (displayList.get(firstVisibleStickyHeaderPosition + 1).shouldSticky())
DataBean dataBean = adapter.get(firstVisibleStickyHeaderPosition + 1);
if (dataBean != null && dataBean.shouldSticky())
firstVisibleStickyHeaderPosition++;
View firstVisibleStickyHeader = layoutManager.findViewByPosition(firstVisibleStickyHeaderPosition);
if (firstVisibleStickyHeader == null)
Expand All @@ -102,39 +103,38 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (headerTop > 0 && headerTop <= mHeaderHeight) { //吸顶正在更替的状态
mHeaderContainer.setY(-(mHeaderHeight - headerTop));
if (firstVisibleStickyHeaderPosition == currentStickyHeaderPosition) {
stickyHeaderPositionStack.pop();
if (!stickyHeaderPositionStack.isEmpty())
updateHeaderView(stickyHeaderPositionStack.peek());
stickyHeaderStack.pop();
if (!stickyHeaderStack.isEmpty())
updateHeaderView(stickyHeaderStack.peek());
}
} else if (headerTop <= 0) { //吸顶稳定在最上方的状态
mHeaderContainer.setY(0);
updateHeaderView(firstVisibleItemPosition);
updateHeaderView(adapter.get(firstVisibleItemPosition));
}

// Cache the StickyHeader position.
if (firstVisibleStickyHeaderPosition > currentStickyHeaderPosition)
stickyHeaderPositionStack.push(firstVisibleStickyHeaderPosition);
stickyHeaderStack.push(adapter.get(firstVisibleStickyHeaderPosition));
else if (firstVisibleStickyHeaderPosition < currentStickyHeaderPosition)
stickyHeaderPositionStack.pop();
stickyHeaderStack.pop();
}
}

);

}

private int findFirstVisibleStickyHeaderPosition(List<DataBean> displayList, int firstVisibleItemPosition) {
private int findFirstVisibleStickyHeaderPosition(int firstVisibleItemPosition) {
int i = firstVisibleItemPosition;
for (; i < displayList.size(); i++) {
if (!displayList.get(i).shouldSticky())
for (; i < adapter.getDisplayListSize(); i++) {
if (!adapter.get(i).shouldSticky())
continue;
break;
}
return i;
}

private void updateHeaderView(int position) {
DataBean entity = adapter.getDisplayList().get(position);
private void updateHeaderView(DataBean entity) {
int layoutId = entity.getItemLayoutId(adapter);
clearHeaderView();
RecyclerView.ViewHolder viewHolder = mViewHolderCache.get(layoutId);
Expand All @@ -147,9 +147,10 @@ private void updateHeaderView(int position) {
}
mHeaderContainer.addView(viewHolder.itemView);
mHeaderHeight = mHeaderContainer.getHeight();
headerViewBinder.bindView(adapter, viewHolder, position, entity);
headerViewBinder.bindView(adapter, viewHolder, adapter.getPosition(entity), entity);
}

// Remove the Header View
private void clearHeaderView() {
mHeaderContainer.removeAllViews();
}
Expand All @@ -160,4 +161,19 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
super.onLayout(changed, left, top, right, bottom);
}

@Override
public void onClearAll() {
stickyHeaderStack.clear();
clearHeaderView();
}

@Override
public void remove(int pos) {
DataBean entity = adapter.get(pos);
if (stickyHeaderStack.peek() == entity)
clearHeaderView();
if (entity != null && entity.shouldSticky()) {
stickyHeaderStack.remove(entity);
}
}
}
Expand Up @@ -8,13 +8,13 @@
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StickyHeaderViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static int SIZE_VIEW_BINDER_POOL = 10;
private SparseArrayCompat<ViewBinder> viewBinderPool;
protected List<DataBean> displayList;
private DataSetChangeListener onDataSetChangeListener;

public StickyHeaderViewAdapter(List<? extends DataBean> displayList) {
viewBinderPool = new SparseArrayCompat<>(SIZE_VIEW_BINDER_POOL);
Expand All @@ -23,10 +23,24 @@ public StickyHeaderViewAdapter(List<? extends DataBean> displayList) {
this.displayList.addAll(displayList);
}

public List<DataBean> getDisplayList() {
private List<DataBean> getDisplayList() {
return displayList;
}

public int getDisplayListSize() {
return displayList == null ? 0 : displayList.size();
}

public DataBean get(int i) {
if (i < getDisplayListSize())
return displayList.get(i);
else return null;
}

public int getPosition(DataBean dataBean) {
return displayList.indexOf(dataBean);
}

@Override
public int getItemViewType(int position) {
return displayList.get(position).getItemLayoutId(this);
Expand Down Expand Up @@ -69,37 +83,35 @@ public void clearViewBinderCache() {
viewBinderPool.clear();
}

public void addAll(List<? extends DataBean> list) {
public void append(List<? extends DataBean> list) {
if (list == null)
return;
displayList.addAll(list);
notifyDataSetChanged();
}

public void append(DataBean dataBean) {
displayList.add(dataBean);
notifyItemInserted(displayList.size() - 1);
}

public void refresh(List<? extends DataBean> list) {
if (list == null)
return;
onDataSetChangeListener.onClearAll();
displayList.clear();
displayList.addAll(list);
notifyDataSetChanged();
}

public void add(int pos, DataBean item) {
displayList.add(pos, item);
notifyItemInserted(pos);
}

public void delete(int pos) {
onDataSetChangeListener.remove(pos);
displayList.remove(pos);
notifyItemRemoved(pos);
}

public void swap(int fromPosition, int toPosition) {
Collections.swap(displayList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}

public void clear(RecyclerView recyclerView) {
onDataSetChangeListener.onClearAll();
displayList.clear();
notifyDataSetChanged();
recyclerView.scrollToPosition(0);
Expand All @@ -109,4 +121,15 @@ public StickyHeaderViewAdapter RegisterItemType(ViewBinder viewBinder) {
viewBinderPool.put(viewBinder.getItemLayoutId(this), viewBinder);
return this;
}

// Don't Call this Method
public void setDataSetChangeListener(DataSetChangeListener listener) {
this.onDataSetChangeListener = listener;
}

public interface DataSetChangeListener {
void onClearAll();

void remove(int pos);
}
}

0 comments on commit 8423bbf

Please sign in to comment.