Skip to content

Commit ecb7ad2

Browse files
committed
Backup point -- The scrolling is smoother after some reading and subclassing
1 parent 7552955 commit ecb7ad2

7 files changed

Lines changed: 446 additions & 199 deletions

File tree

AndroidFilePickerLightLibrary/src/main/java/com/maxieds/androidfilepickerlightlibrary/DisplayAdapters.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ public boolean performNewFileItemClick(DisplayTypes.FileType fileItem) {
142142
}
143143

144144
public static boolean performNewFileItemClick(CheckBox cbView, DisplayTypes.FileType fileItem) {
145+
Log.i(LOGTAG, String.format(Locale.getDefault(), "INIT PERFORM CLICK: (selected, max allowed) = (%d, %d)",
146+
DisplayFragments.getInstance().curSelectionCount, DisplayFragments.getInstance().maxAllowedSelections));
145147
if(cbView == null || fileItem == null) {
146148
return false;
147149
}
@@ -168,6 +170,8 @@ else if(isDir && !DisplayFragments.getInstance().allowSelectFolders) {
168170
DisplayFragments.getInstance().activeSelectionsList.remove(fileItem);
169171
DisplayFragments.getInstance().curSelectionCount--;
170172
Log.i(LOGTAG, "DE-Selected next checkbox (file item)");
173+
Log.i(LOGTAG, String.format(Locale.getDefault(), "RETURNING PERFORM CLICK: (selected, max allowed) = (%d, %d)",
174+
DisplayFragments.getInstance().curSelectionCount, DisplayFragments.getInstance().maxAllowedSelections));
171175
return true;
172176
}
173177
else if(DisplayFragments.getInstance().curSelectionCount >= DisplayFragments.getInstance().maxAllowedSelections) {
@@ -180,6 +184,8 @@ else if(DisplayFragments.getInstance().curSelectionCount >= DisplayFragments.get
180184
DisplayFragments.getInstance().activeSelectionsList.add(fileItem);
181185
DisplayFragments.getInstance().curSelectionCount++;
182186
Log.i(LOGTAG, "Selected next checkbox (file item)");
187+
Log.i(LOGTAG, String.format(Locale.getDefault(), "RETURNING PERFORM CLICK: (selected, max allowed) = (%d, %d)",
188+
DisplayFragments.getInstance().curSelectionCount, DisplayFragments.getInstance().maxAllowedSelections));
183189
return true;
184190
}
185191

AndroidFilePickerLightLibrary/src/main/java/com/maxieds/androidfilepickerlightlibrary/DisplayFragments.java

Lines changed: 12 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ This program (the AndroidFilePickerLight library) is free software written by
2121
import android.content.res.TypedArray;
2222
import android.graphics.Canvas;
2323
import android.graphics.drawable.Drawable;
24+
import android.util.DisplayMetrics;
2425
import android.util.Log;
2526
import android.view.MotionEvent;
2627
import android.view.View;
@@ -35,6 +36,7 @@ This program (the AndroidFilePickerLight library) is free software written by
3536
import androidx.annotation.NonNull;
3637
import androidx.core.view.ViewCompat;
3738
import androidx.recyclerview.widget.LinearLayoutManager;
39+
import androidx.recyclerview.widget.LinearSmoothScroller;
3840
import androidx.recyclerview.widget.RecyclerView;
3941

4042
import java.lang.ref.WeakReference;
@@ -47,7 +49,7 @@ public class DisplayFragments {
4749
private static String LOGTAG = DisplayFragments.class.getSimpleName();
4850

4951
private static DisplayFragments localStaticInst = new DisplayFragments();
50-
private RecyclerView recyclerView = null;
52+
private FileChooserRecyclerView recyclerView = null;
5153

5254
private Drawable folderIconInst;
5355
private Drawable fileIconInst;
@@ -68,7 +70,7 @@ public static RecyclerView getMainRecyclerView() {
6870
return getInstance().recyclerView;
6971
}
7072

71-
public void setRecyclerView(RecyclerView rview) { recyclerView = rview; }
73+
public void setRecyclerView(FileChooserRecyclerView rview) { recyclerView = rview; }
7274

7375
public static DisplayFragments getInstance() { return FileChooserActivity.getInstance().getDisplayFragmentsInstance(); }
7476

@@ -97,16 +99,16 @@ public void setCwdFolderContext(DisplayTypes.DirectoryResultContext nextCwdCtx)
9799
public int findFileItemIndexByLayout(View layoutDisplayView) {
98100
int fileItemIndex = 0;
99101
for(DisplayTypes.FileType fileItem : activeFileItemsDataList) {
100-
if(fileItem.getLayoutContainer() != null && fileItem.getLayoutContainer().equals(layoutDisplayView)) { // ??? TODO: Does this work ???
102+
if(fileItem.getLayoutContainer() != null && fileItem.getLayoutContainer() == layoutDisplayView) { // ??? TODO: Does this work ???
101103
return fileItemIndex;
102104
}
103105
++fileItemIndex;
104106
}
105107
return -1;
106108
}
107109

108-
public static final int SCROLL_QUEUE_BUFFER_SIZE = 8;
109-
public static final int DEFAULT_VIEWPORT_FILE_ITEMS_COUNT = 16 + SCROLL_QUEUE_BUFFER_SIZE; // large enough to overfill the window on first load
110+
public static final int SCROLL_QUEUE_BUFFER_SIZE = 2;
111+
public static final int DEFAULT_VIEWPORT_FILE_ITEMS_COUNT = 16 + SCROLL_QUEUE_BUFFER_SIZE; // set large enough to overfill the window on first load
110112
private int viewportMaxFileItemsCount = DEFAULT_VIEWPORT_FILE_ITEMS_COUNT;
111113
public int fileItemDisplayHeight = 0;
112114

@@ -128,6 +130,7 @@ public void resetViewportMaxFilesCount(View parentViewContainer) {
128130
setViewportMaxFilesCount(SCROLL_QUEUE_BUFFER_SIZE + (int) Math.floor((double) viewportDisplayHeight / fileItemDisplayHeight));
129131
Log.i(LOGTAG, String.format("DELAYED RESPONSE: VP Height = %d, FItemDisp Height = %d ====> %d (with +%d buffer extra)",
130132
viewportDisplayHeight, fileItemDisplayHeight, getViewportMaxFilesCount(), SCROLL_QUEUE_BUFFER_SIZE));
133+
getMainRecyclerView().setItemViewCacheSize(getViewportMaxFilesCount()); // ??? TODO ???
131134
viewportCapacityMesaured = true;
132135
}
133136
}
@@ -150,137 +153,18 @@ public static void updateFolderHistoryPaths(String nextFolderEntryPointPath, boo
150153
}
151154
}
152155

153-
public void initializeRecyclerViewLayout(RecyclerView rview) {
154-
156+
public void initializeRecyclerViewLayout(FileChooserRecyclerView rview) {
155157
if(!recyclerViewAdapterInit) {
158+
rview.setupRecyclerViewLayout(this);
156159
setRecyclerView(rview);
157160
fileItemBasePathsList = new ArrayList<String>();
158161
activeSelectionsList = new ArrayList<DisplayTypes.FileType>();
159162
activeFileItemsDataList = new ArrayList<DisplayTypes.FileType>();
160-
rview.setHasFixedSize(false);
161-
rview.setItemViewCacheSize(0);
162-
rview.setNestedScrollingEnabled(false);
163-
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
164-
ViewGroup.LayoutParams.MATCH_PARENT,
165-
ViewGroup.LayoutParams.WRAP_CONTENT
166-
);
167-
rview.setLayoutParams(layoutParams);
168-
LinearLayoutManager rvLayoutManager = new LinearLayoutManager(FileChooserActivity.getInstance()) {
169-
@Override
170-
public boolean isAutoMeasureEnabled() {
171-
return true;
172-
}
173-
};
174-
rvLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
175-
rvLayoutManager.setAutoMeasureEnabled(true);
176-
rvLayoutManager.setStackFromEnd(true);
177-
rview.setLayoutManager((RecyclerView.LayoutManager) rvLayoutManager);
178-
//rview.addItemDecoration(
179-
// new CustomDividerItemDecoration(R.drawable.rview_file_item_divider)
180-
//);
181163
DisplayAdapters.FileListAdapter rvAdapter = new DisplayAdapters.FileListAdapter(fileItemBasePathsList, activeFileItemsDataList);
182164
rview.setAdapter(rvAdapter);
183165
resetRecyclerViewLayoutContext();
184-
resetRecyclerViewScrollListeners();
185166
recyclerViewAdapterInit = true;
186167
}
187-
188-
}
189-
190-
private void resetRecyclerViewScrollListeners() {
191-
RecyclerView mainFileListRecyclerView = getMainRecyclerView();
192-
mainFileListRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
193-
194-
private static final int SCROLL_BY_ITEMS = SCROLL_QUEUE_BUFFER_SIZE / 2;
195-
boolean haveProcessedInitScroll = false;
196-
197-
private boolean invokeNewDataLoader() {
198-
RecyclerView mainFileListRecyclerView = getMainRecyclerView();
199-
LinearLayoutManager rvLayoutManager = (LinearLayoutManager) mainFileListRecyclerView.getLayoutManager();
200-
BasicFileProvider fpInst = BasicFileProvider.getInstance();
201-
DisplayTypes.DirectoryResultContext cwdFolderContextLocal = getCwdFolderContext();
202-
if(cwdFolderContextLocal == null) {
203-
Log.i(LOGTAG, "invokeNewDataLoader: CWD CONTEXT IS NULL!");
204-
return false;
205-
}
206-
int nextFileItemsLength = getViewportMaxFilesCount();
207-
fpInst.setFilesListLength(SCROLL_BY_ITEMS);
208-
if (rvLayoutManager.findLastCompletelyVisibleItemPosition() >= nextFileItemsLength - 1) {
209-
// Have reached the last item in the list (queue more files below to trigger scrolling):
210-
Log.i(LOGTAG, "onScrollStateChanged: SCROLLING DOWN CASE");
211-
getInstance().lastFileDataEndIndex += SCROLL_BY_ITEMS;
212-
getInstance().lastFileDataStartIndex += SCROLL_BY_ITEMS;
213-
cwdFolderContextLocal.computeDirectoryContents(getInstance().lastFileDataStartIndex, getInstance().lastFileDataEndIndex, SCROLL_BY_ITEMS, 0, SCROLL_BY_ITEMS, true);
214-
displayNextDirectoryFilesList(cwdFolderContextLocal.getWorkingDirectoryContents());
215-
return true;
216-
}
217-
else if (rvLayoutManager.findFirstCompletelyVisibleItemPosition() == 0 &&
218-
fileItemBasePathsList.size() >= nextFileItemsLength) {
219-
// Have reached the first item in the list (queue more files above to trigger scrolling):
220-
Log.i(LOGTAG, "onScrollStateChanged: SCROLLING UP CASE");
221-
if (getInstance().lastFileDataStartIndex == 0) { // cannot scroll more above:
222-
return false;
223-
}
224-
getInstance().lastFileDataStartIndex = Math.max(0, getInstance().lastFileDataStartIndex - SCROLL_BY_ITEMS);
225-
getInstance().lastFileDataEndIndex = Math.max(0, getInstance().lastFileDataEndIndex - SCROLL_BY_ITEMS);
226-
cwdFolderContextLocal.computeDirectoryContents(getInstance().lastFileDataStartIndex, getInstance().lastFileDataEndIndex, 0, SCROLL_BY_ITEMS, -SCROLL_BY_ITEMS, true);
227-
displayNextDirectoryFilesList(cwdFolderContextLocal.getWorkingDirectoryContents());
228-
fpInst.setFilesListLength(getViewportMaxFilesCount());
229-
return true;
230-
}
231-
return false;
232-
}
233-
234-
@Override
235-
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int nextState) {
236-
Log.i(LOGTAG, "onScrollStateChanged");
237-
DisplayTypes.DirectoryResultContext cwdFolderContextLocal = getCwdFolderContext();
238-
if(cwdFolderContextLocal == null) {
239-
Log.i(LOGTAG, "onScrollStateChanged: CWD CONTEXT IS NULL!");
240-
return;
241-
}
242-
BasicFileProvider fpInst = BasicFileProvider.getInstance();
243-
int prevFileItemsLength = getInstance().viewportMaxFileItemsCount;
244-
if(!getInstance().viewportCapacityMesaured && getInstance().getMainRecyclerView().getLayoutManager().getChildCount() != 0) {
245-
fileItemDisplayHeight = getMainRecyclerView().getLayoutManager().getChildAt(0).getMeasuredHeight();
246-
if (fileItemDisplayHeight > 0) {
247-
getInstance().resetViewportMaxFilesCount(FileChooserActivity.getInstance().findViewById(R.id.mainRecyclerViewContainer));
248-
}
249-
}
250-
int indexingByNewSizeDiff = getInstance().viewportMaxFileItemsCount - prevFileItemsLength;
251-
// First, we need to to adjust the working list by any differences in size
252-
// caused by reshaping the viewportsize. This needs to be done as soon as possible
253-
// to prevent odd behaviors when we wait until we should actually perform the
254-
// scrolling operation.
255-
if(indexingByNewSizeDiff != 0) {
256-
Log.i(LOGTAG, "Renormalizing the display size to viewport filling count");
257-
int initTrimFromBackCount = indexingByNewSizeDiff < 0 ? -indexingByNewSizeDiff : 0;
258-
fpInst.setFilesListLength(Math.abs(indexingByNewSizeDiff));
259-
cwdFolderContextLocal.computeDirectoryContents(
260-
getInstance().lastFileDataStartIndex,
261-
Math.min(getInstance().lastFileDataStartIndex, getInstance().lastFileDataEndIndex + indexingByNewSizeDiff),
262-
0, initTrimFromBackCount, Math.abs(indexingByNewSizeDiff), true
263-
);
264-
displayNextDirectoryFilesList(cwdFolderContextLocal.getWorkingDirectoryContents());
265-
}
266-
// Check a corner case to ensure smoother scrolling:
267-
if (nextState == RecyclerView.SCROLL_STATE_SETTLING) {
268-
getMainRecyclerView().stopScroll();
269-
//getMainRecyclerView().stopNestedScroll(ViewCompat.TYPE_TOUCH);
270-
}
271-
invokeNewDataLoader();
272-
}
273-
@Override
274-
public void onScrolled(@NonNull RecyclerView recyclerView, int deltaX, int deltaY) {
275-
/*if(haveProcessedInitScroll) {
276-
invokeNewDataLoader();
277-
}
278-
else {
279-
haveProcessedInitScroll = true;
280-
}*/
281-
super.onScrolled(recyclerView, deltaX, deltaY);
282-
}
283-
});
284168
}
285169

