Skip to content

Commit 72b6e3a

Browse files
committed
Keep selection position when calling dataSetChanged
1 parent 1960fbb commit 72b6e3a

File tree

3 files changed

+67
-31
lines changed

3 files changed

+67
-31
lines changed

app/src/main/java/github/hellocsl/gallerylayoutmanager/TestFragment.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import android.view.ViewGroup;
99
import android.widget.Button;
1010
import android.widget.TextView;
11+
import android.widget.Toast;
1112

1213
import java.util.ArrayList;
1314
import java.util.List;
@@ -126,10 +127,15 @@ public void onClick(View view) {
126127
mMainRecycle2.smoothScrollToPosition(selectPosition);
127128
} else {
128129
if (mMainRecycle1.getAdapter() instanceof DemoAdapter) {
129-
((DemoAdapter) mMainRecycle1.getAdapter()).addData();
130+
int result = ((DemoAdapter) mMainRecycle1.getAdapter()).dataChange();
131+
if (result == 1) {
132+
Toast.makeText(getContext(), "add data", Toast.LENGTH_SHORT).show();
133+
} else if (result == -1) {
134+
Toast.makeText(getContext(), "remove data", Toast.LENGTH_SHORT).show();
135+
}
130136
}
131137
if (mMainRecycle2.getAdapter() instanceof DemoAdapter) {
132-
((DemoAdapter) mMainRecycle2.getAdapter()).addData();
138+
((DemoAdapter) mMainRecycle2.getAdapter()).dataChange();
133139
}
134140
}
135141
}

app/src/main/java/github/hellocsl/gallerylayoutmanager/adapter/DemoAdapter.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import android.widget.TextView;
99

1010
import java.util.List;
11+
import java.util.Random;
1112

1213
import github.hellocsl.gallerylayoutmanager.BuildConfig;
1314
import github.hellocsl.gallerylayoutmanager.R;
@@ -43,6 +44,29 @@ public void addData() {
4344
}
4445
}
4546

