From 0705e697dc0740fd338ae6e36e7b3603e655eafd Mon Sep 17 00:00:00 2001 From: Jonas Kalderstam Date: Tue, 25 Aug 2015 12:59:57 +0200 Subject: [PATCH 1/3] Remove unused string --- library/src/main/res/values/strings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml index f9b3e4dc..dd1cddb9 100644 --- a/library/src/main/res/values/strings.xml +++ b/library/src/main/res/values/strings.xml @@ -16,7 +16,6 @@ --> - NoNonsense File Picker New folder Failed to create folder Name From 7201a2130e7d2a5487ace2193082769d1160a425 Mon Sep 17 00:00:00 2001 From: Jonas Kalderstam Date: Tue, 25 Aug 2015 13:01:38 +0200 Subject: [PATCH 2/3] Make click events overridable. Fixes #48 --- .../AbstractFilePickerFragment.java | 244 +++++++++++++----- 1 file changed, 173 insertions(+), 71 deletions(-) diff --git a/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java b/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java index f4ee72ca..15d4d4d8 100644 --- a/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java +++ b/library/src/main/java/com/nononsenseapps/filepicker/AbstractFilePickerFragment.java @@ -21,6 +21,7 @@ import android.content.Context; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; @@ -108,12 +109,12 @@ protected FileItemAdapter getDummyAdapter() { * arguments bundle in the fragment if it exists so extra arguments will not * be overwritten. This allows you to set any extra arguments in the fragment * constructor if you wish. - * + *