286170
public void resetRecyclerViewLayoutContext() {
@@ -349,85 +233,20 @@ public void displayNextDirectoryFilesList(List<DisplayTypes.FileType> workingDir
349233
if(mainFileListRecyclerView == null) {
350234
return;
351235
}
236+
352237
activeSelectionsList.clear();
353238
activeFileItemsDataList.clear();
354239
fileItemBasePathsList.clear();
355-
LinearLayoutManager rvLayoutManager = (LinearLayoutManager) mainFileListRecyclerView.getLayoutManager();
356-
//rvLayoutManager.removeAllViews();
357-
DisplayAdapters.FileListAdapter rvAdapter = (DisplayAdapters.FileListAdapter) mainFileListRecyclerView.getAdapter();
358240

359241
final List<DisplayTypes.FileType> filteredFileContents = workingDirContentsList;
360242
for(int fidx = 0; fidx < filteredFileContents.size(); fidx++) {
361243
DisplayTypes.FileType fileItem = filteredFileContents.get(fidx);
362244
fileItemBasePathsList.add(fileItem.getBaseName());
363245
activeFileItemsDataList.add(fileItem);
364246
}
365-
//getMainRecyclerView().setAdapter(new DisplayAdapters.FileListAdapter(fileItemBasePathsList, activeFileItemsDataList));
366-
//rvAdapter.notifyDataSetChanged();
247+
DisplayAdapters.FileListAdapter rvAdapter = (DisplayAdapters.FileListAdapter) mainFileListRecyclerView.getAdapter();
367248
rvAdapter.reloadDataSets(fileItemBasePathsList, activeFileItemsDataList);
368-
/*mainFileListRecyclerView.post(new Runnable() {
369-
public void run() {
370-
((DisplayAdapters.FileListAdapter) mainFileListRecyclerView.getAdapter()).reloadDataSets(fileItemBasePathsList, activeFileItemsDataList);
371-
}
372-
});*/
373-
374-
}
375-
376-
public static class CustomDividerItemDecoration extends RecyclerView.ItemDecoration {
377-
378-
private static final int[] DIVIDER_DEFAULT_ATTRS = new int[]{
379-
android.R.attr.listDivider,
380-
android.R.attr.verticalDivider,
381-
android.R.attr.horizontalDivider
382-
};
383-
private Drawable listingsDivider;
384-
385-
public static final int LIST_DIVIDER_STYLE_INDEX = 0;
386-
public static final int DEFAULT_DIVIDER_STYLE_INDEX = 1;
387-
388-
public CustomDividerItemDecoration(Context ctx, int dividerTypeIndex, boolean dividerTypeIsVertical) {
389-
final TypedArray styledDefaultAttributes = ctx.obtainStyledAttributes(DIVIDER_DEFAULT_ATTRS);
390-
if(dividerTypeIndex != LIST_DIVIDER_STYLE_INDEX) {
391-
dividerTypeIndex = DEFAULT_DIVIDER_STYLE_INDEX + (dividerTypeIsVertical ? 0 : 1);
392-
}
393-
listingsDivider = styledDefaultAttributes.getDrawable(dividerTypeIndex);
394-
styledDefaultAttributes.recycle();
395-
}
396249

397-
public CustomDividerItemDecoration(int resId) {
398-
listingsDivider = GradientDrawableFactory.getDrawableFromResource(resId);
399-
}
400-
401-
public static void setMarginAdjustments(int leftAdjust, int topAdjust, int rightAdjust, int bottomAdjust) {
402-
MARGIN_RIGHT_ADJUST = rightAdjust;
403-
MARGIN_LEFT_ADJUST = leftAdjust;
404-
MARGIN_TOP_ADJUST = topAdjust;
405-
MARGIN_BOTTOM_ADJUST = bottomAdjust;
406-
}
407-
408-
private static int MARGIN_RIGHT_ADJUST = 35;
409-
private static int MARGIN_LEFT_ADJUST = 35;
410-
private static int MARGIN_TOP_ADJUST = 0;
411-
private static int MARGIN_BOTTOM_ADJUST = 0;
412-
413-
@Override
414-
public void onDraw(Canvas displayCanvas, RecyclerView parentContainerView, RecyclerView.State rvState) {
415-
416-
int leftMargin = parentContainerView.getPaddingLeft() + MARGIN_LEFT_ADJUST;
417-
int rightMargin = parentContainerView.getWidth() - parentContainerView.getPaddingRight() - MARGIN_RIGHT_ADJUST;
418-
419-
for (int i = 0; i < parentContainerView.getChildCount(); i++) {
420-
421-
View childView = parentContainerView.getChildAt(i);
422-
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) childView.getLayoutParams();
423-
int topMargin = childView.getBottom() + params.bottomMargin + MARGIN_TOP_ADJUST;
424-
int bottomMargin = topMargin + listingsDivider.getIntrinsicHeight() + MARGIN_BOTTOM_ADJUST;
425-
listingsDivider.setBounds(leftMargin, topMargin, rightMargin, bottomMargin);
426-
listingsDivider.draw(displayCanvas);
427-
428-
}
429-
430-
}
431250
}
432251

