Add a new mode for picking new files

This adds a new mode so the library can be used for
"Save-As"-dialogs.

Fixes #82
This commit is contained in:
Jonas Kalderstam 2016-05-14 00:55:28 +02:00
parent 4080ad60c7
commit c8978a9880
20 changed files with 278 additions and 65 deletions

View File

@ -36,10 +36,10 @@ import java.util.List;
* If you want to be able to select multiple items, include EXTRA_ALLOW_MULTIPLE
* (default false).
* <p/>
* Two non-standard extra arguments are supported as well: EXTRA_ONLY_DIRS
* (defaults to false)
* allows only directories to be selected.
* And EXTRA_START_PATH (default null), which should specify the starting path.
* Some non-standard extra arguments are supported as well:
* EXTRA_ONLY_DIRS - (default false) allows only directories to be selected.
* EXTRA_START_PATH - (default null) which should specify the starting path.
* EXTRA_ALLOW_EXISTING_FILE - (default true) if existing files are selectable in 'new file'-mode
* <p/>
* The result of the user's action is returned in onActivityResult intent,
* access it using getUri.
@ -60,16 +60,20 @@ public abstract class AbstractFilePickerActivity<T> extends AppCompatActivity
// For compatibility
public static final String EXTRA_ALLOW_MULTIPLE =
"android.intent.extra" + ".ALLOW_MULTIPLE";
public static final String EXTRA_ALLOW_EXISTING_FILE =
"android.intent.extra" + ".ALLOW_EXISTING_FILE";
public static final String EXTRA_PATHS = "nononsense.intent.PATHS";
public static final int MODE_FILE = AbstractFilePickerFragment.MODE_FILE;
public static final int MODE_FILE_AND_DIR =
AbstractFilePickerFragment.MODE_FILE_AND_DIR;
public static final int MODE_NEW_FILE = AbstractFilePickerFragment.MODE_NEW_FILE;
public static final int MODE_DIR = AbstractFilePickerFragment.MODE_DIR;
protected static final String TAG = "filepicker_fragment";
protected String startPath = null;
protected int mode = AbstractFilePickerFragment.MODE_FILE;
protected boolean allowCreateDir = false;
protected boolean allowMultiple = false;
private boolean allowExistingFile = true;
@Override
@SuppressWarnings("unchecked")
@ -86,6 +90,8 @@ public abstract class AbstractFilePickerActivity<T> extends AppCompatActivity
allowCreateDir);
allowMultiple =
intent.getBooleanExtra(EXTRA_ALLOW_MULTIPLE, allowMultiple);
allowExistingFile =
intent.getBooleanExtra(EXTRA_ALLOW_EXISTING_FILE, allowExistingFile);
}
FragmentManager fm = getSupportFragmentManager();
@ -94,7 +100,7 @@ public abstract class AbstractFilePickerActivity<T> extends AppCompatActivity
if (fragment == null) {
fragment =
getFragment(startPath, mode, allowMultiple, allowCreateDir);
getFragment(startPath, mode, allowMultiple, allowCreateDir, allowExistingFile);
}
if (fragment != null) {
@ -108,7 +114,7 @@ public abstract class AbstractFilePickerActivity<T> extends AppCompatActivity
protected abstract AbstractFilePickerFragment<T> getFragment(
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir);
final boolean allowCreateDir, boolean allowExistingFile);
@Override
public void onSaveInstanceState(Bundle b) {

View File

@ -27,6 +27,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@ -34,6 +35,8 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static com.nononsenseapps.filepicker.Utils.isValidFileName;
/**
* A fragment representing a list of Files.
* <p/>
@ -51,6 +54,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
public static final int MODE_FILE = 0;
public static final int MODE_DIR = 1;
public static final int MODE_FILE_AND_DIR = 2;
public static final int MODE_NEW_FILE = 3;
// Where to display on open.
public static final String KEY_START_PATH = "KEY_START_PATH";
// See MODE_XXX constants above for possible values
@ -59,6 +63,8 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
public static final String KEY_ALLOW_DIR_CREATE = "KEY_ALLOW_DIR_CREATE";
// Allow multiple items to be selected.
public static final String KEY_ALLOW_MULTIPLE = "KEY_ALLOW_MULTIPLE";
// Allow an existing file to be selected under MODE_NEW_FILE
public static final String KEY_ALLOW_EXISTING_FILE = "KEY_ALLOW_EXISTING_FILE";
// Used for saving state.
protected static final String KEY_CURRENT_PATH = "KEY_CURRENT_PATH";
protected final HashSet<T> mCheckedItems;
@ -67,13 +73,17 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
protected T mCurrentPath = null;
protected boolean allowCreateDir = false;
protected boolean allowMultiple = false;
protected boolean allowExistingFile = true;
protected OnFilePickedListener mListener;
protected FileItemAdapter<T> mAdapter = null;
protected TextView mCurrentDirView;
protected EditText mEditTextFileName;
protected SortedList<T> mFiles = null;
protected Toast mToast = null;
// Keep track if we are currently loading a directory, in case it takes a long time
protected boolean isLoading = false;
private View mNewFileButtonContainer = null;
private View mRegularButtonContainer = null;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
@ -110,7 +120,14 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
* @param allowDirCreate can new directories be created?
*/
public void setArgs(@Nullable final String startPath, final int mode,
final boolean allowMultiple, final boolean allowDirCreate) {
final boolean allowMultiple, final boolean allowDirCreate,
final boolean allowExistingFile) {
// Validate some assumptions so users don't get surprised (or get surprised early)
if (mode == MODE_NEW_FILE && allowMultiple) {
throw new IllegalArgumentException(
"MODE_NEW_FILE does not support 'allowMultiple'");
}
// There might have been arguments set elsewhere, if so do not overwrite them.
Bundle b = getArguments();
if (b == null) {
@ -122,6 +139,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
}
b.putBoolean(KEY_ALLOW_DIR_CREATE, allowDirCreate);
b.putBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
b.putBoolean(KEY_ALLOW_EXISTING_FILE, allowExistingFile);
b.putInt(KEY_MODE, mode);
setArguments(b);
}
@ -129,7 +147,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.nnf_fragment_filepicker, container, false);
final View view = inflater.inflate(R.layout.nnf_fragment_filepicker, container, false);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.nnf_picker_toolbar);
if (toolbar != null) {
@ -155,13 +173,24 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
}
});
view.findViewById(R.id.nnf_button_ok)
.setOnClickListener(new View.OnClickListener() {
view.findViewById(R.id.nnf_button_ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
onClickOk(v);
}
});
view.findViewById(R.id.nnf_button_ok_newfile).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
onClickOk(v);
}
});
mNewFileButtonContainer = view.findViewById(R.id.nnf_newfile_button_container);
mRegularButtonContainer = view.findViewById(R.id.nnf_button_container);
mEditTextFileName = (EditText) view.findViewById(R.id.nnf_text_filename);
mCurrentDirView = (TextView) view.findViewById(R.id.nnf_current_dir);
// Restore state
@ -194,6 +223,12 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
}
// Some invalid cases first
if (MODE_NEW_FILE == mode && !isValidFileName(getNewFileName())) {
mToast = Toast.makeText(getActivity(), R.string.nnf_need_valid_filename,
Toast.LENGTH_SHORT);
mToast.show();
return;
}
if ((allowMultiple || mode == MODE_FILE) &&
(mCheckedItems.isEmpty() || getFirstCheckedItem() == null)) {
if (mToast == null) {
@ -204,9 +239,16 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
return;
}
if (allowMultiple) {
// New file allows only a single file
if (mode == MODE_NEW_FILE) {
mListener.onFilePicked(
toUri(mCurrentPath).buildUpon()
.appendPath(getNewFileName())
.build());
} else if (allowMultiple) {
mListener.onFilesPicked(toUri(mCheckedItems));
} else if (mode == MODE_FILE) {
//noinspection ConstantConditions
mListener.onFilePicked(toUri(getFirstCheckedItem()));
} else if (mode == MODE_DIR) {
mListener.onFilePicked(toUri(mCurrentPath));
@ -220,6 +262,15 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
}
}
/**
*
* @return filename as entered/picked by the user for the new file
*/
@NonNull
protected String getNewFileName() {
return mEditTextFileName.getText().toString();
}
/**
* 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.
@ -254,7 +305,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
(mode == MODE_FILE_AND_DIR && allowMultiple));
} else {
// File
checkable = (mode != MODE_DIR);
checkable = (mode == MODE_FILE || mode == MODE_FILE_AND_DIR || allowExistingFile);
}
return checkable;
}
@ -301,6 +352,8 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
.getBoolean(KEY_ALLOW_DIR_CREATE, allowCreateDir);
allowMultiple = savedInstanceState
.getBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
allowExistingFile = savedInstanceState
.getBoolean(KEY_ALLOW_EXISTING_FILE, allowExistingFile);
String path = savedInstanceState.getString(KEY_CURRENT_PATH);
if (path != null) {
@ -312,6 +365,8 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
.getBoolean(KEY_ALLOW_DIR_CREATE, allowCreateDir);
allowMultiple = getArguments()
.getBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
allowExistingFile = getArguments()
.getBoolean(KEY_ALLOW_EXISTING_FILE, allowExistingFile);
if (getArguments().containsKey(KEY_START_PATH)) {
String path = getArguments().getString(KEY_START_PATH);
if (path != null) {
@ -326,9 +381,20 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
}
}
setModeView();
refresh();
}
/**
* Hides/Shows appropriate views depending on mode
*/
protected void setModeView() {
boolean nf = mode == MODE_NEW_FILE;
mNewFileButtonContainer.setVisibility(nf ? View.VISIBLE : View.GONE);
mRegularButtonContainer.setVisibility(nf ? View.GONE : View.VISIBLE);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.picker_actions, menu);
@ -357,6 +423,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
super.onSaveInstanceState(b);
b.putString(KEY_CURRENT_PATH, mCurrentPath.toString());
b.putBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
b.putBoolean(KEY_ALLOW_EXISTING_FILE, allowExistingFile);
b.putBoolean(KEY_ALLOW_DIR_CREATE, allowCreateDir);
b.putInt(KEY_MODE, mode);
}
@ -623,7 +690,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
/**
* 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.
* screen must be de-selected. The text box for new filename is also cleared.
*
* @param viewHolder for the item containing the checkbox.
*/
@ -632,9 +699,13 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
viewHolder.checkbox.setChecked(false);
mCheckedItems.remove(viewHolder.file);
mCheckedVisibleViewHolders.remove(viewHolder);
if (!allowMultiple) {
mEditTextFileName.setText("");
}
} else {
if (!allowMultiple) {
clearSelections();
mEditTextFileName.setText(getName(viewHolder.file));
}
viewHolder.checkbox.setChecked(true);
mCheckedItems.add(viewHolder.file);

View File

@ -8,7 +8,6 @@ package com.nononsenseapps.filepicker;
import android.annotation.SuppressLint;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.File;
@ -23,11 +22,11 @@ public class FilePickerActivity extends AbstractFilePickerActivity<File> {
@Override
protected AbstractFilePickerFragment<File> getFragment(
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir) {
final boolean allowCreateDir, final boolean allowExistingFile) {
AbstractFilePickerFragment<File> fragment = new FilePickerFragment();
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
fragment.setArgs(startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
mode, allowMultiple, allowCreateDir);
mode, allowMultiple, allowCreateDir, allowExistingFile);
return fragment;
}
}

