diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/tellh/com/recyclerstickyheaderview/MainActivity.java b/app/src/main/java/tellh/com/recyclerstickyheaderview/MainActivity.java index df14e4d..a7c8f89 100644 --- a/app/src/main/java/tellh/com/recyclerstickyheaderview/MainActivity.java +++ b/app/src/main/java/tellh/com/recyclerstickyheaderview/MainActivity.java @@ -16,8 +16,6 @@ public class MainActivity extends AppCompatActivity { private RecyclerView rv; - private LinearLayoutManager linearLayoutManager; - private StickyHeaderView stickyHeaderView; private StickyHeaderViewAdapter adapter; @Override @@ -58,8 +56,7 @@ public int compare(User o1, User o2) { private void initView() { rv = (RecyclerView) findViewById(R.id.recyclerView); - stickyHeaderView = (StickyHeaderView) findViewById(R.id.stickyHeaderView); - linearLayoutManager = new LinearLayoutManager(this); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); rv.setLayoutManager(linearLayoutManager); } @@ -73,11 +70,10 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_add_view: -// stickyHeaderView.clearHeaderView(); -// stickyHeaderView.updateHeaderView(R.layout.header, entity, position); - break; - case R.id.action_remove_view: - stickyHeaderView.clearHeaderView(); + 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); break; default: break; diff --git a/app/src/main/java/tellh/com/recyclerstickyheaderview/StickyHeaderView.java b/app/src/main/java/tellh/com/recyclerstickyheaderview/StickyHeaderView.java index 052cc93..468f8fd 100644 --- a/app/src/main/java/tellh/com/recyclerstickyheaderview/StickyHeaderView.java +++ b/app/src/main/java/tellh/com/recyclerstickyheaderview/StickyHeaderView.java @@ -5,6 +5,7 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import android.util.LruCache; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -26,6 +27,7 @@ public class StickyHeaderView extends FrameLayout { private StickyHeaderViewAdapter adapter; private LinearLayoutManager layoutManager; private Stack stickyHeaderPositionStack = new Stack<>(); + private LruCache mViewHolderCache; public StickyHeaderView(Context context) { super(context); @@ -53,54 +55,61 @@ private void initView() { mHeaderContainer.setLayoutParams( new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); addView(mHeaderContainer); - mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - if (mHeaderHeight == -1 || mHeaderHeight == 0 || adapter == null || layoutManager == null) { - mHeaderHeight = mHeaderContainer.getHeight(); - adapter = (StickyHeaderViewAdapter) mRecyclerView.getAdapter(); - layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager(); - if (adapter != null) - stickyHeaderPositionStack.push(findFirstVisibleStickyHeaderPosition(adapter.displayList, 0)); - } - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - if (mHeaderHeight == -1 || adapter == null || layoutManager == null) - return; - List displayList = adapter.getDisplayList(); - int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition(); - int firstVisibleStickyHeaderPosition = findFirstVisibleStickyHeaderPosition(displayList, firstVisibleItemPosition); - int currentStickyHeaderPosition = stickyHeaderPositionStack.peek(); - if (firstVisibleStickyHeaderPosition - firstVisibleItemPosition > 1) { - return; - } - View firstVisibleStickyHeader = layoutManager.findViewByPosition(firstVisibleStickyHeaderPosition); - if (firstVisibleStickyHeader == null) - return; - int headerTop = firstVisibleStickyHeader.getTop(); - if (headerTop > 0 && headerTop <= mHeaderHeight) { - mHeaderContainer.setY(-(mHeaderHeight - headerTop)); - if (firstVisibleStickyHeaderPosition == currentStickyHeaderPosition) { - stickyHeaderPositionStack.pop(); - if (!stickyHeaderPositionStack.isEmpty()) - updateHeaderView(stickyHeaderPositionStack.peek()); + mRecyclerView.addOnScrollListener( + new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (mHeaderHeight == -1 || mHeaderHeight == 0 || adapter == null || layoutManager == null) { + mHeaderHeight = mHeaderContainer.getHeight(); + adapter = (StickyHeaderViewAdapter) mRecyclerView.getAdapter(); + layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager(); + if (adapter != null) { + mViewHolderCache = new LruCache<>(adapter.getItemCount() / 3); + } + } } - } else if (headerTop <= 0) { - mHeaderContainer.setY(0); - updateHeaderView(firstVisibleItemPosition); - } - // Cache the StickyHeader position. - if (firstVisibleStickyHeaderPosition > currentStickyHeaderPosition) - stickyHeaderPositionStack.push(firstVisibleStickyHeaderPosition); - else if (firstVisibleStickyHeaderPosition < currentStickyHeaderPosition) - stickyHeaderPositionStack.pop(); + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + if (mHeaderHeight == -1 || adapter == null || layoutManager == null) + return; + List displayList = adapter.getDisplayList(); + if (stickyHeaderPositionStack.isEmpty()) + stickyHeaderPositionStack.push(findFirstVisibleStickyHeaderPosition(adapter.displayList, 0)); + int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition(); + int firstVisibleStickyHeaderPosition = findFirstVisibleStickyHeaderPosition(displayList, firstVisibleItemPosition); + int currentStickyHeaderPosition = stickyHeaderPositionStack.peek(); + if (firstVisibleStickyHeaderPosition - firstVisibleItemPosition > 1) { + return; + } + // 如果两个连续两个都是StickyView, 取下面那个View + if (displayList.get(firstVisibleStickyHeaderPosition + 1).shouldSticky()) + firstVisibleStickyHeaderPosition++; + View firstVisibleStickyHeader = layoutManager.findViewByPosition(firstVisibleStickyHeaderPosition); + if (firstVisibleStickyHeader == null) + return; + int headerTop = firstVisibleStickyHeader.getTop(); + if (headerTop > 0 && headerTop <= mHeaderHeight) { + mHeaderContainer.setY(-(mHeaderHeight - headerTop)); + if (firstVisibleStickyHeaderPosition == currentStickyHeaderPosition) { + stickyHeaderPositionStack.pop(); + if (!stickyHeaderPositionStack.isEmpty()) + updateHeaderView(stickyHeaderPositionStack.peek()); + } + } else if (headerTop <= 0) { + mHeaderContainer.setY(0); + updateHeaderView(firstVisibleItemPosition); + } + + // Cache the StickyHeader position. + if (firstVisibleStickyHeaderPosition > currentStickyHeaderPosition) + stickyHeaderPositionStack.push(firstVisibleStickyHeaderPosition); + else if (firstVisibleStickyHeaderPosition < currentStickyHeaderPosition) + stickyHeaderPositionStack.pop(); + } } - } ); @@ -116,19 +125,24 @@ private int findFirstVisibleStickyHeaderPosition(List displayList, int return i; } - public void updateHeaderView(int position) { + private void updateHeaderView(int position) { DataBean entity = adapter.getDisplayList().get(position); int layoutId = entity.getItemLayoutId(adapter); clearHeaderView(); - View v = LayoutInflater.from(mHeaderContainer.getContext()) - .inflate(layoutId, mHeaderContainer, false); - mHeaderContainer.addView(v); - mHeaderHeight = mHeaderContainer.getHeight(); + RecyclerView.ViewHolder viewHolder = mViewHolderCache.get(layoutId); ViewBinder headerViewBinder = adapter.getViewBinder(layoutId); - headerViewBinder.bindView(adapter, headerViewBinder.provideViewHolder(v), position, entity); + if (viewHolder == null) { + View v = LayoutInflater.from(mHeaderContainer.getContext()) + .inflate(layoutId, mHeaderContainer, false); + viewHolder = headerViewBinder.provideViewHolder(v); + mViewHolderCache.put(layoutId, viewHolder); + } + mHeaderContainer.addView(viewHolder.itemView); + mHeaderHeight = mHeaderContainer.getHeight(); + headerViewBinder.bindView(adapter, viewHolder, position, entity); } - public void clearHeaderView() { + private void clearHeaderView() { mHeaderContainer.removeAllViews(); } diff --git a/app/src/main/java/tellh/com/recyclerstickyheaderview/User.java b/app/src/main/java/tellh/com/recyclerstickyheaderview/User.java index 1514fac..21fe459 100644 --- a/app/src/main/java/tellh/com/recyclerstickyheaderview/User.java +++ b/app/src/main/java/tellh/com/recyclerstickyheaderview/User.java @@ -4,6 +4,16 @@ public class User extends DataBean { private String login; private int id; private String avatar_url; + private boolean shouldSticky; + + public User() { + } + + public User(String login, int id, String avatar_url) { + this.login = login; + this.id = id; + this.avatar_url = avatar_url; + } public String getAvatar_url() { return avatar_url; @@ -34,11 +44,13 @@ public int getItemLayoutId(StickyHeaderViewAdapter adapter) { return R.layout.item_user; } + public void setShouldSticky(boolean shouldSticky) { + this.shouldSticky = shouldSticky; + } + @Override protected boolean shouldSticky() { - if (id == 1269143) - return true; - return super.shouldSticky(); + return shouldSticky; } public static String dataSource = "{\"items\": [\n" + diff --git a/app/src/main/res/layout/header.xml b/app/src/main/res/layout/header.xml index ec3311d..b8df577 100644 --- a/app/src/main/res/layout/header.xml +++ b/app/src/main/res/layout/header.xml @@ -11,5 +11,5 @@ android:layout_height="wrap_content" android:gravity="center" tools:text="H" - android:textSize="20sp" /> + android:textSize="26sp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_user.xml b/app/src/main/res/layout/item_user.xml index 737ad56..0426769 100644 --- a/app/src/main/res/layout/item_user.xml +++ b/app/src/main/res/layout/item_user.xml @@ -16,8 +16,8 @@ diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index d200f89..8b38acb 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -1,9 +1,5 @@ - - - + - \ No newline at end of file