Fragment can now be used together with action bar

Now possible to load the fragment even with existing
toolbar, as long as setupToolbar() is overriden.

Fixes #32

Signed-off-by: Jonas Kalderstam <jonas@kalderstam.se>
This commit is contained in:
Jonas Kalderstam 2015-07-13 14:14:32 +02:00
parent 4124e8ea20
commit 2ede72dca9
5 changed files with 95 additions and 80 deletions

View File

@ -70,15 +70,15 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
public static final String KEY_ALLOW_MULTIPLE = "KEY_ALLOW_MULTIPLE";
// Used for saving state.
protected static final String KEY_CURRENT_PATH = "KEY_CURRENT PATH";
protected final HashSet<T> checkedItems;
protected final HashSet<CheckableViewHolder> checkedVisibleViewHolders;
protected T currentPath = null;
protected final HashSet<T> mCheckedItems;
protected final HashSet<CheckableViewHolder> mCheckedVisibleViewHolders;
protected T mCurrentPath = null;
protected boolean allowCreateDir = false;
protected boolean allowMultiple = false;
private OnFilePickedListener listener;
private FileItemAdapter<T> mAdapter = null;
private TextView currentDirView;
private SortedList<T> mFiles = null;
protected OnFilePickedListener mListener;
protected FileItemAdapter<T> mAdapter = null;
protected TextView mCurrentDirView;
protected SortedList<T> mFiles = null;
protected FileItemAdapter<T> getAdapter() {
return mAdapter;
@ -93,8 +93,8 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
* fragment (e.g. upon screen orientation changes).
*/
public AbstractFilePickerFragment() {
checkedItems = new HashSet<>();
checkedVisibleViewHolders = new HashSet<>();
mCheckedItems = new HashSet<>();
mCheckedVisibleViewHolders = new HashSet<>();
// Retain this fragment across configuration changes, to allow
// asynctasks and such to be used with ease.
@ -126,9 +126,10 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.nnf_fragment_filepicker, container, false);
Toolbar mToolbar = (Toolbar) view.findViewById(R.id.picker_toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.nnf_picker_toolbar);
if (toolbar != null) {
setupToolbar(toolbar);
}
RecyclerView mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
// improve performance if you know that changes in content
@ -141,26 +142,26 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
mAdapter = new FileItemAdapter<>(this);
mRecyclerView.setAdapter(mAdapter);
view.findViewById(R.id.button_cancel)
view.findViewById(R.id.nnf_button_cancel)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
if (listener != null) {
listener.onCancelled();
if (mListener != null) {
mListener.onCancelled();
}
}
});
view.findViewById(R.id.button_ok)
view.findViewById(R.id.nnf_button_ok)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
if (listener == null) {
if (mListener == null) {
return;
}
// Some invalid cases first
if ((allowMultiple || mode == MODE_FILE) && checkedItems.isEmpty()) {
if ((allowMultiple || mode == MODE_FILE) && mCheckedItems.isEmpty()) {
Toast.makeText(getActivity(),
R.string.nnf_select_something_first,
Toast.LENGTH_SHORT).show();
@ -168,33 +169,44 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
}
if (allowMultiple) {
listener.onFilesPicked(toUri(checkedItems));
mListener.onFilesPicked(toUri(mCheckedItems));
} else if (mode == MODE_FILE) {
listener.onFilePicked(toUri(getFirstCheckedItem()));
mListener.onFilePicked(toUri(getFirstCheckedItem()));
} else if (mode == MODE_DIR) {
listener.onFilePicked(toUri(currentPath));
mListener.onFilePicked(toUri(mCurrentPath));
} else {
// single FILE OR DIR
if (checkedItems.isEmpty()) {
listener.onFilePicked(toUri(currentPath));
if (mCheckedItems.isEmpty()) {
mListener.onFilePicked(toUri(mCurrentPath));
} else {
listener.onFilePicked(toUri(getFirstCheckedItem()));
mListener.onFilePicked(toUri(getFirstCheckedItem()));
}
}
}
});
currentDirView = (TextView) view.findViewById(R.id.current_dir);
mCurrentDirView = (TextView) view.findViewById(R.id.nnf_current_dir);
// Restore state
if (currentPath != null) {
currentDirView.setText(getFullPath(currentPath));
if (mCurrentPath != null && mCurrentDirView != null) {
mCurrentDirView.setText(getFullPath(mCurrentPath));
}
return view;
}
/**
* 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.
* Not called if no toolbar was found.
*
* @param toolbar from layout with id "picker_toolbar"
*/
protected void setupToolbar(Toolbar toolbar) {
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
}
public T getFirstCheckedItem() {
for (T file : checkedItems) {
for (T file : mCheckedItems) {
return file;
}
return null;
@ -224,7 +236,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
listener = (OnFilePickedListener) activity;
mListener = (OnFilePickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() +
" must implement OnFilePickedListener");
@ -255,14 +267,14 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Only if we have no state
if (currentPath == null) {
if (mCurrentPath == null) {
if (savedInstanceState != null) {
mode = savedInstanceState.getInt(KEY_MODE, mode);
allowCreateDir = savedInstanceState
.getBoolean(KEY_ALLOW_DIR_CREATE, allowCreateDir);
allowMultiple = savedInstanceState
.getBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
currentPath =
mCurrentPath =
getPath(savedInstanceState.getString(KEY_CURRENT_PATH));
} else if (getArguments() != null) {
mode = getArguments().getInt(KEY_MODE, mode);
@ -271,14 +283,14 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
allowMultiple = getArguments()
.getBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
if (getArguments().containsKey(KEY_START_PATH)) {
currentPath =
mCurrentPath =
getPath(getArguments().getString(KEY_START_PATH));
}
}
// If still null
if (currentPath == null) {
currentPath = getRoot();
if (mCurrentPath == null) {
mCurrentPath = getRoot();
}
}
@ -311,7 +323,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
@Override
public void onSaveInstanceState(Bundle b) {
super.onSaveInstanceState(b);
b.putString(KEY_CURRENT_PATH, currentPath.toString());
b.putString(KEY_CURRENT_PATH, mCurrentPath.toString());
b.putBoolean(KEY_ALLOW_MULTIPLE, allowMultiple);
b.putBoolean(KEY_ALLOW_DIR_CREATE, allowCreateDir);
b.putInt(KEY_MODE, mode);
@ -320,7 +332,7 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
@Override
public void onDetach() {
super.onDetach();
listener = null;
mListener = null;
}
/**
@ -352,11 +364,13 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
@Override
public void onLoadFinished(final Loader<SortedList<T>> loader,
final SortedList<T> data) {
checkedItems.clear();
checkedVisibleViewHolders.clear();
mCheckedItems.clear();
mCheckedVisibleViewHolders.clear();
mFiles = data;
mAdapter.setList(data);
currentDirView.setText(getFullPath(currentPath));
if (mCurrentDirView != null) {
mCurrentDirView.setText(getFullPath(mCurrentPath));
}
}
/**
@ -447,12 +461,12 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
vh.text.setText(getName(data));
if (isCheckable(data)) {
if (checkedItems.contains(data)) {
checkedVisibleViewHolders.add((CheckableViewHolder) vh);
if (mCheckedItems.contains(data)) {
mCheckedVisibleViewHolders.add((CheckableViewHolder) vh);
((CheckableViewHolder) vh).checkbox.setChecked(true);
} else {
//noinspection SuspiciousMethodCalls
checkedVisibleViewHolders.remove(vh);
mCheckedVisibleViewHolders.remove(vh);
((CheckableViewHolder) vh).checkbox.setChecked(false);
}
}
@ -474,9 +488,9 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
*/
@Override
public void onClick(View v) {
currentPath = getParent(currentPath);
checkedItems.clear();
checkedVisibleViewHolders.clear();
mCurrentPath = getParent(mCurrentPath);
mCheckedItems.clear();
mCheckedVisibleViewHolders.clear();
refresh();
}
}
@ -503,9 +517,9 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
@Override
public void onClick(View v) {
if (isDir(file)) {
currentPath = file;
checkedItems.clear();
checkedVisibleViewHolders.clear();
mCurrentPath = file;
mCheckedItems.clear();
mCheckedVisibleViewHolders.clear();
refresh();
}
}
@ -545,9 +559,9 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
@Override
public void onClick(View v) {
if (isDir(file)) {
currentPath = file;
checkedItems.clear();
checkedVisibleViewHolders.clear();
mCurrentPath = file;
mCheckedItems.clear();
mCheckedVisibleViewHolders.clear();
refresh();
} else {
onLongClick(v);
@ -562,17 +576,17 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
*/
@Override
public boolean onLongClick(View v) {
if (checkedItems.contains(file)) {
if (mCheckedItems.contains(file)) {
checkbox.setChecked(false);
checkedItems.remove(file);
checkedVisibleViewHolders.remove(this);
mCheckedItems.remove(file);
mCheckedVisibleViewHolders.remove(this);
} else {
if (!allowMultiple) {
clearSelections();
}
checkbox.setChecked(true);
checkedItems.add(file);
checkedVisibleViewHolders.add(this);
mCheckedItems.add(file);
mCheckedVisibleViewHolders.add(this);
}
return true;
}
@ -583,11 +597,11 @@ public abstract class AbstractFilePickerFragment<T> extends Fragment
* selected set.
*/
public void clearSelections() {
for (CheckableViewHolder vh : checkedVisibleViewHolders) {
for (CheckableViewHolder vh : mCheckedVisibleViewHolders) {
vh.checkbox.setChecked(false);
}
checkedVisibleViewHolders.clear();
checkedItems.clear();
mCheckedVisibleViewHolders.clear();
mCheckedItems.clear();
}
}

View File

@ -132,7 +132,7 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
@Override
public SortedList<File> loadInBackground() {
File[] listFiles = currentPath.listFiles();
File[] listFiles = mCurrentPath.listFiles();
final int initCap = listFiles == null ? 0 : listFiles.length;
SortedList<File> files = new SortedList<>(File.class, new SortedListAdapterCallback<File>(getDummyAdapter()) {
@ -174,12 +174,12 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
super.onStartLoading();
// handle if directory does not exist. Fall back to root.
if (currentPath == null || !currentPath.isDirectory()) {
currentPath = getRoot();
if (mCurrentPath == null || !mCurrentPath.isDirectory()) {
mCurrentPath = getRoot();
}
// Start watching for changes
fileObserver = new FileObserver(currentPath.getPath(),
fileObserver = new FileObserver(mCurrentPath.getPath(),
FileObserver.CREATE |
FileObserver.DELETE
| FileObserver.MOVED_FROM | FileObserver.MOVED_TO
@ -220,10 +220,10 @@ public class FilePickerFragment extends AbstractFilePickerFragment<File> {
*/
@Override
public void onNewFolder(final String name) {
File folder = new File(currentPath, name);
File folder = new File(mCurrentPath, name);
if (folder.mkdir()) {
currentPath = folder;
mCurrentPath = folder;
refresh();
} else {
Toast.makeText(getActivity(), R.string.nnf_create_folder_error,

View File

@ -24,7 +24,7 @@
tools:context=".FilePickerActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/picker_toolbar"
android:id="@+id/nnf_picker_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
@ -33,7 +33,7 @@
android:theme="?nnf_toolbarTheme">
<TextView
android:id="@+id/current_dir"
android:id="@+id/nnf_current_dir"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="start"
@ -45,19 +45,19 @@
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/button_container"
android:layout_below="@+id/picker_toolbar"
tools:listitem="@layout/filepicker_listitem_dir" />
android:layout_above="@+id/nnf_button_container"
android:layout_below="@+id/nnf_picker_toolbar"
tools:listitem="@layout/nnf_filepicker_listitem_dir" />
<LinearLayout
android:id="@+id/button_container"
android:id="@+id/nnf_button_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/button_cancel"
android:id="@+id/nnf_button_cancel"
style="?android:attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="48dp"
@ -65,7 +65,7 @@
android:text="@android:string/cancel" />
<Button
android:id="@+id/button_ok"
android:id="@+id/nnf_button_ok"
style="?android:attr/borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="48dp"

View File

@ -3,6 +3,7 @@
- Added two base themes for convenience.
- Now possible to specify a specific Toolbar-theme separate from the rest
of your theme.
- Now possible to override toolbar behaviour in the fragment.
# 2.1

View File

@ -56,7 +56,7 @@ public class DropboxFilePickerFragment
@Override
public void onNewFolder(final String name) {
File folder = new File(currentPath.path, name);
File folder = new File(mCurrentPath.path, name);
if (folderCreator == null) {
folderCreator = new FolderCreator();
@ -147,13 +147,13 @@ public class DropboxFilePickerFragment
try {
if (!dbApi.metadata(currentPath.path, 1, null, false,
if (!dbApi.metadata(mCurrentPath.path, 1, null, false,
null).isDir) {
currentPath = getRoot();
mCurrentPath = getRoot();
}
DropboxAPI.Entry dirEntry =
dbApi.metadata(currentPath.path, 0, null, true,
dbApi.metadata(mCurrentPath.path, 0, null, true,
null);
files.beginBatchedUpdates();
@ -179,8 +179,8 @@ public class DropboxFilePickerFragment
protected void onStartLoading() {
super.onStartLoading();
if (currentPath == null || !currentPath.isDir) {
currentPath = getRoot();
if (mCurrentPath == null || !mCurrentPath.isDir) {
mCurrentPath = getRoot();
}
forceLoad();
@ -203,7 +203,7 @@ public class DropboxFilePickerFragment
for (String path : paths) {
try {
dbApi.createFolder(path);
currentPath = dbApi.metadata(path, 1, null, false, null);
mCurrentPath = dbApi.metadata(path, 1, null, false, null);
refresh();
} catch (DropboxException e) {
Toast.makeText(getActivity(), R.string.nnf_create_folder_error,