* The key/value-pairs listed below will be overwritten however. * - * @param startPath path to directory the picker will show upon start - * @param mode what is allowed to be selected (dirs, files, both) - * @param allowMultiple selecting a single item or several? + * @param startPath path to directory the picker will show upon start + * @param mode what is allowed to be selected (dirs, files, both) + * @param allowMultiple selecting a single item or several? * @param allowDirCreate can new directories be created? */ public void setArgs(final String startPath, final int mode, @@ -158,9 +159,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, .setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { - if (mListener != null) { - mListener.onCancelled(); - } + onClickCancel(v); } }); @@ -168,34 +167,7 @@ public void onClick(final View v) { .setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { - if (mListener == null) { - return; - } - - // Some invalid cases first - if ((allowMultiple || mode == MODE_FILE) && mCheckedItems.isEmpty()) { - if (mToast == null) { - mToast = Toast.makeText(getActivity(), R.string.nnf_select_something_first, - Toast.LENGTH_SHORT); - } - mToast.show(); - return; - } - - if (allowMultiple) { - mListener.onFilesPicked(toUri(mCheckedItems)); - } else if (mode == MODE_FILE) { - mListener.onFilePicked(toUri(getFirstCheckedItem())); - } else if (mode == MODE_DIR) { - mListener.onFilePicked(toUri(mCurrentPath)); - } else { - // single FILE OR DIR - if (mCheckedItems.isEmpty()) { - mListener.onFilePicked(toUri(mCurrentPath)); - } else { - mListener.onFilePicked(toUri(getFirstCheckedItem())); - } - } + onClickOk(v); } }); @@ -208,6 +180,53 @@ public void onClick(final View v) { return view; } + /** + * Called when the cancel-button is pressed. + * + * @param view which was clicked. Not used in default implementation. + */ + public void onClickCancel(View view) { + if (mListener != null) { + mListener.onCancelled(); + } + } + + /** + * Called when the ok-button is pressed. + * + * @param view which was clicked. Not used in default implementation. + */ + public void onClickOk(View view) { + if (mListener == null) { + return; + } + + // Some invalid cases first + if ((allowMultiple || mode == MODE_FILE) && mCheckedItems.isEmpty()) { + if (mToast == null) { + mToast = Toast.makeText(getActivity(), R.string.nnf_select_something_first, + Toast.LENGTH_SHORT); + } + mToast.show(); + return; + } + + if (allowMultiple) { + mListener.onFilesPicked(toUri(mCheckedItems)); + } else if (mode == MODE_FILE) { + mListener.onFilePicked(toUri(getFirstCheckedItem())); + } else if (mode == MODE_DIR) { + mListener.onFilePicked(toUri(mCurrentPath)); + } else { + // single FILE OR DIR + if (mCheckedItems.isEmpty()) { + mListener.onFilePicked(toUri(mCurrentPath)); + } else { + mListener.onFilePicked(toUri(getFirstCheckedItem())); + } + } + } + /** * Configure the toolbar anyway you like here. Default is to set it as the activity's * main action bar. Override if you already provide an action bar. @@ -276,7 +295,7 @@ public void onCreate(Bundle savedInstanceState) { * and before {@link #onViewStateRestored(Bundle)}. * * @param savedInstanceState If the fragment is being re-created from - * a previous saved state, this is the state. + * a previous saved state, this is the state. */ @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -430,7 +449,7 @@ public void onLoaderReset(final Loader> loader) { /** * @param position 0 - n, where the header has been subtracted - * @param data the actual file or directory + * @param data the actual file or directory * @return an integer greater than 0 */ @Override @@ -475,7 +494,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType /** * @param vh to bind data from either a file or directory * @param position 0 - n, where the header has been subtracted - * @param data the file or directory which this item represents + * @param data the file or directory which this item represents */ @Override public void onBindViewHolder(DirViewHolder vh, int position, T data) { @@ -507,6 +526,116 @@ public void clearSelections() { mCheckedItems.clear(); } + + /** + * Called when a header item ("..") is clicked. + * + * @param view that was clicked. Not used in default implementation. + * @param viewHolder for the clicked view + */ + public void onClickHeader(View view, HeaderViewHolder viewHolder) { + goUp(); + } + + /** + * Browses to the parent directory from the current directory. For example, if the current + * directory is /foo/bar/, then goUp() will change the current directory to /foo/. It is up to + * the caller to not call this in vain, e.g. if you are already at the root. + *

+ * Currently selected items are cleared by this operation. + */ + public void goUp() { + goToDir(getParent(mCurrentPath)); + } + + /** + * Called when a non-selectable item, typically a directory, is clicked. + * + * @param view that was clicked. Not used in default implementation. + * @param viewHolder for the clicked view + */ + public void onClickDir(View view, DirViewHolder viewHolder) { + if (isDir(viewHolder.file)) { + goToDir(viewHolder.file); + } + } + + /** + * Browses to the designated directory. It is up to the caller verify that the argument is + * in fact a directory. + *

+ * Currently selected items are cleared by this operation. + * + * @param file representing the target directory. + */ + public void goToDir(@NonNull T file) { + mCurrentPath = file; + mCheckedItems.clear(); + mCheckedVisibleViewHolders.clear(); + refresh(); + } + + /** + * Long clicking a non-selectable item does nothing by default. + * + * @param view which was long clicked. Not used in default implementation. + * @param viewHolder for the clicked view + * @return true if the callback consumed the long click, false otherwise. + */ + public boolean onLongClickDir(View view, DirViewHolder viewHolder) { + return false; + } + + /** + * Called when a selectable item is clicked. This might be either a file or a directory. + * + * @param view that was clicked. Not used in default implementation. + * @param viewHolder for the clicked view + */ + public void onClickCheckable(View view, CheckableViewHolder viewHolder) { + if (isDir(viewHolder.file)) { + goToDir(viewHolder.file); + } else { + onLongClickCheckable(view, viewHolder); + } + } + + /** + * Long clicking a selectable item should toggle its selected state. Note that if only a + * single item can be selected, then other potentially selected views on screen must be + * de-selected. + * + * @param view which was long clicked. Not used in default implementation. + * @param viewHolder for the clicked view + * @return true if the callback consumed the long click, false otherwise. + */ + public boolean onLongClickCheckable(View view, CheckableViewHolder viewHolder) { + onClickCheckBox(viewHolder); + return true; + } + + /** + * Called when a selectable item's checkbox is pressed. This should toggle its selected state. + * Note that if only a single item can be selected, then other potentially selected views on + * screen must be de-selected. + * + * @param viewHolder for the item containing the checkbox. + */ + public void onClickCheckBox(CheckableViewHolder viewHolder) { + if (mCheckedItems.contains(viewHolder.file)) { + viewHolder.checkbox.setChecked(false); + mCheckedItems.remove(viewHolder.file); + mCheckedVisibleViewHolders.remove(viewHolder); + } else { + if (!allowMultiple) { + clearSelections(); + } + viewHolder.checkbox.setChecked(true); + mCheckedItems.add(viewHolder.file); + mCheckedVisibleViewHolders.add(viewHolder); + } + } + /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated @@ -542,10 +671,7 @@ public HeaderViewHolder(View v) { */ @Override public void onClick(View v) { - mCurrentPath = getParent(mCurrentPath); - mCheckedItems.clear(); - mCheckedVisibleViewHolders.clear(); - refresh(); + onClickHeader(v, this); } } @@ -570,12 +696,7 @@ public DirViewHolder(View v) { */ @Override public void onClick(View v) { - if (isDir(file)) { - mCurrentPath = file; - mCheckedItems.clear(); - mCheckedVisibleViewHolders.clear(); - refresh(); - } + onClickDir(v, this); } /** @@ -586,7 +707,7 @@ public void onClick(View v) { */ @Override public boolean onLongClick(View v) { - return false; + return onLongClickDir(v, this); } } @@ -600,7 +721,7 @@ public CheckableViewHolder(View v) { checkbox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - onLongClick(v); + onClickCheckBox(CheckableViewHolder.this); } }); } @@ -612,14 +733,7 @@ public void onClick(View v) { */ @Override public void onClick(View v) { - if (isDir(file)) { - mCurrentPath = file; - mCheckedItems.clear(); - mCheckedVisibleViewHolders.clear(); - refresh(); - } else { - onLongClick(v); - } + onClickCheckable(v, this); } /** @@ -630,19 +744,7 @@ public void onClick(View v) { */ @Override public boolean onLongClick(View v) { - if (mCheckedItems.contains(file)) { - checkbox.setChecked(false); - mCheckedItems.remove(file); - mCheckedVisibleViewHolders.remove(this); - } else { - if (!allowMultiple) { - clearSelections(); - } - checkbox.setChecked(true); - mCheckedItems.add(file); - mCheckedVisibleViewHolders.add(this); - } - return true; + return onLongClickCheckable(v, this); } } From 3b2f89343b1d1e8a5adc196d8c9b152fd4a89e7a Mon Sep 17 00:00:00 2001 From: Jonas Kalderstam Date: Tue, 25 Aug 2015 13:24:23 +0200 Subject: [PATCH 3/3] Bump version and add release notes --- README.md | 2 +- gradle.properties | 4 ++-- release-notes.md | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 05f45452..37d9555a 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ repositories { } dependencies { - compile 'com.nononsenseapps:filepicker:2.3.1' + compile 'com.nononsenseapps:filepicker:2.4.0' } ``` diff --git a/gradle.properties b/gradle.properties index 5d2535d3..a6ae75b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,8 +17,8 @@ # Project-wide Gradle settings. -VERSION_NAME=2.3.1 -VERSION_CODE=22 +VERSION_NAME=2.4.0 +VERSION_CODE=23 GROUP=com.nononsenseapps PROJECT_NAME=com.nononsenseapps:filepicker diff --git a/release-notes.md b/release-notes.md index 1cebfe05..78937a60 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,3 +1,21 @@ +# 2.4.0 +- Added additional methods in AbstractFilePickerFragment to allow more + customized behavior. All methods have default behavior, but can be augmented + by child classes.: + + goUp, navigates to parent directory. + goToDir, navigates to specified directory. + onClickOK, handles ok button. + onClickCancel, handles cancel button. + onClickHeader, handles clicks on "..". + onClickDir, handles clicks on non-selectable items (usually directories). + onLongClickDir, handles long clicks on non-selectable items. + onClickCheckable, handles clicks on selectable items. + onLongClickCheckable, handles long clicks on selectable items. + onClickCheckBox, handles clicks on the checkbox of selectable items. + + Please see default implementation and docstrings before overriding them. + # 2.3.1 - Library should work correctly with non-touch controls like directional pads or keyboards.