123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- /**
- * ownCloud Android client application
- *
- * Copyright (C) 2012 Bartek Przybylski
- * Copyright (C) 2012-2016 ownCloud Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package com.owncloud.android.ui.fragment;
- import android.os.Bundle;
- import android.support.annotation.DrawableRes;
- import android.support.annotation.StringRes;
- import android.support.v4.app.Fragment;
- import android.support.v4.view.MenuItemCompat;
- import android.support.v4.widget.SwipeRefreshLayout;
- import android.view.GestureDetector;
- import android.support.v7.widget.SearchView;
- import android.view.LayoutInflater;
- import android.view.MotionEvent;
- import android.view.ScaleGestureDetector;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AbsListView;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.GridView;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- import com.getbase.floatingactionbutton.FloatingActionButton;
- import com.getbase.floatingactionbutton.FloatingActionsMenu;
- import com.owncloud.android.MainApp;
- import com.owncloud.android.R;
- import com.owncloud.android.lib.common.utils.Log_OC;
- import com.owncloud.android.ui.ExtendedListView;
- import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
- import com.owncloud.android.ui.adapter.FilterableListAdapter;
- import java.util.ArrayList;
- import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
- public class ExtendedListFragment extends Fragment
- implements OnItemClickListener, OnEnforceableRefreshListener, SearchView.OnQueryTextListener {
- protected static final String TAG = ExtendedListFragment.class.getSimpleName();
- protected static final String KEY_SAVED_LIST_POSITION = "SAVED_LIST_POSITION";
- private static final String KEY_INDEXES = "INDEXES";
- private static final String KEY_FIRST_POSITIONS= "FIRST_POSITIONS";
- private static final String KEY_TOPS = "TOPS";
- private static final String KEY_HEIGHT_CELL = "HEIGHT_CELL";
- private static final String KEY_EMPTY_LIST_MESSAGE = "EMPTY_LIST_MESSAGE";
- private static final String KEY_IS_GRID_VISIBLE = "IS_GRID_VISIBLE";
- private ScaleGestureDetector SGD = null;
- protected SwipeRefreshLayout mRefreshListLayout;
- private SwipeRefreshLayout mRefreshGridLayout;
- protected SwipeRefreshLayout mRefreshEmptyLayout;
- protected LinearLayout mEmptyListContainer;
- protected TextView mEmptyListMessage;
- protected TextView mEmptyListHeadline;
- protected ImageView mEmptyListIcon;
- protected ProgressBar mEmptyListProgress;
- private FloatingActionsMenu mFabMain;
- private FloatingActionButton mFabUpload;
- private FloatingActionButton mFabMkdir;
- private FloatingActionButton mFabUploadFromApp;
- // Save the state of the scroll in browsing
- private ArrayList<Integer> mIndexes;
- private ArrayList<Integer> mFirstPositions;
- private ArrayList<Integer> mTops;
- private int mHeightCell = 0;
- private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = null;
- protected AbsListView mCurrentListView;
- private ExtendedListView mListView;
- private View mListFooterView;
- private GridViewWithHeaderAndFooter mGridView;
- private View mGridFooterView;
- private FilterableListAdapter mAdapter;
- p private float scale = -1f;
- protected void setListAdapter(FilterableListAdapter listAdapter) {
- mAdapter = listAdapter;
- mCurrentListView.setAdapter(listAdapter);
- mCurrentListView.invalidateViews();
- }
- protected AbsListView getListView() {
- return mCurrentListView;
- }
- public FloatingActionButton getFabUpload() {
- return mFabUpload;
- }
- public FloatingActionButton getFabUploadFromApp() {
- return mFabUploadFromApp;
- }
- public FloatingActionButton getFabMkdir() {
- return mFabMkdir;
- }
- public FloatingActionsMenu getFabMain() {
- return mFabMain;
- }
- public void switchToGridView() {
- if (!isGridEnabled()) {
- mListView.setAdapter(null);
- mRefreshListLayout.setVisibility(View.GONE);
- mRefreshGridLayout.setVisibility(View.VISIBLE);
- mCurrentListView = mGridView;
- setListAdapter(mAdapter);
- }
- }
- public void switchToListView() {
- if (isGridEnabled()) {
- mGridView.setAdapter(null);
- mRefreshGridLayout.setVisibility(View.GONE);
- mRefreshListLayout.setVisibility(View.VISIBLE);
- mCurrentListView = mListView;
- setListAdapter(mAdapter);
- }
- }
- public boolean isGridEnabled(){
- return (mCurrentListView != null && mCurrentListView.equals(mGridView));
- }
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- final MenuItem item = menu.findItem(R.id.action_search);
- final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
- searchView.setOnQueryTextListener(this);
- }
- public boolean onQueryTextChange(String query) {
- mAdapter.filter(query);
- return true;
- }
- @Override
- public boolean onQueryTextSubmit(String query) {
- mAdapter.filter(query);
- return true;
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- Log_OC.d(TAG, "onCreateView");
- View v = inflater.inflate(R.layout.list_fragment, null);
- setupEmptyList(v);
- mListView = (ExtendedListView)(v.findViewById(R.id.list_root));
- mListView.setOnItemClickListener(this);
- mListFooterView = inflater.inflate(R.layout.list_footer, null, false);
- mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
- mGridView.setNumColumns(GridView.AUTO_FIT);
- mGridView.setOnItemClickListener(this);
- mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);
- SGD = new ScaleGestureDetector(MainApp.getAppContext(),new ScaleListener());
- // gestureDetector = new GestureDetector(MainApp.getAppContext(), new SingleTapConfirm());
- mGridView.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- // if (SGD.onTouchEvent(motionEvent)) {
- // return false;
- // }
- // return false;
- SGD.onTouchEvent(motionEvent);
- return false;
- }
- });
- if (savedInstanceState != null) {
- int referencePosition = savedInstanceState.getInt(KEY_SAVED_LIST_POSITION);
- if (mCurrentListView == mListView) {
- Log_OC.v(TAG, "Setting and centering around list position " + referencePosition);
- mListView.setAndCenterSelection(referencePosition);
- } else {
- Log_OC.v(TAG, "Setting grid position " + referencePosition);
- mGridView.setSelection(referencePosition);
- }
- }
- // Pull-down to refresh layout
- mRefreshListLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_list);
- mRefreshGridLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_grid);
- mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_empty);
-
- onCreateSwipeToRefresh(mRefreshListLayout);
- onCreateSwipeToRefresh(mRefreshGridLayout);
- onCreateSwipeToRefresh(mRefreshEmptyLayout);
- mListView.setEmptyView(mRefreshEmptyLayout);
- mGridView.setEmptyView(mRefreshEmptyLayout);
- mFabMain = (FloatingActionsMenu) v.findViewById(R.id.fab_main);
- mFabUpload = (FloatingActionButton) v.findViewById(R.id.fab_upload);
- mFabMkdir = (FloatingActionButton) v.findViewById(R.id.fab_mkdir);
- mFabUploadFromApp = (FloatingActionButton) v.findViewById(R.id.fab_upload_from_app);
- mCurrentListView = mListView; // list by default
- if (savedInstanceState != null) {
- if (savedInstanceState.getBoolean(KEY_IS_GRID_VISIBLE, false)) {
- switchToGridView();
- }
- int referencePosition = savedInstanceState.getInt(KEY_SAVED_LIST_POSITION);
- if (isGridEnabled()) {
- Log_OC.v(TAG, "Setting grid position " + referencePosition);
- mGridView.setSelection(referencePosition);
- } else {
- Log_OC.v(TAG, "Setting and centering around list position " + referencePosition);
- mListView.setAndCenterSelection(referencePosition);
- }
- }
- return v;
- }
- private class SingleTapConfirm extends GestureDetector.SimpleOnGestureListener {
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- return true;
- }
- }
- private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
- @Override
- public boolean onScale(ScaleGestureDetector detector) {
- if (scale == -1f){
- mGridView.setNumColumns(GridView.AUTO_FIT);
- scale = mGridView.getNumColumns();
- }
- scale *= 1-(detector.getScaleFactor()- 1);
- scale = Math.max(2.0f, Math.min(scale, 10.0f));
- Integer scaleInt = Math.round(scale);
- mGridView.setNumColumns(scaleInt);
- mGridView.invalidateViews();
- return true;
- }
- }
- protected void setupEmptyList(View view) {
- mEmptyListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
- mEmptyListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
- mEmptyListHeadline = (TextView) view.findViewById(R.id.empty_list_view_headline);
- mEmptyListIcon = (ImageView) view.findViewById(R.id.empty_list_icon);
- mEmptyListProgress = (ProgressBar) view.findViewById(R.id.empty_list_progress);
- }
- /**
- * {@inheritDoc}
- */
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- if (savedInstanceState != null) {
- mIndexes = savedInstanceState.getIntegerArrayList(KEY_INDEXES);
- mFirstPositions = savedInstanceState.getIntegerArrayList(KEY_FIRST_POSITIONS);
- mTops = savedInstanceState.getIntegerArrayList(KEY_TOPS);
- mHeightCell = savedInstanceState.getInt(KEY_HEIGHT_CELL);
- setMessageForEmptyList(savedInstanceState.getString(KEY_EMPTY_LIST_MESSAGE));
-
- } else {
- mIndexes = new ArrayList<>();
- mFirstPositions = new ArrayList<>();
- mTops = new ArrayList<>();
- mHeightCell = 0;
- }
- }
-
-
- @Override
- public void onSaveInstanceState(Bundle savedInstanceState) {
- super.onSaveInstanceState(savedInstanceState);
- Log_OC.d(TAG, "onSaveInstanceState()");
- savedInstanceState.putBoolean(KEY_IS_GRID_VISIBLE, isGridEnabled());
- savedInstanceState.putInt(KEY_SAVED_LIST_POSITION, getReferencePosition());
- savedInstanceState.putIntegerArrayList(KEY_INDEXES, mIndexes);
- savedInstanceState.putIntegerArrayList(KEY_FIRST_POSITIONS, mFirstPositions);
- savedInstanceState.putIntegerArrayList(KEY_TOPS, mTops);
- savedInstanceState.putInt(KEY_HEIGHT_CELL, mHeightCell);
- savedInstanceState.putString(KEY_EMPTY_LIST_MESSAGE, getEmptyViewText());
- }
- /**
- * Calculates the position of the item that will be used as a reference to
- * reposition the visible items in the list when the device is turned to
- * other position.
- *
- * The current policy is take as a reference the visible item in the center
- * of the screen.
- *
- * @return The position in the list of the visible item in the center of the
- * screen.
- */
- protected int getReferencePosition() {
- if (mCurrentListView != null) {
- return (mCurrentListView.getFirstVisiblePosition() +
- mCurrentListView.getLastVisiblePosition()) / 2;
- } else {
- return 0;
- }
- }
- /*
- * Restore index and position
- */
- protected void restoreIndexAndTopPosition() {
- if (mIndexes.size() > 0) {
- // needs to be checked; not every browse-up had a browse-down before
-
- int index = mIndexes.remove(mIndexes.size() - 1);
- final int firstPosition = mFirstPositions.remove(mFirstPositions.size() -1);
- int top = mTops.remove(mTops.size() - 1);
- Log_OC.v(TAG, "Setting selection to position: " + firstPosition + "; top: "
- + top + "; index: " + index);
- if (mCurrentListView!= null && mCurrentListView.equals(mListView)) {
- if (mHeightCell*index <= mListView.getHeight()) {
- mListView.setSelectionFromTop(firstPosition, top);
- } else {
- mListView.setSelectionFromTop(index, 0);
- }
- } else {
- if (mHeightCell*index <= mGridView.getHeight()) {
- mGridView.setSelection(firstPosition);
- //mGridView.smoothScrollToPosition(firstPosition);
- } else {
- mGridView.setSelection(index);
- //mGridView.smoothScrollToPosition(index);
- }
- }
- }
- }
-
- /*
- * Save index and top position
- */
- protected void saveIndexAndTopPosition(int index) {
-
- mIndexes.add(index);
-
- int firstPosition = mCurrentListView.getFirstVisiblePosition();
- mFirstPositions.add(firstPosition);
-
- View view = mCurrentListView.getChildAt(0);
- int top = (view == null) ? 0 : view.getTop() ;
- mTops.add(top);
-
- // Save the height of a cell
- mHeightCell = (view == null || mHeightCell != 0) ? mHeightCell : view.getHeight();
- }
-
-
- @Override
- public void onItemClick (AdapterView<?> parent, View view, int position, long id) {
- // to be @overriden
- }
- @Override
- public void onRefresh() {
- mRefreshListLayout.setRefreshing(false);
- mRefreshGridLayout.setRefreshing(false);
- mRefreshEmptyLayout.setRefreshing(false);
- if (mOnRefreshListener != null) {
- mOnRefreshListener.onRefresh();
- }
- }
- public void setOnRefreshListener(OnEnforceableRefreshListener listener) {
- mOnRefreshListener = listener;
- }
-
- /**
- * Disables swipe gesture.
- *
- * Sets the 'enabled' state of the refresh layouts contained in the fragment.
- *
- * When 'false' is set, prevents user gestures but keeps the option to refresh programatically,
- *
- * @param enabled Desired state for capturing swipe gesture.
- */
- public void setSwipeEnabled(boolean enabled) {
- mRefreshListLayout.setEnabled(enabled);
- mRefreshGridLayout.setEnabled(enabled);
- mRefreshEmptyLayout.setEnabled(enabled);
- }
- /**
- * Sets the 'visibility' state of the FAB contained in the fragment.
- *
- * When 'false' is set, FAB visibility is set to View.GONE programmatically,
- *
- * @param enabled Desired visibility for the FAB.
- */
- public void setFabEnabled(boolean enabled) {
- if(enabled) {
- mFabMain.setVisibility(View.VISIBLE);
- } else {
- mFabMain.setVisibility(View.GONE);
- }
- }
- /**
- * Set message for empty list view.
- */
- public void setMessageForEmptyList(String message) {
- if (mEmptyListContainer != null && mEmptyListMessage != null) {
- mEmptyListMessage.setText(message);
- }
- }
- /**
- * displays an empty list information with a headline, a message and an icon.
- *
- * @param headline the headline
- * @param message the message
- * @param icon the icon to be shown
- */
- public void setMessageForEmptyList(@StringRes int headline, @StringRes int message, @DrawableRes int icon) {
- if (mEmptyListContainer != null && mEmptyListMessage != null) {
- mEmptyListHeadline.setText(headline);
- mEmptyListMessage.setText(message);
- mEmptyListIcon.setImageResource(icon);
- mEmptyListIcon.setVisibility(View.VISIBLE);
- mEmptyListProgress.setVisibility(View.GONE);
- }
- }
- /**
- * Set message for empty list view.
- */
- public void setEmptyListMessage() {
- setMessageForEmptyList(
- R.string.file_list_empty_headline,
- R.string.file_list_empty,
- R.drawable.ic_list_empty_folder
- );
- }
- /**
- * Set message for empty list view.
- */
- public void setEmptyListLoadingMessage() {
- if (mEmptyListContainer != null && mEmptyListMessage != null) {
- mEmptyListHeadline.setText(R.string.file_list_loading);
- mEmptyListMessage.setText("");
- mEmptyListIcon.setVisibility(View.GONE);
- mEmptyListProgress.setVisibility(View.VISIBLE);
- }
- }
- /**
- * Get the text of EmptyListMessage TextView.
- *
- * @return String empty text view text-value
- */
- public String getEmptyViewText() {
- return (mEmptyListContainer != null && mEmptyListMessage != null) ? mEmptyListMessage.getText().toString() : "";
- }
- protected void onCreateSwipeToRefresh(SwipeRefreshLayout refreshLayout) {
- // Colors in animations
- refreshLayout.setColorSchemeResources(R.color.color_accent, R.color.primary, R.color.primary_dark);
- refreshLayout.setOnRefreshListener(this);
- }
- @Override
- public void onRefresh(boolean ignoreETag) {
- mRefreshListLayout.setRefreshing(false);
- mRefreshGridLayout.setRefreshing(false);
- mRefreshEmptyLayout.setRefreshing(false);
- if (mOnRefreshListener != null) {
- mOnRefreshListener.onRefresh();
- }
- }
- protected void setChoiceMode(int choiceMode) {
- mListView.setChoiceMode(choiceMode);
- mGridView.setChoiceMode(choiceMode);
- }
- protected void setMultiChoiceModeListener(AbsListView.MultiChoiceModeListener listener) {
- mListView.setMultiChoiceModeListener(listener);
- mGridView.setMultiChoiceModeListener(listener);
- }
- /**
- * TODO doc
- * To be called before setAdapter, or GridViewWithHeaderAndFooter will throw an exception
- *
- * @param enabled flag if footer should be shown/calculated
- */
- protected void setFooterEnabled(boolean enabled) {
- if (enabled) {
- if (mGridView.getFooterViewCount() == 0 && mGridView.isCorrectAdapter()) {
- if (mGridFooterView.getParent() != null ) {
- ((ViewGroup) mGridFooterView.getParent()).removeView(mGridFooterView);
- }
- mGridView.addFooterView(mGridFooterView, null, false);
- }
- mGridFooterView.invalidate();
- if (mListView.getFooterViewsCount() == 0) {
- if (mListFooterView.getParent() != null ) {
- ((ViewGroup) mListFooterView.getParent()).removeView(mListFooterView);
- }
- mListView.addFooterView(mListFooterView, null, false);
- }
- mListFooterView.invalidate();
- } else {
- mGridView.removeFooterView(mGridFooterView);
- mListView.removeFooterView(mListFooterView);
- }
- }
- /**
- * set the list/grid footer text.
- *
- * @param text the footer text
- */
- protected void setFooterText(String text) {
- if (text != null && text.length() > 0) {
- ((TextView)mListFooterView.findViewById(R.id.footerText)).setText(text);
- ((TextView)mGridFooterView.findViewById(R.id.footerText)).setText(text);
- setFooterEnabled(true);
- } else {
- setFooterEnabled(false);
- }
- }
- }
|