From c31ae4d5e088270223183acfc83faf4268297bdf Mon Sep 17 00:00:00 2001 From: linus_lee Date: Thu, 2 Oct 2014 12:41:23 -0700 Subject: [PATCH] Eleven: Add loading dialogs to all fragments Some fragments intentionally don't show the loading dialog on recreate to prevent a split second flash on the screen Loading is delayed by 300ms for better user experience Fixed a small bug in the RecentStore https://cyanogen.atlassian.net/browse/MUSIC-63 Change-Id: I5bd7ee25234d0146887f152bbcb57fed6bbb2c01 --- res/layout/activity_album_detail.xml | 3 + res/layout/activity_artist_detail.xml | 3 + res/layout/grid_base.xml | 2 +- res/layout/list_base.xml | 2 +- res/layout/loading_empty_container.xml | 23 +++++++ res/layout/playlist_detail.xml | 7 --- .../eleven/adapters/AlbumDetailSongAdapter.java | 3 +- .../eleven/adapters/ArtistDetailSongAdapter.java | 3 +- .../cyngn/eleven/adapters/DetailSongAdapter.java | 14 ++--- .../eleven/adapters/IEmptyAdapterCallback.java | 8 --- src/com/cyngn/eleven/provider/RecentStore.java | 2 +- .../eleven/sectionadapter/SectionAdapter.java | 2 + .../cyngn/eleven/ui/activities/SearchActivity.java | 33 +++++----- .../eleven/ui/fragments/AlbumDetailFragment.java | 22 +++++-- .../cyngn/eleven/ui/fragments/AlbumFragment.java | 17 ++++-- .../eleven/ui/fragments/ArtistDetailFragment.java | 20 ++++-- .../cyngn/eleven/ui/fragments/ArtistFragment.java | 16 +++-- .../ui/fragments/PlaylistDetailFragment.java | 32 +++++++--- .../eleven/ui/fragments/PlaylistFragment.java | 13 ++++ .../cyngn/eleven/ui/fragments/QueueFragment.java | 29 ++++++--- .../cyngn/eleven/ui/fragments/RecentFragment.java | 5 +- .../cyngn/eleven/ui/fragments/SongFragment.java | 3 + .../ui/fragments/profile/BasicSongFragment.java | 24 +++++--- .../ui/fragments/profile/LastAddedFragment.java | 3 + .../ui/fragments/profile/TopTracksFragment.java | 3 + .../eleven/widgets/LoadingEmptyContainer.java | 71 ++++++++++++++++++++++ 26 files changed, 271 insertions(+), 92 deletions(-) create mode 100644 res/layout/loading_empty_container.xml delete mode 100644 src/com/cyngn/eleven/adapters/IEmptyAdapterCallback.java create mode 100644 src/com/cyngn/eleven/widgets/LoadingEmptyContainer.java diff --git a/res/layout/activity_album_detail.xml b/res/layout/activity_album_detail.xml index 4cd98a0..2f4a060 100644 --- a/res/layout/activity_album_detail.xml +++ b/res/layout/activity_album_detail.xml @@ -90,6 +90,9 @@ android:textColor="@color/default_text_color" /> + + + + + layout="@layout/loading_empty_container" /> + layout="@layout/loading_empty_container" /> + + + + + + + + diff --git a/res/layout/playlist_detail.xml b/res/layout/playlist_detail.xml index 0ec4e50..1a43d3d 100644 --- a/res/layout/playlist_detail.xml +++ b/res/layout/playlist_detail.xml @@ -7,13 +7,6 @@ android:layout_height="match_parent"> - - > onCreateLoader(int id, Bundle args) { + onLoading(); return new AlbumSongLoader(mActivity, args.getLong(Config.ID)); } diff --git a/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java b/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java index c24ba7e..384aa9a 100644 --- a/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java +++ b/src/com/cyngn/eleven/adapters/ArtistDetailSongAdapter.java @@ -15,7 +15,7 @@ import com.cyngn.eleven.model.Song; import java.util.List; -public class ArtistDetailSongAdapter extends DetailSongAdapter { +public abstract class ArtistDetailSongAdapter extends DetailSongAdapter { public ArtistDetailSongAdapter(Activity activity) { super(activity); @@ -25,6 +25,7 @@ public class ArtistDetailSongAdapter extends DetailSongAdapter { @Override // LoaderCallbacks public Loader> onCreateLoader(int id, Bundle args) { + onLoading(); return new ArtistSongLoader(mActivity, args.getLong(Config.ID)); } diff --git a/src/com/cyngn/eleven/adapters/DetailSongAdapter.java b/src/com/cyngn/eleven/adapters/DetailSongAdapter.java index a3b2df2..bed1956 100644 --- a/src/com/cyngn/eleven/adapters/DetailSongAdapter.java +++ b/src/com/cyngn/eleven/adapters/DetailSongAdapter.java @@ -23,13 +23,12 @@ import java.util.Collections; import java.util.List; public abstract class DetailSongAdapter extends BaseAdapter -implements LoaderCallbacks>, OnItemClickListener, IPopupMenuCallback { + implements LoaderCallbacks>, OnItemClickListener, IPopupMenuCallback { protected final Activity mActivity; private final ImageFetcher mImageFetcher; private final LayoutInflater mInflater; private List mSongs = Collections.emptyList(); private IListener mListener; - private IEmptyAdapterCallback mEmptyCallback; public DetailSongAdapter(final Activity activity) { mActivity = activity; @@ -64,6 +63,8 @@ implements LoaderCallbacks>, OnItemClickListener, IPopupMenuCallback } protected abstract int rowLayoutId(); + protected abstract void onLoading(); + protected abstract void onNoResults(); @Override // OnItemClickListener public void onItemClick(AdapterView parent, View view, int pos, long id) { @@ -81,10 +82,7 @@ implements LoaderCallbacks>, OnItemClickListener, IPopupMenuCallback @Override // LoaderCallbacks public void onLoadFinished(Loader> loader, List songs) { if (songs.isEmpty()) { - if (mEmptyCallback != null) { - mEmptyCallback.onEmptyAdapter(); - } - + onNoResults(); return; } mSongs = songs; @@ -103,10 +101,6 @@ implements LoaderCallbacks>, OnItemClickListener, IPopupMenuCallback mListener = listener; } - public void setOnEmptyAdapterListener(IEmptyAdapterCallback callback) { - mEmptyCallback = callback; - } - protected abstract Holder newHolder(View root, ImageFetcher fetcher); protected static abstract class Holder { diff --git a/src/com/cyngn/eleven/adapters/IEmptyAdapterCallback.java b/src/com/cyngn/eleven/adapters/IEmptyAdapterCallback.java deleted file mode 100644 index 11b9228..0000000 --- a/src/com/cyngn/eleven/adapters/IEmptyAdapterCallback.java +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (C) 2014 Cyanogen, Inc. - */ -package com.cyngn.eleven.adapters; - -public interface IEmptyAdapterCallback { - public void onEmptyAdapter(); -} diff --git a/src/com/cyngn/eleven/provider/RecentStore.java b/src/com/cyngn/eleven/provider/RecentStore.java index 285d53e..860c6e3 100644 --- a/src/com/cyngn/eleven/provider/RecentStore.java +++ b/src/com/cyngn/eleven/provider/RecentStore.java @@ -90,7 +90,7 @@ public class RecentStore { // if our db is too large, delete the extra items Cursor oldest = null; try { - database.query(RecentStoreColumns.NAME, + oldest = database.query(RecentStoreColumns.NAME, new String[]{RecentStoreColumns.TIMEPLAYED}, null, null, null, null, RecentStoreColumns.TIMEPLAYED + " ASC"); diff --git a/src/com/cyngn/eleven/sectionadapter/SectionAdapter.java b/src/com/cyngn/eleven/sectionadapter/SectionAdapter.java index 1a7f872..3af7245 100644 --- a/src/com/cyngn/eleven/sectionadapter/SectionAdapter.java +++ b/src/com/cyngn/eleven/sectionadapter/SectionAdapter.java @@ -360,6 +360,7 @@ public class SectionAdapter> loader) { + mAdapter.unload(); } /** @@ -593,7 +597,7 @@ public class SearchActivity extends FragmentActivity implements mSearchHistoryListView.setVisibility(View.INVISIBLE); mListView.setVisibility(View.INVISIBLE); - mNoResultsContainer.setVisibility(View.INVISIBLE); + mLoadingEmptyContainer.setVisibility(View.INVISIBLE); switch (mCurrentState) { case SearchHistory: @@ -603,11 +607,12 @@ public class SearchActivity extends FragmentActivity implements mListView.setVisibility(View.VISIBLE); break; case Empty: - mNoResultsContainer.setVisibility(View.VISIBLE); + mLoadingEmptyContainer.setVisibility(View.VISIBLE); + mLoadingEmptyContainer.showNoResults(); break; - default: - // Don't show anything for now - we need a loading screen - // see bug: https://cyanogen.atlassian.net/browse/MUSIC-63 + case Loading: + mLoadingEmptyContainer.setVisibility(View.VISIBLE); + mLoadingEmptyContainer.showLoading(); break; } } @@ -972,7 +977,7 @@ public class SearchActivity extends FragmentActivity implements @Override public void onLoaderReset(Loader> cursorAdapterLoader) { - + ((ArrayAdapter)mSearchHistoryListView.getAdapter()).clear(); } } diff --git a/src/com/cyngn/eleven/ui/fragments/AlbumDetailFragment.java b/src/com/cyngn/eleven/ui/fragments/AlbumDetailFragment.java index def092d..40de324 100644 --- a/src/com/cyngn/eleven/ui/fragments/AlbumDetailFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/AlbumDetailFragment.java @@ -19,6 +19,7 @@ import com.cyngn.eleven.utils.GenreFetcher; import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.utils.SongPopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import com.cyngn.eleven.widgets.PopupMenuButton; import java.util.List; @@ -36,6 +37,7 @@ public class AlbumDetailFragment extends BaseFragment { private long mAlbumId; private String mArtistName; private String mAlbumName; + private LoadingEmptyContainer mLoadingEmptyContainer; @Override protected int getLayoutToInflate() { @@ -123,7 +125,17 @@ public class AlbumDetailFragment extends BaseFragment { private void setupSongList() { mSongs = (ListView)mRootView.findViewById(R.id.songs); - mSongAdapter = new AlbumDetailSongAdapter(getActivity(), this); + mSongAdapter = new AlbumDetailSongAdapter(getActivity(), this) { + @Override + protected void onLoading() { + mLoadingEmptyContainer.showLoading(); + } + + @Override + protected void onNoResults() { + getContainingActivity().postRemoveFragment(AlbumDetailFragment.this); + } + }; mSongAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() { @Override public void onPopupMenuClicked(View v, int position) { @@ -132,6 +144,9 @@ public class AlbumDetailFragment extends BaseFragment { }); mSongs.setAdapter(mSongAdapter); mSongs.setOnItemClickListener(mSongAdapter); + mLoadingEmptyContainer = + (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + mSongs.setEmptyView(mLoadingEmptyContainer); } /** called back by song loader */ @@ -143,10 +158,7 @@ public class AlbumDetailFragment extends BaseFragment { /** use the first song on the album to get a genre */ if(!songs.isEmpty()) { - GenreFetcher.fetch(getActivity(), (int)songs.get(0).mSongId, mGenre); - } else { - // no songs, remove from stack - getContainingActivity().postRemoveFragment(this); + GenreFetcher.fetch(getActivity(), (int) songs.get(0).mSongId, mGenre); } } diff --git a/src/com/cyngn/eleven/ui/fragments/AlbumFragment.java b/src/com/cyngn/eleven/ui/fragments/AlbumFragment.java index ea0e12e..cbb148d 100644 --- a/src/com/cyngn/eleven/ui/fragments/AlbumFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/AlbumFragment.java @@ -42,6 +42,7 @@ import com.cyngn.eleven.utils.MusicUtils; import com.cyngn.eleven.utils.NavUtils; import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import com.cyngn.eleven.widgets.NoResultsContainer; import com.viewpagerindicator.TitlePageIndicator; @@ -79,6 +80,11 @@ public class AlbumFragment extends MusicBrowserFragment implements */ private PopupMenuHelper mPopupMenuHelper; + /** + * This holds the loading progress bar as well as the no results message + */ + private LoadingEmptyContainer mLoadingEmptyContainer; + @Override public int getLoaderId() { return PagerAdapter.MusicFragments.ALBUM.ordinal(); @@ -183,6 +189,7 @@ public class AlbumFragment extends MusicBrowserFragment implements */ @Override public Loader> onCreateLoader(final int id, final Bundle args) { + mLoadingEmptyContainer.showLoading(); // if we ever decide to add section headers for grid items, we can pass a compartor // instead of null return new SectionCreator(getActivity(), new AlbumLoader(getActivity()), null); @@ -196,9 +203,7 @@ public class AlbumFragment extends MusicBrowserFragment implements final SectionListContainer data) { // Check for any errors if (data.mListResults.isEmpty()) { - // Set the empty text - final NoResultsContainer empty = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container); - mGridView.setEmptyView(empty); + mLoadingEmptyContainer.showNoResults(); return; } @@ -253,7 +258,7 @@ public class AlbumFragment extends MusicBrowserFragment implements public void refresh() { // Wait a moment for the preference to change. SystemClock.sleep(10); - restartLoader(null, this); + restartLoader(); } /** @@ -316,5 +321,9 @@ public class AlbumFragment extends MusicBrowserFragment implements } else { mGridView.setNumColumns(TWO); } + + // Show progress bar + mLoadingEmptyContainer = (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + mGridView.setEmptyView(mLoadingEmptyContainer); } } diff --git a/src/com/cyngn/eleven/ui/fragments/ArtistDetailFragment.java b/src/com/cyngn/eleven/ui/fragments/ArtistDetailFragment.java index 25d6c39..7b0c049 100644 --- a/src/com/cyngn/eleven/ui/fragments/ArtistDetailFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/ArtistDetailFragment.java @@ -14,15 +14,14 @@ import com.cyngn.eleven.Config; import com.cyngn.eleven.R; import com.cyngn.eleven.adapters.ArtistDetailAlbumAdapter; import com.cyngn.eleven.adapters.ArtistDetailSongAdapter; -import com.cyngn.eleven.adapters.IEmptyAdapterCallback; import com.cyngn.eleven.cache.ImageFetcher; -import com.cyngn.eleven.lastfm.Artist; import com.cyngn.eleven.menu.FragmentMenuItems; import com.cyngn.eleven.model.Album; import com.cyngn.eleven.model.Song; import com.cyngn.eleven.utils.AlbumPopupMenuHelper; import com.cyngn.eleven.utils.SongPopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import java.util.TreeSet; @@ -41,6 +40,8 @@ public class ArtistDetailFragment extends DetailFragment { private SongPopupMenuHelper mSongPopupMenuHelper; private AlbumPopupMenuHelper mAlbumPopupMenuHelper; + private LoadingEmptyContainer mLoadingEmptyContainer; + @Override protected int getLayoutToInflate() { return R.layout.activity_artist_detail; } @@ -94,15 +95,19 @@ public class ArtistDetailFragment extends DetailFragment { inflate(R.layout.artist_detail_header, mSongs, false); mSongs.addHeaderView(mHeader); mSongs.setOnScrollListener(this); - mSongAdapter = new ArtistDetailSongAdapter(getActivity()); - mSongAdapter.setOnEmptyAdapterListener(new IEmptyAdapterCallback() { + mSongAdapter = new ArtistDetailSongAdapter(getActivity()) { + @Override + protected void onLoading() { + mLoadingEmptyContainer.showLoading(); + } + @Override - public void onEmptyAdapter() { + protected void onNoResults() { // no results - because the user deleted the last item - pop our fragment // from the stack getContainingActivity().postRemoveFragment(ArtistDetailFragment.this); } - }); + }; mSongAdapter.setPopupMenuClickedListener(new IPopupMenuCallback.IListener() { @Override public void onPopupMenuClicked(View v, int position) { @@ -111,6 +116,9 @@ public class ArtistDetailFragment extends DetailFragment { }); mSongs.setAdapter(mSongAdapter); mSongs.setOnItemClickListener(mSongAdapter); + mLoadingEmptyContainer = + (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + mSongs.setEmptyView(mLoadingEmptyContainer); } private void setupPopupMenuHelpers() { diff --git a/src/com/cyngn/eleven/ui/fragments/ArtistFragment.java b/src/com/cyngn/eleven/ui/fragments/ArtistFragment.java index 20cae3d..e1507a2 100644 --- a/src/com/cyngn/eleven/ui/fragments/ArtistFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/ArtistFragment.java @@ -45,6 +45,7 @@ import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.utils.SectionCreatorUtils; import com.cyngn.eleven.utils.SectionCreatorUtils.IItemCompare; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import com.cyngn.eleven.widgets.NoResultsContainer; import com.viewpagerindicator.TitlePageIndicator; @@ -78,6 +79,11 @@ public class ArtistFragment extends MusicBrowserFragment implements private PopupMenuHelper mPopupMenuHelper; /** + * Loading container and no results container + */ + private LoadingEmptyContainer mLoadingEmptyContainer; + + /** * Empty constructor as per the {@link Fragment} documentation */ public ArtistFragment() { @@ -209,6 +215,7 @@ public class ArtistFragment extends MusicBrowserFragment implements */ @Override public Loader> onCreateLoader(final int id, final Bundle args) { + mLoadingEmptyContainer.showLoading(); final Context context = getActivity(); IItemCompare comparator = SectionCreatorUtils.createArtistComparison(context); return new SectionCreator(getActivity(), new ArtistLoader(context), comparator); @@ -222,9 +229,7 @@ public class ArtistFragment extends MusicBrowserFragment implements final SectionListContainer data) { // Check for any errors if (data.mListResults.isEmpty()) { - // Set the empty text - final NoResultsContainer empty = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container); - mListView.setEmptyView(empty); + mLoadingEmptyContainer.showNoResults(); return; } @@ -279,7 +284,7 @@ public class ArtistFragment extends MusicBrowserFragment implements public void refresh() { // Wait a moment for the preference to change. SystemClock.sleep(10); - restartLoader(null, this); + restartLoader(); } /** @@ -335,6 +340,9 @@ public class ArtistFragment extends MusicBrowserFragment implements mListView = (ListView)mRootView.findViewById(R.id.list_base); // Set the data behind the list mListView.setAdapter(mAdapter); + // set the loading and empty view container + mLoadingEmptyContainer = (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + mListView.setEmptyView(mLoadingEmptyContainer); // Set up the helpers initAbsListView(mListView); } diff --git a/src/com/cyngn/eleven/ui/fragments/PlaylistDetailFragment.java b/src/com/cyngn/eleven/ui/fragments/PlaylistDetailFragment.java index 8584486..0afec03 100644 --- a/src/com/cyngn/eleven/ui/fragments/PlaylistDetailFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/PlaylistDetailFragment.java @@ -30,6 +30,7 @@ import com.cyngn.eleven.utils.MusicUtils; import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.utils.SongPopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import com.cyngn.eleven.widgets.NoResultsContainer; import java.util.ArrayList; @@ -51,7 +52,7 @@ public class PlaylistDetailFragment extends DetailFragment implements private View mHeaderContainer; private ImageView mPlaylistImageView; - private NoResultsContainer mNoResultsContainer; + private LoadingEmptyContainer mLoadingEmptyContainer; private TextView mNumberOfSongs; private TextView mDurationOfPlaylist; @@ -82,7 +83,6 @@ public class PlaylistDetailFragment extends DetailFragment implements setupHero(); setupSongList(); - setupNoResultsContainer(); } @Override @@ -167,12 +167,21 @@ public class PlaylistDetailFragment extends DetailFragment implements mListView.setVerticalScrollBarEnabled(false); mListView.setFastScrollEnabled(false); mListView.setPadding(0, 0, 0, 0); + + // Adjust the progress bar padding to account for the header + int padTop = getResources().getDimensionPixelSize(R.dimen.playlist_detail_header_height); + mRootView.findViewById(R.id.progressbar).setPadding(0, padTop, 0, 0); + + // set the loading and empty view container + mLoadingEmptyContainer = + (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + setupNoResultsContainer(mLoadingEmptyContainer.getNoResultsContainer()); + mListView.setEmptyView(mLoadingEmptyContainer); } - private void setupNoResultsContainer() { - mNoResultsContainer = (NoResultsContainer)mRootView.findViewById(R.id.no_results_container); - mNoResultsContainer.setMainText(R.string.empty_playlist_main); - mNoResultsContainer.setSecondaryText(R.string.empty_playlist_secondary); + private void setupNoResultsContainer(final NoResultsContainer container) { + container.setMainText(R.string.empty_playlist_main); + container.setSecondaryText(R.string.empty_playlist_secondary); } /** @@ -256,18 +265,18 @@ public class PlaylistDetailFragment extends DetailFragment implements @Override public Loader> onCreateLoader(int i, Bundle bundle) { + mLoadingEmptyContainer.showLoading(); + return new PlaylistSongLoader(getActivity(), mPlaylistId); } @Override public void onLoadFinished(final Loader> loader, final List data) { if (data.isEmpty()) { - // set the empty view - only do it here so we don't see the empty view by default - // while the list is loading - mListView.setEmptyView(mNoResultsContainer); + mLoadingEmptyContainer.showNoResults(); // hide the header container - mHeaderContainer.setVisibility(View.GONE); + mHeaderContainer.setVisibility(View.INVISIBLE); // Return the correct count mAdapter.setCount(new ArrayList()); @@ -308,6 +317,9 @@ public class PlaylistDetailFragment extends DetailFragment implements @Override public void restartLoader() { + // unload the adapter - this will also get the loading progress bar to show + mAdapter.unload(); + getLoaderManager().restartLoader(0, getArguments(), this); } } \ No newline at end of file diff --git a/src/com/cyngn/eleven/ui/fragments/PlaylistFragment.java b/src/com/cyngn/eleven/ui/fragments/PlaylistFragment.java index b8c639b..81bf19a 100644 --- a/src/com/cyngn/eleven/ui/fragments/PlaylistFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/PlaylistFragment.java @@ -42,6 +42,7 @@ import com.cyngn.eleven.utils.MusicUtils; import com.cyngn.eleven.utils.NavUtils; import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import java.util.List; @@ -70,6 +71,11 @@ public class PlaylistFragment extends MusicBrowserFragment implements private PopupMenuHelper mPopupMenuHelper; /** + * This holds the loading progress bar as well as the no results message + */ + private LoadingEmptyContainer mLoadingEmptyContainer; + + /** * Empty constructor as per the {@link Fragment} documentation */ public PlaylistFragment() { @@ -149,6 +155,10 @@ public class PlaylistFragment extends MusicBrowserFragment implements mListView.setRecyclerListener(new RecycleHolder()); // Play the selected song mListView.setOnItemClickListener(this); + // Setup the loading and empty state + mLoadingEmptyContainer = + (LoadingEmptyContainer)rootView.findViewById(R.id.loading_empty_container); + mListView.setEmptyView(mLoadingEmptyContainer); // Register the music status listener ((BaseActivity)getActivity()).setMusicStateListenerListener(this); @@ -197,6 +207,8 @@ public class PlaylistFragment extends MusicBrowserFragment implements */ @Override public Loader> onCreateLoader(final int id, final Bundle args) { + // show the loading progress bar + mLoadingEmptyContainer.showLoading(); return new PlaylistLoader(getActivity()); } @@ -207,6 +219,7 @@ public class PlaylistFragment extends MusicBrowserFragment implements public void onLoadFinished(final Loader> loader, final List data) { // Check for any errors if (data.isEmpty()) { + mLoadingEmptyContainer.showNoResults(); return; } diff --git a/src/com/cyngn/eleven/ui/fragments/QueueFragment.java b/src/com/cyngn/eleven/ui/fragments/QueueFragment.java index c42972f..2fc5117 100644 --- a/src/com/cyngn/eleven/ui/fragments/QueueFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/QueueFragment.java @@ -29,6 +29,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; +import android.widget.ProgressBar; import com.cyngn.eleven.MusicPlaybackService; import com.cyngn.eleven.R; @@ -47,6 +48,7 @@ import com.cyngn.eleven.utils.MusicUtils; import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; import com.cyngn.eleven.widgets.NoResultsContainer; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import com.cyngn.eleven.widgets.PlayPauseProgressButton; import java.lang.ref.WeakReference; @@ -90,9 +92,17 @@ public class QueueFragment extends Fragment implements LoaderCallbacks> onCreateLoader(final int id, final Bundle args) { + mLoadingEmptyContainer.showLoading(); return new QueueLoader(getActivity()); } @@ -309,13 +326,7 @@ public class QueueFragment extends Fragment implements LoaderCallbacks> onCreateLoader(final int id, final Bundle args) { + // show the loading progress bar + mLoadingEmptyContainer.showLoading(); + TopTracksLoader loader = new TopTracksLoader(getActivity(), TopTracksLoader.QueryType.RecentSongs); return new SectionCreator(getActivity(), loader, null); @@ -62,7 +65,7 @@ public class RecentFragment extends BasicSongFragment implements ISetupActionBar @Override public void onMetaChanged() { // refresh the list since a track playing means it should be recently played - getLoaderManager().restartLoader(LOADER, null, this); + restartLoader(); } @Override diff --git a/src/com/cyngn/eleven/ui/fragments/SongFragment.java b/src/com/cyngn/eleven/ui/fragments/SongFragment.java index aaaa37f..0024314 100644 --- a/src/com/cyngn/eleven/ui/fragments/SongFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/SongFragment.java @@ -51,6 +51,9 @@ public class SongFragment extends BasicSongFragment { */ @Override public Loader> onCreateLoader(final int id, final Bundle args) { + // show the loading progress bar + mLoadingEmptyContainer.showLoading(); + // get the context Context context = getActivity(); diff --git a/src/com/cyngn/eleven/ui/fragments/profile/BasicSongFragment.java b/src/com/cyngn/eleven/ui/fragments/profile/BasicSongFragment.java index 830033e..1b8b781 100644 --- a/src/com/cyngn/eleven/ui/fragments/profile/BasicSongFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/profile/BasicSongFragment.java @@ -37,6 +37,7 @@ import com.cyngn.eleven.ui.activities.BaseActivity; import com.cyngn.eleven.utils.PopupMenuHelper; import com.cyngn.eleven.utils.SongPopupMenuHelper; import com.cyngn.eleven.widgets.IPopupMenuCallback; +import com.cyngn.eleven.widgets.LoadingEmptyContainer; import com.cyngn.eleven.widgets.NoResultsContainer; import java.util.TreeSet; @@ -67,7 +68,12 @@ public abstract class BasicSongFragment extends Fragment implements /** * Pop up menu helper */ - private PopupMenuHelper mPopupMenuHelper; + protected PopupMenuHelper mPopupMenuHelper; + + /** + * This holds the loading progress bar as well as the no results message + */ + protected LoadingEmptyContainer mLoadingEmptyContainer; /** * Empty constructor as per the {@link Fragment} documentation @@ -146,6 +152,12 @@ public abstract class BasicSongFragment extends Fragment implements } }); + // Show progress bar + mLoadingEmptyContainer = (LoadingEmptyContainer)mRootView.findViewById(R.id.loading_empty_container); + // Setup the container strings + setupNoResultsContainer(mLoadingEmptyContainer.getNoResultsContainer()); + mListView.setEmptyView(mLoadingEmptyContainer); + // Register the music status listener ((BaseActivity)getActivity()).setMusicStateListenerListener(this); @@ -194,13 +206,7 @@ public abstract class BasicSongFragment extends Fragment implements final SectionListContainer data) { // Check for any errors if (data.mListResults.isEmpty()) { - // Set the empty text - final NoResultsContainer empty = - (NoResultsContainer)mRootView.findViewById(R.id.no_results_container); - // Setup the container strings - setupNoResultsContainer(empty); - // set the empty view into the list view - mListView.setEmptyView(empty); + mLoadingEmptyContainer.showNoResults(); return; } @@ -214,7 +220,7 @@ public abstract class BasicSongFragment extends Fragment implements public void refresh() { // Wait a moment for the preference to change. SystemClock.sleep(10); - getFragmentLoaderManager().restartLoader(getLoaderId(), null, this); + restartLoader(); } /** diff --git a/src/com/cyngn/eleven/ui/fragments/profile/LastAddedFragment.java b/src/com/cyngn/eleven/ui/fragments/profile/LastAddedFragment.java index 07e4e69..92493ad 100644 --- a/src/com/cyngn/eleven/ui/fragments/profile/LastAddedFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/profile/LastAddedFragment.java @@ -44,6 +44,9 @@ public class LastAddedFragment extends BasicSongFragment implements ISetupAction */ @Override public Loader> onCreateLoader(final int id, final Bundle args) { + // show the loading progress bar + mLoadingEmptyContainer.showLoading(); + LastAddedLoader loader = new LastAddedLoader(getActivity()); return new SectionCreator(getActivity(), loader, null); } diff --git a/src/com/cyngn/eleven/ui/fragments/profile/TopTracksFragment.java b/src/com/cyngn/eleven/ui/fragments/profile/TopTracksFragment.java index 0460f40..7fbf413 100644 --- a/src/com/cyngn/eleven/ui/fragments/profile/TopTracksFragment.java +++ b/src/com/cyngn/eleven/ui/fragments/profile/TopTracksFragment.java @@ -49,6 +49,9 @@ public class TopTracksFragment extends BasicSongFragment implements ISetupAction */ @Override public Loader> onCreateLoader(final int id, final Bundle args) { + // show the loading progress bar + mLoadingEmptyContainer.showLoading(); + TopTracksLoader loader = new TopTracksLoader(getActivity(), TopTracksLoader.QueryType.TopTracks); return new SectionCreator(getActivity(), loader, null); diff --git a/src/com/cyngn/eleven/widgets/LoadingEmptyContainer.java b/src/com/cyngn/eleven/widgets/LoadingEmptyContainer.java new file mode 100644 index 0000000..0522439 --- /dev/null +++ b/src/com/cyngn/eleven/widgets/LoadingEmptyContainer.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2014 Cyanogen, Inc. + */ +package com.cyngn.eleven.widgets; + +import android.content.Context; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.cyngn.eleven.R; + +/** + * This class is the default empty state view for most listviews/fragments + * It allows the ability to set a main text, a main highlight text and a secondary text + * By default this container has some strings loaded, but other classes can call the apis to change + * the text + */ +public class LoadingEmptyContainer extends FrameLayout { + private static final int LOADING_DELAY = 300; + + private Handler mHandler; + private Runnable mShowLoadingRunnable; + + public LoadingEmptyContainer(Context context, AttributeSet attrs) { + super(context, attrs); + + mHandler = new Handler(); + mShowLoadingRunnable = new Runnable() { + @Override + public void run() { + findViewById(R.id.progressbar).setVisibility(View.VISIBLE); + getNoResultsContainer().setVisibility(View.INVISIBLE); + } + }; + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + hideAll(); + } + + public void hideAll() { + findViewById(R.id.progressbar).setVisibility(View.INVISIBLE); + getNoResultsContainer().setVisibility(View.INVISIBLE); + } + + public void showLoading() { + hideAll(); + + if (!mHandler.hasCallbacks(mShowLoadingRunnable)) { + mHandler.postDelayed(mShowLoadingRunnable, LOADING_DELAY); + } + } + + public void showNoResults() { + mHandler.removeCallbacks(mShowLoadingRunnable); + + findViewById(R.id.progressbar).setVisibility(View.INVISIBLE); + getNoResultsContainer().setVisibility(View.VISIBLE); + } + + public NoResultsContainer getNoResultsContainer() { + return (NoResultsContainer)findViewById(R.id.no_results_container); + } +} -- 2.11.0