433252
public static class FileListItemFragment {

AndroidFilePickerLightLibrary/src/main/java/com/maxieds/androidfilepickerlightlibrary/DisplayTypes.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ public void computeDirectoryContents(int startIndexPos, int maxIndexPos,
9797
initMatrixCursorListing.moveToFirst();
9898
boolean appendNewItems = newItemsCount > 0;
9999
List<FileType> filesDataList = new ArrayList<FileType>(directoryContentsList.subList(trimFromFrontCount, directoryContentsList.size() - trimFromBackCount));
100-
int prependInsertIdx = 0;
101-
for (int mcRowIdx = 0; mcRowIdx < Math.min(initMatrixCursorListing.getCount(), Math.abs(newItemsCount)); mcRowIdx++) {
100+
int prependInsertIdx = 0, mcRowIdx;
101+
for (mcRowIdx = 0; mcRowIdx < Math.min(initMatrixCursorListing.getCount(), Math.abs(newItemsCount)); mcRowIdx++) {
102102
String[] filePropertiesList = fpInst.getPropertiesOfCurrentRow(initMatrixCursorListing, !BasicFileProvider.CURSOR_TYPE_IS_ROOT);
103103
String fileAbsPath = filePropertiesList[BasicFileProvider.PROPERTY_ABSPATH];
104104
String fileProviderDocId = filePropertiesList[BasicFileProvider.PROPERTY_FILE_PROVIDER_DOCID];
@@ -117,10 +117,11 @@ public void computeDirectoryContents(int startIndexPos, int maxIndexPos,
117117
initMatrixCursorListing.moveToNext();
118118
}
119119
if(updateGlobalIndices) {
120+
int resultSizeDiff = Math.abs(newItemsCount) - mcRowIdx;
120121
Log.i(LOGTAG, String.format(Locale.getDefault(), "UPDATING GLOBAL INDICES: [%d, %d] -> [%d, %d]", initStartIndexPos,
121122
DisplayFragments.getInstance().lastFileDataEndIndex, initStartIndexPos,
122-
initStartIndexPos + Math.max(0, filesDataList.size() - 1)));
123-
DisplayFragments.getInstance().lastFileDataEndIndex = initStartIndexPos + Math.max(0, filesDataList.size() - 1);
123+
DisplayFragments.getInstance().lastFileDataEndIndex - resultSizeDiff));
124+
DisplayFragments.getInstance().lastFileDataEndIndex = DisplayFragments.getInstance().lastFileDataEndIndex - resultSizeDiff;
124125
}
125126
setNextDirectoryContents(filesDataList);
126127
}

0 commit comments

Comments
 (0)