47+
private static final Random RANDOM = new Random();
48+
49+
public int dataChange() {
50+
int result = 0;
51+
if (mItems != null) {
52+
if (RANDOM.nextBoolean()) {
53+
for (int i = 0; i < 10; i++) {
54+
mItems.add("Extra:" + i);
55+
}
56+
result = 1;
57+
} else {
58+
int size = mItems.size();
59+
int cut = size / 2;
60+
for (int i = size - 1; i > cut; i--) {
61+
mItems.remove(i);
62+
}
63+
result = -1;
64+
}
65+
notifyDataSetChanged();
66+
}
67+
return result;
68+
}
69+
4670
public DemoAdapter setOnItemClickListener(OnItemClickListener onItemClickListener) {
4771
this.mOnItemClickListener = onItemClickListener;
4872
return this;

library/src/main/java/github/hellocsl/layoutmanager/gallery/GalleryLayoutManager.java

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
* Created by chensuilun on 2016/11/18.
2222
*/
2323
public class GalleryLayoutManager extends RecyclerView.LayoutManager implements RecyclerView.SmoothScroller.ScrollVectorProvider {
24-
private static final boolean DEBUG = false;
2524
private static final String TAG = "GalleryLayoutManager";
2625
final static int LAYOUT_START = -1;
2726

@@ -33,7 +32,7 @@ public class GalleryLayoutManager extends RecyclerView.LayoutManager implements
3332

3433
private int mFirstVisiblePosition = 0;
3534
private int mLastVisiblePos = 0;
36-
private int mInitialSelectedPosition = -1;
35+
private int mInitialSelectedPosition = 0;
3736

3837
int mCurSelectedPosition = -1;
3938

@@ -104,7 +103,7 @@ public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
104103

105104
@Override
106105
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
107-
if (DEBUG) {
106+
if (BuildConfig.DEBUG) {
108107
Log.d(TAG, "onLayoutChildren() called with: state = [" + state + "]");
109108
}
110109
if (getItemCount() == 0) {
@@ -124,40 +123,42 @@ public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State
124123
if (getChildCount() == 0 || state.didStructureChange()) {
125124
reset();
126125
}
126+
mInitialSelectedPosition = Math.min(Math.max(0, mInitialSelectedPosition), getItemCount() - 1);
127127
detachAndScrapAttachedViews(recycler);
128128
firstFillCover(recycler, state, 0);
129129
}
130130

131131

132132
private void reset() {
133-
if (DEBUG) {
133+
if (BuildConfig.DEBUG) {
134134
Log.d(TAG, "reset: ");
135135
}
136136
if (mState != null) {
137137
mState.mItemsFrames.clear();
138138
}
139+
if (mCurSelectedPosition != -1) {
140+
mInitialSelectedPosition = mCurSelectedPosition;
141+
} else {
142+
mInitialSelectedPosition = 0;
143+
}
144+
mFirstVisiblePosition = mInitialSelectedPosition;
145+
mLastVisiblePos = mInitialSelectedPosition;
139146
mCurSelectedPosition = -1;
140-
mFirstVisiblePosition = 0;
141147
if (mCurSelectedView != null) {
142148
mCurSelectedView.setSelected(false);
143149
mCurSelectedView = null;
144150
}
145-
mLastVisiblePos = 0;
146151
}
147152

148153

149154
private void firstFillCover(RecyclerView.Recycler recycler, RecyclerView.State state, int scrollDelta) {
150-
if (mInitialSelectedPosition < 0 || mInitialSelectedPosition >= getItemCount()) {
151-
fillCover(recycler, state, scrollDelta);
152-
return;
153-
}
154155
if (mOrientation == HORIZONTAL) {
155156
firstFillWithHorizontal(recycler, state);
156157
} else {
157158
firstFillWithVertical(recycler, state);
158159
}
159160

160-
if (DEBUG) {
161+
if (BuildConfig.DEBUG) {
161162
Log.d(TAG, "firstFillCover finish:first: " + mFirstVisiblePosition + ",last:" + mLastVisiblePos);
162163
}
163164

@@ -210,6 +211,11 @@ private void firstFillWithHorizontal(RecyclerView.Recycler recycler, RecyclerVie
210211
fillRight(recycler, mInitialSelectedPosition + 1, rightStartOffset, rightEdge);
211212
}
212213

214+
@Override
215+
public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
216+
super.onItemsRemoved(recyclerView, positionStart, itemCount);
217+
}
218+
213219
/**
214220
* Layout the item view witch position special by {@link GalleryLayoutManager#mInitialSelectedPosition} first and then layout the other
215221
*
@@ -407,7 +413,7 @@ private float calculateToCenterFraction(View child, float pendingOffset) {
407413
int distance = calculateDistanceCenter(child, pendingOffset);
408414
int childLength = mOrientation == GalleryLayoutManager.HORIZONTAL ? child.getWidth() : child.getHeight();
409415

410-
if (DEBUG) {
416+
if (BuildConfig.DEBUG) {
411417
Log.d(TAG, "calculateToCenterFraction: distance:" + distance + ",childLength:" + childLength);
412418
}
413419
return Math.max(-1.f, Math.min(1.f, distance * 1.f / childLength));
@@ -435,7 +441,7 @@ private int calculateDistanceCenter(View child, float pendingOffset) {
435441
* @param dy
436442
*/
437443
private void fillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State state, int dy) {
438-
if (DEBUG) {
444+
if (BuildConfig.DEBUG) {
439445
Log.d(TAG, "fillWithVertical: dy:" + dy);
440446
}
441447
int topEdge = getOrientationHelper().getStartAfterPadding();
@@ -450,14 +456,14 @@ private void fillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State
450456
for (int i = 0; i < getChildCount(); i++) {
451457
child = getChildAt(i + fixIndex);
452458
if (getDecoratedBottom(child) - dy < topEdge) {
453-
if (DEBUG) {
459+
if (BuildConfig.DEBUG) {
454460
Log.v(TAG, "fillWithVertical: removeAndRecycleView:" + getPosition(child) + ",bottom:" + getDecoratedBottom(child));
455461
}
456462
removeAndRecycleView(child, recycler);
457463
mFirstVisiblePosition++;
458464
fixIndex--;
459465
} else {
460-
if (DEBUG) {
466+
if (BuildConfig.DEBUG) {
461467
Log.d(TAG, "fillWithVertical: break:" + getPosition(child) + ",bottom:" + getDecoratedBottom(child));
462468
}
463469
break;
@@ -468,7 +474,7 @@ private void fillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State
468474
for (int i = getChildCount() - 1; i >= 0; i--) {
469475
child = getChildAt(i);
470476
if (getDecoratedTop(child) - dy > bottomEdge) {
471-
if (DEBUG) {
477+
if (BuildConfig.DEBUG) {
472478
Log.v(TAG, "fillWithVertical: removeAndRecycleView:" + getPosition(child));
473479
}
474480
removeAndRecycleView(child, recycler);
@@ -516,7 +522,7 @@ private void fillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State
516522
layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom);
517523
startOffset = scrapRect.bottom;
518524
mLastVisiblePos = i;
519-
if (DEBUG) {
525+
if (BuildConfig.DEBUG) {
520526
Log.d(TAG, "fillWithVertical: add view:" + i + ",startOffset:" + startOffset + ",mLastVisiblePos:" + mLastVisiblePos + ",bottomEdge" + bottomEdge);
521527
}
522528
}
@@ -555,7 +561,7 @@ private void fillWithVertical(RecyclerView.Recycler recycler, RecyclerView.State
555561
private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.State state, int dx) {
556562
int leftEdge = getOrientationHelper().getStartAfterPadding();
557563
int rightEdge = getOrientationHelper().getEndAfterPadding();
558-
if (DEBUG) {
564+
if (BuildConfig.DEBUG) {
559565
Log.v(TAG, "fillWithHorizontal() called with: dx = [" + dx + "],leftEdge:" + leftEdge + ",rightEdge:" + rightEdge);
560566
}
561567
//1.remove and recycle the view that disappear in screen
@@ -570,7 +576,7 @@ private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.Sta
570576
removeAndRecycleView(child, recycler);
571577
mFirstVisiblePosition++;
572578
fixIndex--;
573-
if (DEBUG) {
579+
if (BuildConfig.DEBUG) {
574580
Log.v(TAG, "fillWithHorizontal:removeAndRecycleView:" + getPosition(child) + " mFirstVisiblePosition change to:" + mFirstVisiblePosition);
575581
}
576582
} else {
@@ -584,7 +590,7 @@ private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.Sta
584590
if (getDecoratedLeft(child) - dx > rightEdge) {
585591
removeAndRecycleView(child, recycler);
586592
mLastVisiblePos--;
587-
if (DEBUG) {
593+
if (BuildConfig.DEBUG) {
588594
Log.v(TAG, "fillWithHorizontal:removeAndRecycleView:" + getPosition(child) + "mLastVisiblePos change to:" + mLastVisiblePos);
589595
}
590596
}
@@ -605,7 +611,7 @@ private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.Sta
605611
View lastView = getChildAt(getChildCount() - 1);
606612
startPosition = getPosition(lastView) + 1; //start layout from next position item
607613
startOffset = getDecoratedRight(lastView);
608-
if (DEBUG) {
614+
if (BuildConfig.DEBUG) {
609615
Log.d(TAG, "fillWithHorizontal:to right startPosition:" + startPosition + ",startOffset:" + startOffset + ",rightEdge:" + rightEdge);
610616
}
611617
}
@@ -631,7 +637,7 @@ private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.Sta
631637
layoutDecorated(scrap, scrapRect.left, scrapRect.top, scrapRect.right, scrapRect.bottom);
632638
startOffset = scrapRect.right;
633639
mLastVisiblePos = i;
634-
if (DEBUG) {
640+
if (BuildConfig.DEBUG) {
635641
Log.d(TAG, "fillWithHorizontal,layout:mLastVisiblePos: " + mLastVisiblePos);
636642
}
637643
}
@@ -641,7 +647,7 @@ private void fillWithHorizontal(RecyclerView.Recycler recycler, RecyclerView.Sta
641647
View firstView = getChildAt(0);
642648
startPosition = getPosition(firstView) - 1; //start layout from previous position item
643649
startOffset = getDecoratedLeft(firstView);
644-
if (DEBUG) {
650+
if (BuildConfig.DEBUG) {
645651
Log.d(TAG, "fillWithHorizontal:to left startPosition:" + startPosition + ",startOffset:" + startOffset + ",leftEdge:" + leftEdge + ",child count:" + getChildCount());
646652
}
647653
}
@@ -760,7 +766,7 @@ public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, Recycler
760766
delta = -Math.min(0, Math.max(dx, ((child.getRight() - child.getLeft()) / 2 + child.getLeft()) - parentCenter));
761767
}
762768
}
763-
if (DEBUG) {
769+
if (BuildConfig.DEBUG) {
764770
Log.d(TAG, "scrollHorizontallyBy: dx:" + dx + ",fixed:" + delta);
765771
}
766772
getState().mScrollDelta = -delta;
@@ -790,7 +796,7 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi
790796
delta = -Math.min(0, Math.max(dy, (getDecoratedBottom(child) - getDecoratedTop(child)) / 2 + getDecoratedTop(child) - parentCenter));
791797
}
792798
}
793-
if (DEBUG) {
799+
if (BuildConfig.DEBUG) {
794800
Log.d(TAG, "scrollVerticallyBy: dy:" + dy + ",fixed:" + delta);
795801
}
796802
getState().mScrollDelta = -delta;
@@ -899,7 +905,7 @@ public void attach(RecyclerView recyclerView, int selectedPosition) {
899905
throw new IllegalArgumentException("The attach RecycleView must not null!!");
900906
}
901907
mRecyclerView = recyclerView;
902-
mInitialSelectedPosition = selectedPosition;
908+
mInitialSelectedPosition = Math.max(0, selectedPosition);
903909
recyclerView.setLayoutManager(this);
904910
mSnapHelper.attachToRecyclerView(recyclerView);
905911
recyclerView.addOnScrollListener(mInnerScrollListener);
@@ -935,7 +941,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
935941
mCurSelectedView.setSelected(true);
936942
mCurSelectedPosition = selectedPosition;
937943
if (!mCallbackInFling && mState != SCROLL_STATE_IDLE) {
938-
if (DEBUG) {
944+
if (BuildConfig.DEBUG) {
939945
Log.v(TAG, "ignore selection change callback when fling ");
940946
}
941947
mCallbackOnIdle = true;
@@ -946,7 +952,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
946952
}
947953
}
948954
}
949-
if (DEBUG) {
955+
if (BuildConfig.DEBUG) {
950956
Log.v(TAG, "onScrolled: dx:" + dx + ",dy:" + dy);
951957
}
952958
}
@@ -955,7 +961,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
955961
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
956962
super.onScrollStateChanged(recyclerView, newState);
957963
mState = newState;
958-
if (DEBUG) {
964+
if (BuildConfig.DEBUG) {
959965
Log.v(TAG, "onScrollStateChanged: " + newState);
960966
}
961967
if (mState == SCROLL_STATE_IDLE) {

0 commit comments

Comments
 (0)