Skip to content
This repository was archived by the owner on Mar 9, 2022. It is now read-only.

Commit 4c2c0e1

Browse files
committed
Add cancel button feature
1 parent be656a1 commit 4c2c0e1

File tree

22 files changed

+512
-139
lines changed

22 files changed

+512
-139
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/demo/.idea
2+
/demo/.gradle
23
/demo/build
34
/demo/local.properties
45
/demo/aFileDialog/build
56
/demo/aFileDialogTesting/build
67

78
/library/.idea
9+
/library/.gradle
810
/library/build
911
/library/local.properties
1012
/library/app/build

demo/aFileDialog/aFileDialog.iml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
1313
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
1414
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
15-
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
1615
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
1716
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
18-
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
17+
<afterSyncTasks>
18+
<task>generateDebugAndroidTestSources</task>
19+
<task>generateDebugSources</task>
20+
</afterSyncTasks>
1921
<option name="ALLOW_USER_CONFIGURATION" value="false" />
2022
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
2123
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@@ -25,7 +27,7 @@
2527
</configuration>
2628
</facet>
2729
</component>
28-
<component name="NewModuleRootManager" inherit-compiler-output="false">
30+
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
2931
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
3032
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
3133
<exclude-output />

demo/aFileDialog/src/main/java/ar/com/daidalos/afiledialog/FileChooserActivity.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,13 @@ public class FileChooserActivity extends Activity implements FileChooser {
7070
* a boolean that indicates if the user can create files.
7171
*/
7272
public static final String INPUT_CAN_CREATE_FILES = "input_can_create_files";
73-
73+
74+
/**
75+
* Constant used for represent the key of the bundle object (inside the start's intent) which contains
76+
* a boolean that indicates if the cancel button must be show.
77+
*/
78+
public static final String INPUT_SHOW_CANCEL_BUTTON = "input_show_cancel_button";
79+
7480
/**
7581
* Constant used for represent the key of the bundle object (inside the start's intent) which contains
7682
* a regular expression which is going to be used as a filter to determine which files can be selected.
@@ -160,6 +166,7 @@ public void onCreate(Bundle savedInstanceState) {
160166
if(extras.containsKey(INPUT_CAN_CREATE_FILES)) core.setCanCreateFiles(extras.getBoolean(INPUT_CAN_CREATE_FILES));
161167
if(extras.containsKey(INPUT_LABELS)) core.setLabels((FileChooserLabels) extras.get(INPUT_LABELS));
162168
if(extras.containsKey(INPUT_SHOW_CONFIRMATION_ON_CREATE)) core.setShowConfirmationOnCreate(extras.getBoolean(INPUT_SHOW_CONFIRMATION_ON_CREATE));
169+
if(extras.containsKey(INPUT_SHOW_CANCEL_BUTTON)) core.setShowCancelButton(extras.getBoolean(INPUT_SHOW_CANCEL_BUTTON));
163170
if(extras.containsKey(INPUT_SHOW_CONFIRMATION_ON_SELECT)) core.setShowConfirmationOnSelect(extras.getBoolean(INPUT_SHOW_CONFIRMATION_ON_SELECT));
164171
if(extras.containsKey(INPUT_SHOW_FULL_PATH_IN_TITLE)) core.setShowFullPathInTitle(extras.getBoolean(INPUT_SHOW_FULL_PATH_IN_TITLE));
165172
if(extras.containsKey(INPUT_USE_BACK_BUTTON_TO_NAVIGATE)) this.useBackButton = extras.getBoolean(INPUT_USE_BACK_BUTTON_TO_NAVIGATE);
@@ -193,6 +200,14 @@ public void onFileSelected(File file) {
193200
finish();
194201
}
195202
});
203+
204+
// Add a listener for when the cancel button is pressed.
205+
core.addListener(new FileChooserCore.OnCancelListener() {
206+
public void onCancel() {
207+
// Close activity.
208+
FileChooserActivity.super.onBackPressed();
209+
}
210+
});
196211
}
197212

198213
/** Called when the user push the 'back' button. */

demo/aFileDialog/src/main/java/ar/com/daidalos/afiledialog/FileChooserCore.java

Lines changed: 117 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,13 @@ class FileChooserCore {
5151
/**
5252
* The listeners for the event of select a file.
5353
*/
54-
private List<OnFileSelectedListener> listeners;
55-
54+
private List<OnFileSelectedListener> fileSelectedListeners;
55+
56+
/**
57+
* The listeners for the event of select a file.
58+
*/
59+
private List<OnCancelListener> cancelListeners;
60+
5661
/**
5762
* A regular expression for filter the files.
5863
*/
@@ -72,7 +77,12 @@ class FileChooserCore {
7277
* A boolean indicating if the chooser is going to be used to select folders.
7378
*/
7479
private boolean folderMode;
75-
80+
81+
/**
82+
* A boolean indicating if the chooser is going to be used to select folders.
83+
*/
84+
private boolean showCancelButton;
85+
7686
/**
7787
* A file that indicates the folder that is currently being displayed.
7888
*/
@@ -122,7 +132,8 @@ class FileChooserCore {
122132
public FileChooserCore(FileChooser fileChooser) {
123133
// Initialize attributes.
124134
this.chooser = fileChooser;
125-
this.listeners = new LinkedList<OnFileSelectedListener>();
135+
this.fileSelectedListeners = new LinkedList<OnFileSelectedListener>();
136+
this.cancelListeners = new LinkedList<OnCancelListener>();
126137
this.filter = null;
127138
this.showOnlySelectable = false;
128139
this.setCanCreateFiles(false);
@@ -132,13 +143,16 @@ public FileChooserCore(FileChooser fileChooser) {
132143
this.showConfirmationOnCreate = false;
133144
this.showConfirmationOnSelect = false;
134145
this.showFullPathInTitle = false;
135-
136-
// Add listener for the buttons.
146+
this.showCancelButton = false;
147+
148+
// Add listener for the buttons.
137149
LinearLayout root = this.chooser.getRootLayout();
138150
Button addButton = (Button) root.findViewById(R.id.buttonAdd);
139151
addButton.setOnClickListener(addButtonClickListener);
140152
Button okButton = (Button) root.findViewById(R.id.buttonOk);
141153
okButton.setOnClickListener(okButtonClickListener);
154+
Button cancelButton = (Button) root.findViewById(R.id.buttonCancel);
155+
cancelButton.setOnClickListener(cancelButtonClickListener);
142156
}
143157

144158
// ----- Events methods ----- //
@@ -178,7 +192,7 @@ public void onClick(DialogInterface dialog, int whichButton) {
178192
// Verify if a value has been entered.
179193
if(fileName != null && fileName.length() > 0) {
180194
// Notify the listeners.
181-
FileChooserCore.this.notifyListeners(FileChooserCore.this.currentFolder, fileName);
195+
FileChooserCore.this.notifyFileListeners(FileChooserCore.this.currentFolder, fileName);
182196
}
183197
}
184198
});
@@ -199,10 +213,20 @@ public void onClick(DialogInterface dialog, int whichButton) {
199213
private View.OnClickListener okButtonClickListener = new View.OnClickListener() {
200214
public void onClick(View v) {
201215
// Notify the listeners.
202-
FileChooserCore.this.notifyListeners(FileChooserCore.this.currentFolder, null);
216+
FileChooserCore.this.notifyFileListeners(FileChooserCore.this.currentFolder, null);
203217
}
204218
};
205-
219+
220+
/**
221+
* Implementation of the click listener for when the cancel button is clicked.
222+
*/
223+
private View.OnClickListener cancelButtonClickListener = new View.OnClickListener() {
224+
public void onClick(View v) {
225+
// Notify the listeners.
226+
FileChooserCore.this.notifyCancelListeners();
227+
}
228+
};
229+
206230
/**
207231
* Implementation of the click listener for when a file item is clicked.
208232
*/
@@ -215,7 +239,7 @@ public void onClick(FileItem source) {
215239
FileChooserCore.this.loadFolder(file);
216240
} else {
217241
// Notify the listeners.
218-
FileChooserCore.this.notifyListeners(file, null);
242+
FileChooserCore.this.notifyFileListeners(file, null);
219243
}
220244
}
221245
};
@@ -226,7 +250,7 @@ public void onClick(FileItem source) {
226250
* @param listener The listener to add.
227251
*/
228252
public void addListener(OnFileSelectedListener listener) {
229-
this.listeners.add(listener);
253+
this.fileSelectedListeners.add(listener);
230254
}
231255

232256
/**
@@ -235,16 +259,35 @@ public void addListener(OnFileSelectedListener listener) {
235259
* @param listener The listener to remove.
236260
*/
237261
public void removeListener(OnFileSelectedListener listener) {
238-
this.listeners.remove(listener);
239-
}
240-
241-
/**
242-
* Removes all the listeners for the event of a file selected.
243-
*/
244-
public void removeAllListeners() {
245-
this.listeners.clear();
262+
this.fileSelectedListeners.remove(listener);
246263
}
247-
264+
265+
/**
266+
* Add a listener for the event of a file selected.
267+
*
268+
* @param listener The listener to add.
269+
*/
270+
public void addListener(OnCancelListener listener) {
271+
this.cancelListeners.add(listener);
272+
}
273+
274+
/**
275+
* Removes a listener for the event of a file selected.
276+
*
277+
* @param listener The listener to remove.
278+
*/
279+
public void removeListener(OnCancelListener listener) {
280+
this.cancelListeners.remove(listener);
281+
}
282+
283+
/**
284+
* Removes all the listeners for the event of a file selected.
285+
*/
286+
public void removeAllListeners() {
287+
this.fileSelectedListeners.clear();
288+
this.cancelListeners.clear();
289+
}
290+
248291
/**
249292
* Interface definition for a callback to be invoked when a file is selected.
250293
*/
@@ -264,14 +307,33 @@ public interface OnFileSelectedListener {
264307
*/
265308
void onFileSelected(File folder, String name);
266309
}
267-
310+
311+
/**
312+
* Interface definition for a callback to be invoked when the cancel button is clicked.
313+
*/
314+
public interface OnCancelListener {
315+
/**
316+
* Called when the cancel button is clicked.
317+
*/
318+
void onCancel();
319+
}
320+
321+
/**
322+
* Notify to all listeners that the cancel button has been pressed.
323+
*/
324+
private void notifyCancelListeners() {
325+
for(int i=0; i<FileChooserCore.this.cancelListeners.size(); i++) {
326+
FileChooserCore.this.cancelListeners.get(i).onCancel();
327+
}
328+
}
329+
268330
/**
269331
* Notify to all listeners that a file has been selected or created.
270332
*
271333
* @param file The file or folder selected or the folder in which the file must be created.
272334
* @param name The name of the file that must be created or 'null' if a file was selected (instead of being created).
273335
*/
274-
private void notifyListeners(final File file, final String name) {
336+
private void notifyFileListeners(final File file, final String name) {
275337
// Determine if a file has been selected or created.
276338
final boolean creation = name != null && name.length() > 0;
277339

@@ -301,11 +363,11 @@ private void notifyListeners(final File file, final String name) {
301363
alert.setPositiveButton(posButton, new DialogInterface.OnClickListener() {
302364
public void onClick(DialogInterface dialog, int whichButton) {
303365
// Notify to listeners.
304-
for(int i=0; i<FileChooserCore.this.listeners.size(); i++) {
366+
for(int i=0; i<FileChooserCore.this.fileSelectedListeners.size(); i++) {
305367
if(creation) {
306-
FileChooserCore.this.listeners.get(i).onFileSelected(file, name);
368+
FileChooserCore.this.fileSelectedListeners.get(i).onFileSelected(file, name);
307369
} else {
308-
FileChooserCore.this.listeners.get(i).onFileSelected(file);
370+
FileChooserCore.this.fileSelectedListeners.get(i).onFileSelected(file);
309371
}
310372
}
311373
}
@@ -320,11 +382,11 @@ public void onClick(DialogInterface dialog, int whichButton) {
320382
alert.show();
321383
} else {
322384
// Notify to listeners.
323-
for(int i=0; i<FileChooserCore.this.listeners.size(); i++) {
385+
for(int i=0; i<FileChooserCore.this.fileSelectedListeners.size(); i++) {
324386
if(creation) {
325-
FileChooserCore.this.listeners.get(i).onFileSelected(file, name);
387+
FileChooserCore.this.fileSelectedListeners.get(i).onFileSelected(file, name);
326388
} else {
327-
FileChooserCore.this.listeners.get(i).onFileSelected(file);
389+
FileChooserCore.this.fileSelectedListeners.get(i).onFileSelected(file);
328390
}
329391
}
330392
}
@@ -362,7 +424,7 @@ public void setShowFullPathInTitle(boolean show) {
362424
/**
363425
* Defines the value of the labels.
364426
*
365-
* @param label The labels.
427+
* @param labels The labels.
366428
*/
367429
public void setLabels(FileChooserLabels labels) {
368430
this.labels = labels;
@@ -379,7 +441,12 @@ public void setLabels(FileChooserLabels labels) {
379441
if(labels.labelSelectButton != null) {
380442
Button okButton = (Button) root.findViewById(R.id.buttonOk);
381443
okButton.setText(labels.labelSelectButton);
382-
}
444+
}
445+
446+
if(labels.labelCancelButton != null) {
447+
Button cancelButton = (Button) root.findViewById(R.id.buttonCancel);
448+
cancelButton.setText(labels.labelCancelButton);
449+
}
383450
}
384451
}
385452

@@ -413,7 +480,19 @@ public void setFolderMode(boolean folderMode) {
413480
// Reload the list of files.
414481
this.loadFolder(this.currentFolder);
415482
}
416-
483+
484+
/**
485+
* Defines if the chooser is going to be used to select folders, instead of files.
486+
*
487+
* @param showCancelButton 'true' for show the cancel button or 'false' for not showing it.
488+
*/
489+
public void setShowCancelButton(boolean showCancelButton) {
490+
this.showCancelButton = showCancelButton;
491+
492+
// Show or hide the 'Cancel' button.
493+
updateButtonsLayout();
494+
}
495+
417496
/**
418497
* Defines if the user can create files, instead of only select files.
419498
*
@@ -455,37 +534,19 @@ public File getCurrentFolder() {
455534
private void updateButtonsLayout() {
456535
// Get the buttons layout.
457536
LinearLayout root = this.chooser.getRootLayout();
458-
LinearLayout buttonsLayout = (LinearLayout) root.findViewById(R.id.linearLayoutButtons);
459537

460538
// Verify if the 'Add' button is visible or not.
461539
View addButton = root.findViewById(R.id.buttonAdd);
462-
addButton.setVisibility(this.canCreateFiles? View.VISIBLE : View.INVISIBLE);
463-
addButton.getLayoutParams().width = this.canCreateFiles? ViewGroup.LayoutParams.MATCH_PARENT : 0;
540+
addButton.setVisibility(this.canCreateFiles? View.VISIBLE : View.GONE);
464541

465542
// Verify if the 'Ok' button is visible or not.
466543
View okButton = root.findViewById(R.id.buttonOk);
467-
okButton.setVisibility(this.folderMode? View.VISIBLE : View.INVISIBLE);
468-
okButton.getLayoutParams().width = this.folderMode? ViewGroup.LayoutParams.MATCH_PARENT : 0;
469-
470-
// If both buttons are invisible, hide the layout.
471-
ViewGroup.LayoutParams params = buttonsLayout.getLayoutParams();
472-
if(this.canCreateFiles || this.folderMode) {
473-
// Show the layout.
474-
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
475-
476-
// If only the 'Ok' button is visible, put him first. Otherwise, put 'Add' first.
477-
buttonsLayout.removeAllViews();
478-
if(this.folderMode && !this.canCreateFiles) {
479-
buttonsLayout.addView(okButton);
480-
buttonsLayout.addView(addButton);
481-
} else {
482-
buttonsLayout.addView(addButton);
483-
buttonsLayout.addView(okButton);
484-
}
485-
} else {
486-
// Hide the layout.
487-
params.height = 0;
488-
}
544+
okButton.setVisibility(this.folderMode? View.VISIBLE : View.GONE);
545+
546+
// Verify if the 'Cancel' button is visible or not.
547+
View cancelButton = root.findViewById(R.id.buttonCancel);
548+
cancelButton.setVisibility(this.showCancelButton? View.VISIBLE : View.GONE);
549+
489550
}
490551

491552
/**

0 commit comments

Comments
 (0)