View File

@ -325,7 +325,8 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
if(!showHiddenItems && file.isHidden()){
return false;
}
return (isDir(file) || (mode == MODE_FILE || mode == MODE_FILE_AND_DIR));
return (isDir(file) ||
(mode != MODE_DIR));
}
/**

View File

@ -10,7 +10,8 @@ package com.nononsenseapps.filepicker;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.text.TextUtils;
import static com.nononsenseapps.filepicker.Utils.isValidFileName;
public class NewFolderFragment extends NewItemFragment {
@ -25,9 +26,6 @@ public class NewFolderFragment extends NewItemFragment {
@Override
protected boolean validateName(@Nullable final String itemName) {
return !TextUtils.isEmpty(itemName)
&& !itemName.contains("/")
&& !itemName.equals(".")
&& !itemName.equals("..");
return isValidFileName(itemName);
}
}

View File

@ -113,12 +113,6 @@ public abstract class NewItemFragment extends DialogFragment {
protected abstract boolean validateName(final String itemName);
public interface OnNewFolderListener {
/**
* Name is validated to be non-null, non-empty and not containing any
* slashes.
*
* @param name The name of the folder the user wishes to create.
*/
void onNewFolder(@NonNull final String name);
}
}

View File

@ -0,0 +1,23 @@
package com.nononsenseapps.filepicker;
import android.support.annotation.Nullable;
import android.text.TextUtils;
/**
* Some utility methods
*/
public class Utils {
/**
* Name is validated to be non-null, non-empty and not containing any
* slashes.
*
* @param name The name of the folder the user wishes to create.
*/
public static boolean isValidFileName(@Nullable String name) {
return !TextUtils.isEmpty(name)
&& !name.contains("/")
&& !name.equals(".")
&& !name.equals("..");
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
</vector>

View File

@ -34,41 +34,74 @@
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/nnf_button_container"
android:layout_above="@+id/nnf_buttons_container"
android:layout_below="@+id/nnf_picker_toolbar"
android:descendantFocusability="afterDescendants"
android:focusable="true"
tools:listitem="@layout/nnf_filepicker_listitem_dir"/>
<LinearLayout
android:id="@+id/nnf_button_container"
<FrameLayout
android:id="@+id/nnf_buttons_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
android:layout_alignParentBottom="true">
<Button
android:id="@+id/nnf_button_cancel"
style="?attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@android:string/cancel"/>
<LinearLayout
android:id="@+id/nnf_button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/nnf_button_ok"
style="?attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@android:string/ok"/>
<Button
android:id="@+id/nnf_button_cancel"
style="?attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@android:string/cancel"/>
</LinearLayout>
<Button
android:id="@+id/nnf_button_ok"
style="?attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="@android:string/ok"/>
</LinearLayout>
<LinearLayout
android:id="@+id/nnf_newfile_button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/nnf_text_filename"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:hint="@string/nnf_filename"
android:maxLines="1"
android:paddingLeft="8dp"
android:paddingRight="8dp"/>
<ImageButton
android:id="@+id/nnf_button_ok_newfile"
style="?attr/borderlessButtonStyle"
android:layout_width="48dp"
android:layout_height="48dp"
android:hint="@android:string/ok"
android:src="@drawable/nnf_ic_save_black_24dp"
android:tint="?attr/nnf_save_icon_color"/>
</LinearLayout>
</FrameLayout>
<FrameLayout
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_above="@id/nnf_button_container"
android:layout_above="@id/nnf_buttons_container"
android:background="?nnf_separator_color"/>
</RelativeLayout>

View File

@ -11,6 +11,8 @@
<attr name="nnf_toolbarTheme" format="reference"/>
<!-- Color to apply to separator for OK/Cancel buttons -->
<attr name="nnf_separator_color" format="color"/>
<!-- Color to apply to the save icon -->
<attr name="nnf_save_icon_color" format="color"/>
<!-- Color to apply to the directory icons in list -->
<attr name="nnf_dir_icon_color" format="color"/>
</resources>

View File

@ -9,5 +9,7 @@
<string name="nnf_create_folder_error">Failed to create folder</string>
<string name="nnf_name">Name</string>
<string name="nnf_select_something_first">Please select something first</string>
<string name="nnf_need_valid_filename">Please enter or select a valid filename</string>
<string name="nnf_permission_external_write_denied">Permisson to access filesystem denied</string>
<string name="nnf_filename">Filename</string>
</resources>

View File

@ -12,6 +12,7 @@
<!-- You can override this in your sub theme -->
<item name="nnf_toolbarTheme">@style/ThemeOverlay.AppCompat.ActionBar</item>
<item name="nnf_separator_color">@color/nnf_dark_separator_color</item>
<item name="nnf_save_icon_color">?attr/colorAccent</item>
<item name="nnf_dir_icon_color">?attr/colorAccent</item>
<!-- These are important. Handled by toolbar. -->
@ -23,6 +24,7 @@
<!-- You can override this in your sub theme -->
<item name="nnf_toolbarTheme">@style/ThemeOverlay.AppCompat.ActionBar</item>
<item name="nnf_separator_color">@color/nnf_light_separator_color</item>
<item name="nnf_save_icon_color">?attr/colorAccent</item>
<item name="nnf_dir_icon_color">?attr/colorAccent</item>
<!-- These are important. Handled by toolbar. -->

View File

@ -12,7 +12,9 @@ import org.junit.Test;
import java.io.File;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class FilePickerFragmentTest {
@ -62,6 +64,17 @@ public class FilePickerFragmentTest {
assertEquals("/", fragment.getRoot().getPath());
}
@Test
public void testSetArgsMultipleNewFiles() throws Exception {
try {
fragment.setArgs(null, AbstractFilePickerFragment.MODE_NEW_FILE, true, false, true);
fail("Expected exception");
} catch (IllegalArgumentException e) {
assertTrue("Should mention the mode limitations: " + e.getMessage(),
e.getMessage().contains("MODE_NEW_FILE"));
}
}
@Test
public void testCompareFiles() throws Exception {
assertEquals(0, fragment.compareFiles(new File("/A/A"), new File("/A/A")));

View File

@ -24,12 +24,13 @@ android {
targetSdkVersion 23
versionCode gitCommitCount
versionName gitTag
archivesBaseName = "nononsensefilepicker-sample-${gitTag}".toString()
//archivesBaseName = "nononsensefilepicker-sample-${gitTag}".toString()
}
buildTypes {
release {
release {
archivesBaseName = "nononsensefilepicker-sample-${gitTag}".toString()
//minifyEnabled true
//shrinkResources true
//proguardFiles getDefaultProguardFile('proguard-android.txt')

View File

@ -7,7 +7,7 @@
package com.nononsenseapps.filepicker.sample;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.nononsenseapps.filepicker.AbstractFilePickerActivity;
import com.nononsenseapps.filepicker.AbstractFilePickerFragment;
@ -25,12 +25,12 @@ public class MultimediaPickerActivity extends AbstractFilePickerActivity {
@Override
protected AbstractFilePickerFragment<File> getFragment(
@NonNull final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir) {
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir, boolean allowExistingFile) {
AbstractFilePickerFragment<File> fragment = new MultimediaPickerFragment();
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
fragment.setArgs(startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
mode, allowMultiple, allowCreateDir);
mode, allowMultiple, allowCreateDir, allowExistingFile);
return fragment;
}
}

View File

@ -19,6 +19,7 @@ import android.view.View;
import android.widget.CheckBox;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
@ -50,6 +51,8 @@ public class NoNonsenseFilePicker extends Activity {
(CheckBox) findViewById(R.id.checkAllowCreateDir);
final CheckBox checkAllowMultiple =
(CheckBox) findViewById(R.id.checkAllowMultiple);
final CheckBox checkAllowExistingFile =
(CheckBox) findViewById(R.id.checkAllowExistingFile);
final CheckBox checkLightTheme =
(CheckBox) findViewById(R.id.checkLightTheme);
final RadioGroup radioGroup =
@ -75,26 +78,38 @@ public class NoNonsenseFilePicker extends Activity {
checkAllowMultiple.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR,
checkAllowCreateDir.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_EXISTING_FILE,
checkAllowExistingFile.isChecked());
// What mode is selected
final int mode;
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.radioDir:
mode = AbstractFilePickerFragment.MODE_DIR;
mode = FilePickerActivity.MODE_DIR;
break;
case R.id.radioFilesAndDirs:
mode =
AbstractFilePickerFragment.MODE_FILE_AND_DIR;
mode = FilePickerActivity.MODE_FILE_AND_DIR;
break;
case R.id.radioNewFile:
mode = FilePickerActivity.MODE_NEW_FILE;
break;
case R.id.radioFile:
default:
mode = AbstractFilePickerFragment.MODE_FILE;
mode = FilePickerActivity.MODE_FILE;
break;
}
i.putExtra(FilePickerActivity.EXTRA_MODE, mode);
// Warn about invalid combination
if (mode == FilePickerActivity.MODE_NEW_FILE &&
checkAllowMultiple.isChecked()) {
Toast.makeText(NoNonsenseFilePicker.this,
"'New file' does not support multiple items",
Toast.LENGTH_SHORT)
.show();
return;
}
startActivityForResult(i, CODE_SD);
}
});
@ -118,6 +133,8 @@ public class NoNonsenseFilePicker extends Activity {
checkAllowMultiple.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR,
checkAllowCreateDir.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_EXISTING_FILE,
checkAllowExistingFile.isChecked());
// What mode is selected (makes no sense to restrict to folders here)
final int mode;
@ -126,6 +143,9 @@ public class NoNonsenseFilePicker extends Activity {
mode =
AbstractFilePickerFragment.MODE_FILE_AND_DIR;
break;
case R.id.radioNewFile:
mode = FilePickerActivity.MODE_NEW_FILE;
break;
case R.id.radioFile:
default:
mode = AbstractFilePickerFragment.MODE_FILE;
@ -158,6 +178,8 @@ public class NoNonsenseFilePicker extends Activity {
checkAllowMultiple.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR,
checkAllowCreateDir.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_EXISTING_FILE,
checkAllowExistingFile.isChecked());
// What mode is selected (makes no sense to restrict to folders here)
final int mode;
@ -169,6 +191,9 @@ public class NoNonsenseFilePicker extends Activity {
mode =
AbstractFilePickerFragment.MODE_FILE_AND_DIR;
break;
case R.id.radioNewFile:
mode = FilePickerActivity.MODE_NEW_FILE;
break;
case R.id.radioFile:
default:
mode = AbstractFilePickerFragment.MODE_FILE;
@ -212,6 +237,8 @@ public class NoNonsenseFilePicker extends Activity {
i.putExtra(
FilePickerActivity.EXTRA_ALLOW_CREATE_DIR,
checkAllowCreateDir.isChecked());
i.putExtra(FilePickerActivity.EXTRA_ALLOW_EXISTING_FILE,
checkAllowExistingFile.isChecked());
// What mode is selected
final int mode;
@ -223,6 +250,9 @@ public class NoNonsenseFilePicker extends Activity {
mode =
AbstractFilePickerFragment.MODE_FILE_AND_DIR;
break;
case R.id.radioNewFile:
mode = FilePickerActivity.MODE_NEW_FILE;
break;
case R.id.radioFile:
default:
mode = AbstractFilePickerFragment.MODE_FILE;

View File

@ -8,6 +8,7 @@ package com.nononsenseapps.filepicker.sample.dropbox;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
@ -34,8 +35,8 @@ public class DropboxFilePickerActivity
@Override
protected AbstractFilePickerFragment<DropboxAPI.Entry> getFragment(
@NonNull final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir) {
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir, boolean allowExistingFile) {
if (mDBApi == null || !mDBApi.getSession().isLinked()) {
// No valid authentication
finish();
@ -44,7 +45,7 @@ public class DropboxFilePickerActivity
DropboxFilePickerFragment fragment =
new DropboxFilePickerFragment(mDBApi);
fragment.setArgs(startPath, mode, allowMultiple, allowCreateDir);
fragment.setArgs(startPath, mode, allowMultiple, allowCreateDir, allowExistingFile);
return fragment;
}
}

View File

@ -8,6 +8,7 @@ package com.nononsenseapps.filepicker.sample.ftp;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.nononsenseapps.filepicker.AbstractFilePickerActivity;
import com.nononsenseapps.filepicker.AbstractFilePickerFragment;
@ -19,8 +20,12 @@ import org.apache.commons.net.ftp.FTPClient;
*/
public class FtpPickerActivity extends AbstractFilePickerActivity<FtpFile> {
@Override
protected AbstractFilePickerFragment<FtpFile> getFragment(@NonNull String startPath, int mode, boolean allowMultiple, boolean allowCreateDir) {
protected AbstractFilePickerFragment<FtpFile> getFragment(@Nullable String startPath, int mode,
boolean allowMultiple,
boolean allowCreateDir,
boolean allowExistingFile) {
return FtpPickerFragment.newInstance(startPath, mode, allowMultiple, allowCreateDir,
allowExistingFile,
"debian.simnet.is",
FTPClient.DEFAULT_PORT,
null,

View File

@ -53,13 +53,14 @@ public class FtpPickerFragment extends AbstractFilePickerFragment<FtpFile> {
public static AbstractFilePickerFragment<FtpFile> newInstance(String startPath, int mode,
boolean allowMultiple,
boolean allowCreateDir,
boolean allowExistingFile,
String server, int port,
String username,
String password,
String rootDir) {
FtpPickerFragment fragment = new FtpPickerFragment();
// Add arguments
fragment.setArgs(startPath, mode, allowMultiple, allowCreateDir);
fragment.setArgs(startPath, mode, allowMultiple, allowCreateDir, allowExistingFile);
Bundle args = fragment.getArguments();
// Add ftp related stuff

View File

@ -47,6 +47,16 @@
android:gravity="center_vertical"
android:text="Select file" />
<RadioButton
android:id="@+id/radioNewFile"
style="?android:textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:fontFamily="light"
android:gravity="center_vertical"
android:text="Select new file" />
<RadioButton
android:id="@+id/radioDir"
style="?android:textAppearanceMedium"
@ -66,6 +76,7 @@
android:fontFamily="light"
android:gravity="center_vertical"
android:text="Select any" />
</RadioGroup>
<CheckBox
@ -88,6 +99,17 @@
android:gravity="center_vertical"
android:text="Allow creation of directories" />
<CheckBox
android:id="@+id/checkAllowExistingFile"
style="?android:textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="left"
android:fontFamily="light"
android:gravity="center_vertical"
android:checked="true"
android:text="Allow selection of existing (new) file" />
<CheckBox
android:id="@+id/checkLightTheme"
style="?android:textAppearanceMedium"