From 8bfe2665ddfd033e7476839bfce0fe12a75ea7c1 Mon Sep 17 00:00:00 2001 From: Martijn Brekhof Date: Fri, 18 Mar 2016 16:58:15 +0100 Subject: [PATCH] Refactored MediaFileListFragment to support multi-/single-columns Refactored AbstractListFragment to make it more generic and allow it to be used by MediaFileListFragment. This adds support for switching between a single- and multicolumn view. Created new abstract class AbstractCursorListFragment for list fragments using a cursoradapter. --- .../kore/ui/AbstractCursorListFragment.java | 270 ++++++++++++++++++ .../xbmc/kore/ui/AbstractListFragment.java | 232 ++------------- .../org/xbmc/kore/ui/AlbumListFragment.java | 2 +- .../org/xbmc/kore/ui/ArtistListFragment.java | 3 +- .../xbmc/kore/ui/AudioGenresListFragment.java | 2 +- .../xbmc/kore/ui/MediaFileListFragment.java | 60 ++-- .../org/xbmc/kore/ui/MovieListFragment.java | 2 +- .../xbmc/kore/ui/MusicVideoListFragment.java | 2 +- .../org/xbmc/kore/ui/TVShowListFragment.java | 2 +- .../res/menu/abstractcursorlistfragment.xml | 23 ++ .../main/res/menu/abstractlistfragment.xml | 3 - 11 files changed, 345 insertions(+), 256 deletions(-) create mode 100644 app/src/main/java/org/xbmc/kore/ui/AbstractCursorListFragment.java create mode 100644 app/src/main/res/menu/abstractcursorlistfragment.xml diff --git a/app/src/main/java/org/xbmc/kore/ui/AbstractCursorListFragment.java b/app/src/main/java/org/xbmc/kore/ui/AbstractCursorListFragment.java new file mode 100644 index 0000000..88b214b --- /dev/null +++ b/app/src/main/java/org/xbmc/kore/ui/AbstractCursorListFragment.java @@ -0,0 +1,270 @@ +/* + * Copyright 2015 Martijn Brekhof. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.xbmc.kore.ui; + +import android.annotation.TargetApi; +import android.content.Intent; +import android.content.ServiceConnection; +import android.database.Cursor; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.SearchView; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; +import android.widget.Toast; + +import org.xbmc.kore.R; +import org.xbmc.kore.host.HostInfo; +import org.xbmc.kore.host.HostManager; +import org.xbmc.kore.jsonrpc.ApiException; +import org.xbmc.kore.jsonrpc.event.MediaSyncEvent; +import org.xbmc.kore.service.LibrarySyncService; +import org.xbmc.kore.service.SyncUtils; +import org.xbmc.kore.utils.LogUtils; + +import de.greenrobot.event.EventBus; + +public abstract class AbstractCursorListFragment extends AbstractListFragment + implements LoaderManager.LoaderCallbacks, + SyncUtils.OnServiceListener, + SearchView.OnQueryTextListener, + SwipeRefreshLayout.OnRefreshListener { + private static final String TAG = LogUtils.makeLogTag(AbstractCursorListFragment.class); + + private ServiceConnection serviceConnection; + + private HostInfo hostInfo; + private EventBus bus; + + private CursorAdapter adapter; + + // Loader IDs + private static final int LOADER = 0; + + // The search filter to use in the loader + private String searchFilter = null; + + abstract protected CursorLoader createCursorLoader(); + + @TargetApi(16) + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View root = super.onCreateView(inflater, container, savedInstanceState); + + bus = EventBus.getDefault(); + HostManager hostManager = HostManager.getInstance(getActivity()); + hostInfo = hostManager.getHostInfo(); + + swipeRefreshLayout.setEnabled(true); + swipeRefreshLayout.setOnRefreshListener(this); + + adapter = (CursorAdapter) getAdapter(); + + return root; + } + + @Override + public void onActivityCreated (Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + getLoaderManager().initLoader(LOADER, null, this); + } + + @Override + public void onStart() { + super.onStart(); + serviceConnection = SyncUtils.connectToLibrarySyncService(getActivity(), this); + } + + @Override + public void onResume() { + bus.register(this); + super.onResume(); + } + + @Override + public void onPause() { + bus.unregister(this); + super.onPause(); + } + + @Override + public void onStop() { + super.onStop(); + SyncUtils.disconnectFromLibrarySyncService(getActivity(), serviceConnection); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.abstractcursorlistfragment, menu); + + super.onCreateOptionsMenu(menu, inflater); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.action_refresh: + onRefresh(); + break; + } + return super.onOptionsItemSelected(item); + } + + /** + * Swipe refresh layout callback + */ + /** {@inheritDoc} */ + @Override + public void onRefresh() { + if (hostInfo != null) { + showRefreshAnimation(); + onSwipeRefresh(); + } else { + swipeRefreshLayout.setRefreshing(false); + Toast.makeText(getActivity(), R.string.no_xbmc_configured, Toast.LENGTH_SHORT) + .show(); + } + } + + /** + * Should return the {@link LibrarySyncService} SyncType that + * this list initiates + * @return {@link LibrarySyncService} SyncType + */ + abstract protected String getListSyncType(); + + /** + * Event bus post. Called when the syncing process ended + * + * @param event Refreshes data + */ + public void onEventMainThread(MediaSyncEvent event) { + onSyncProcessEnded(event); + } + + /** + * Called each time a MediaSyncEvent is received. + * @param event + */ + protected void onSyncProcessEnded(MediaSyncEvent event) { + boolean silentSync = false; + if (event.syncExtras != null) { + silentSync = event.syncExtras.getBoolean(LibrarySyncService.SILENT_SYNC, false); + } + + if (event.syncType.equals(getListSyncType())) { + swipeRefreshLayout.setRefreshing(false); + if (event.status == MediaSyncEvent.STATUS_SUCCESS) { + refreshList(); + if (!silentSync) { + Toast.makeText(getActivity(), R.string.sync_successful, Toast.LENGTH_SHORT) + .show(); + } + } else if (!silentSync) { + String msg = (event.errorCode == ApiException.API_ERROR) ? + String.format(getString(R.string.error_while_syncing), event.errorMessage) : + getString(R.string.unable_to_connect_to_xbmc); + Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onServiceConnected(LibrarySyncService librarySyncService) { + if(SyncUtils.isLibrarySyncing( + librarySyncService, + HostManager.getInstance(getActivity()).getHostInfo(), + getListSyncType())) { + showRefreshAnimation(); + } + } + + protected void onSwipeRefresh() { + LogUtils.LOGD(TAG, "Swipe, starting sync for: " + getListSyncType()); + // Start the syncing process + Intent syncIntent = new Intent(this.getActivity(), LibrarySyncService.class); + syncIntent.putExtra(getListSyncType(), true); + getActivity().startService(syncIntent); + } + + /** + * Search view callbacks + */ + /** {@inheritDoc} */ + @Override + public boolean onQueryTextChange(String newText) { + searchFilter = newText; + getLoaderManager().restartLoader(LOADER, null, this); + return true; + } + + /** {@inheritDoc} */ + @Override + public boolean onQueryTextSubmit(String newText) { + // All is handled in onQueryTextChange + return true; + } + + /** + * Loader callbacks + */ + /** {@inheritDoc} */ + @Override + public Loader onCreateLoader(int i, Bundle bundle) { + return createCursorLoader(); + } + + /** {@inheritDoc} */ + @Override + public void onLoadFinished(Loader cursorLoader, Cursor cursor) { + adapter.swapCursor(cursor); + // To prevent the empty text from appearing on the first load, set it now + emptyView.setText(getString(R.string.swipe_down_to_refresh)); + } + + /** {@inheritDoc} */ + @Override + public void onLoaderReset(Loader cursorLoader) { + adapter.swapCursor(null); + } + + + /** + * @return text entered in searchview + */ + public String getSearchFilter() { + return searchFilter; + } + + /** + * Use this to reload the items in the list + */ + public void refreshList() { + getLoaderManager().restartLoader(LOADER, null, this); + } +} diff --git a/app/src/main/java/org/xbmc/kore/ui/AbstractListFragment.java b/app/src/main/java/org/xbmc/kore/ui/AbstractListFragment.java index f233e94..efed551 100644 --- a/app/src/main/java/org/xbmc/kore/ui/AbstractListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/AbstractListFragment.java @@ -17,19 +17,12 @@ package org.xbmc.kore.ui; import android.annotation.TargetApi; -import android.content.Intent; -import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.database.Cursor; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; -import android.support.v4.app.LoaderManager; -import android.support.v4.content.CursorLoader; -import android.support.v4.content.Loader; import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.widget.SearchView; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -38,44 +31,21 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.AdapterView; -import android.widget.CursorAdapter; +import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.TextView; -import android.widget.Toast; import org.xbmc.kore.R; import org.xbmc.kore.Settings; -import org.xbmc.kore.host.HostInfo; -import org.xbmc.kore.host.HostManager; -import org.xbmc.kore.jsonrpc.ApiException; -import org.xbmc.kore.jsonrpc.event.MediaSyncEvent; -import org.xbmc.kore.service.LibrarySyncService; -import org.xbmc.kore.service.SyncUtils; import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.Utils; import butterknife.ButterKnife; import butterknife.InjectView; -import de.greenrobot.event.EventBus; -public abstract class AbstractListFragment extends Fragment - implements LoaderManager.LoaderCallbacks, - SyncUtils.OnServiceListener, - SearchView.OnQueryTextListener, - SwipeRefreshLayout.OnRefreshListener { +public abstract class AbstractListFragment extends Fragment { private static final String TAG = LogUtils.makeLogTag(AbstractListFragment.class); - - private ServiceConnection serviceConnection; - private CursorAdapter adapter; - - private HostInfo hostInfo; - private EventBus bus; - - // Loader IDs - private static final int LOADER = 0; - - // The search filter to use in the loader - private String searchFilter = null; + private BaseAdapter adapter; private boolean gridViewUsesMultipleColumns; @@ -84,8 +54,7 @@ public abstract class AbstractListFragment extends Fragment @InjectView(android.R.id.empty) TextView emptyView; abstract protected AdapterView.OnItemClickListener createOnItemClickListener(); - abstract protected CursorAdapter createAdapter(); - abstract protected CursorLoader createCursorLoader(); + abstract protected BaseAdapter createAdapter(); @TargetApi(16) @Nullable @@ -94,22 +63,25 @@ public abstract class AbstractListFragment extends Fragment ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_generic_media_list, container, false); ButterKnife.inject(this, root); - bus = EventBus.getDefault(); - HostManager hostManager = HostManager.getInstance(getActivity()); - hostInfo = hostManager.getHostInfo(); + swipeRefreshLayout.setEnabled(false); - swipeRefreshLayout.setOnRefreshListener(this); + gridView.setEmptyView(emptyView); + gridView.setOnItemClickListener(createOnItemClickListener()); + + // Configure the adapter and start the loader + adapter = createAdapter(); + gridView.setAdapter(adapter); //Listener added to be able to determine if multiple-columns is at all possible for the current grid //We use this information to enable/disable the menu item to switch between multiple and single columns gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - if(gridView.getNumColumns() > 1) { + if (gridView.getNumColumns() > 1) { gridViewUsesMultipleColumns = true; } - if(Utils.isJellybeanOrLater()) { + if (Utils.isJellybeanOrLater()) { gridView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { gridView.getViewTreeObserver().removeGlobalOnLayoutListener(this); @@ -119,47 +91,11 @@ public abstract class AbstractListFragment extends Fragment getActivity().invalidateOptionsMenu(); } }); - return root; - } - @Override - public void onActivityCreated (Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - gridView.setEmptyView(emptyView); - gridView.setOnItemClickListener(createOnItemClickListener()); - - // Configure the adapter and start the loader - adapter = createAdapter(); - gridView.setAdapter(adapter); - - getLoaderManager().initLoader(LOADER, null, this); setHasOptionsMenu(true); - } - @Override - public void onStart() { - super.onStart(); - serviceConnection = SyncUtils.connectToLibrarySyncService(getActivity(), this); - } - - @Override - public void onResume() { - bus.register(this); - super.onResume(); - } - - @Override - public void onPause() { - bus.unregister(this); - super.onPause(); - } - - @Override - public void onStop() { - super.onStop(); - SyncUtils.disconnectFromLibrarySyncService(getActivity(), serviceConnection); + return root; } @Override @@ -193,9 +129,6 @@ public abstract class AbstractListFragment extends Fragment @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { - case R.id.action_refresh: - onRefresh(); - break; case R.id.action_multi_single_columns: toggleAmountOfColumns(item); break; @@ -219,139 +152,6 @@ public abstract class AbstractListFragment extends Fragment adapter.notifyDataSetChanged(); //force gridView to redraw } - /** - * Swipe refresh layout callback - */ - /** {@inheritDoc} */ - @Override - public void onRefresh() { - if (hostInfo != null) { - showRefreshAnimation(); - onSwipeRefresh(); - } else { - swipeRefreshLayout.setRefreshing(false); - Toast.makeText(getActivity(), R.string.no_xbmc_configured, Toast.LENGTH_SHORT) - .show(); - } - } - - /** - * Should return the {@link org.xbmc.kore.service.LibrarySyncService} SyncType that - * this list initiates - * @return {@link org.xbmc.kore.service.LibrarySyncService} SyncType - */ - abstract protected String getListSyncType(); - - /** - * Event bus post. Called when the syncing process ended - * - * @param event Refreshes data - */ - public void onEventMainThread(MediaSyncEvent event) { - onSyncProcessEnded(event); - } - - /** - * Called each time a MediaSyncEvent is received. - * @param event - */ - protected void onSyncProcessEnded(MediaSyncEvent event) { - boolean silentSync = false; - if (event.syncExtras != null) { - silentSync = event.syncExtras.getBoolean(LibrarySyncService.SILENT_SYNC, false); - } - - if (event.syncType.equals(getListSyncType())) { - swipeRefreshLayout.setRefreshing(false); - if (event.status == MediaSyncEvent.STATUS_SUCCESS) { - refreshList(); - if (!silentSync) { - Toast.makeText(getActivity(), R.string.sync_successful, Toast.LENGTH_SHORT) - .show(); - } - } else if (!silentSync) { - String msg = (event.errorCode == ApiException.API_ERROR) ? - String.format(getString(R.string.error_while_syncing), event.errorMessage) : - getString(R.string.unable_to_connect_to_xbmc); - Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show(); - } - } - } - - @Override - public void onServiceConnected(LibrarySyncService librarySyncService) { - if(SyncUtils.isLibrarySyncing( - librarySyncService, - HostManager.getInstance(getActivity()).getHostInfo(), - getListSyncType())) { - showRefreshAnimation(); - } - } - - protected void onSwipeRefresh() { - LogUtils.LOGD(TAG, "Swipe, starting sync for: " + getListSyncType()); - // Start the syncing process - Intent syncIntent = new Intent(this.getActivity(), LibrarySyncService.class); - syncIntent.putExtra(getListSyncType(), true); - getActivity().startService(syncIntent); - } - - /** - * Search view callbacks - */ - /** {@inheritDoc} */ - @Override - public boolean onQueryTextChange(String newText) { - searchFilter = newText; - getLoaderManager().restartLoader(LOADER, null, this); - return true; - } - - /** {@inheritDoc} */ - @Override - public boolean onQueryTextSubmit(String newText) { - // All is handled in onQueryTextChange - return true; - } - - /** - * Loader callbacks - */ - /** {@inheritDoc} */ - @Override - public Loader onCreateLoader(int i, Bundle bundle) { - return createCursorLoader(); - } - - /** {@inheritDoc} */ - @Override - public void onLoadFinished(Loader cursorLoader, Cursor cursor) { - adapter.swapCursor(cursor); - // To prevent the empty text from appearing on the first load, set it now - emptyView.setText(getString(R.string.swipe_down_to_refresh)); - } - - /** {@inheritDoc} */ - @Override - public void onLoaderReset(Loader cursorLoader) { - adapter.swapCursor(null); - } - - - /** - * @return text entered in searchview - */ - public String getSearchFilter() { - return searchFilter; - } - - /** - * Use this to reload the items in the list - */ - public void refreshList() { - getLoaderManager().restartLoader(LOADER, null, this); - } - public void showRefreshAnimation() { /** * Fixes issue with refresh animation not showing when using appcompat library (from version 20?) @@ -364,4 +164,8 @@ public abstract class AbstractListFragment extends Fragment } }); } + + public BaseAdapter getAdapter() { + return adapter; + } } diff --git a/app/src/main/java/org/xbmc/kore/ui/AlbumListFragment.java b/app/src/main/java/org/xbmc/kore/ui/AlbumListFragment.java index 0ef933e..6bf8d22 100644 --- a/app/src/main/java/org/xbmc/kore/ui/AlbumListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/AlbumListFragment.java @@ -54,7 +54,7 @@ import org.xbmc.kore.utils.Utils; /** * Fragment that presents the albums list */ -public class AlbumListFragment extends AbstractListFragment { +public class AlbumListFragment extends AbstractCursorListFragment { private static final String TAG = LogUtils.makeLogTag(AlbumListFragment.class); public interface OnAlbumSelectedListener { diff --git a/app/src/main/java/org/xbmc/kore/ui/ArtistListFragment.java b/app/src/main/java/org/xbmc/kore/ui/ArtistListFragment.java index e432034..dc9cec5 100644 --- a/app/src/main/java/org/xbmc/kore/ui/ArtistListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/ArtistListFragment.java @@ -41,7 +41,6 @@ import android.widget.TextView; import org.xbmc.kore.R; import org.xbmc.kore.host.HostInfo; import org.xbmc.kore.host.HostManager; -import org.xbmc.kore.jsonrpc.method.Playlist; import org.xbmc.kore.jsonrpc.type.PlaylistType; import org.xbmc.kore.provider.MediaContract; import org.xbmc.kore.provider.MediaDatabase; @@ -54,7 +53,7 @@ import org.xbmc.kore.utils.Utils; /** * Fragment that presents the artists list */ -public class ArtistListFragment extends AbstractListFragment { +public class ArtistListFragment extends AbstractCursorListFragment { private static final String TAG = LogUtils.makeLogTag(ArtistListFragment.class); public interface OnArtistSelectedListener { diff --git a/app/src/main/java/org/xbmc/kore/ui/AudioGenresListFragment.java b/app/src/main/java/org/xbmc/kore/ui/AudioGenresListFragment.java index 3605914..cd09315 100644 --- a/app/src/main/java/org/xbmc/kore/ui/AudioGenresListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/AudioGenresListFragment.java @@ -50,7 +50,7 @@ import org.xbmc.kore.utils.UIUtils; /** * Fragment that presents the album genres list */ -public class AudioGenresListFragment extends AbstractListFragment { +public class AudioGenresListFragment extends AbstractCursorListFragment { private static final String TAG = LogUtils.makeLogTag(AudioGenresListFragment.class); public interface OnAudioGenreSelectedListener { diff --git a/app/src/main/java/org/xbmc/kore/ui/MediaFileListFragment.java b/app/src/main/java/org/xbmc/kore/ui/MediaFileListFragment.java index 414a18f..36fdf07 100644 --- a/app/src/main/java/org/xbmc/kore/ui/MediaFileListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/MediaFileListFragment.java @@ -21,15 +21,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; -import android.support.v4.app.Fragment; -import android.support.v4.widget.SwipeRefreshLayout; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; -import android.widget.GridView; import android.widget.ImageView; import android.widget.ListAdapter; import android.widget.PopupMenu; @@ -56,13 +53,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Queue; -import butterknife.ButterKnife; -import butterknife.InjectView; - /** * Presents a list of files of different types (Video/Music) */ -public class MediaFileListFragment extends Fragment { +public class MediaFileListFragment extends AbstractListFragment { private static final String TAG = LogUtils.makeLogTag(MediaFileListFragment.class); public static final String MEDIA_TYPE = "mediaType"; @@ -80,15 +74,15 @@ public class MediaFileListFragment extends Fragment { String mediaType = Files.Media.MUSIC; String parentDirectory = null; int playlistId = PlaylistType.MUSIC_PLAYLISTID; // this is the ID of the music player - private MediaFileListAdapter adapter = null; +// private MediaFileListAdapter adapter = null; boolean browseRootAlready = false; ArrayList rootFileLocation = new ArrayList(); Queue mediaQueueFileLocation = new LinkedList<>(); - @InjectView(R.id.list) GridView folderGridView; - @InjectView(R.id.swipe_refresh_layout) SwipeRefreshLayout swipeRefreshLayout; - @InjectView(android.R.id.empty) TextView emptyView; +// @InjectView(R.id.list) GridView folderGridView; +// @InjectView(R.id.swipe_refresh_layout) SwipeRefreshLayout swipeRefreshLayout; +// @InjectView(android.R.id.empty) TextView emptyView; public static MediaFileListFragment newInstance(final String media) { MediaFileListFragment fragment = new MediaFileListFragment(); @@ -103,7 +97,7 @@ public class MediaFileListFragment extends Fragment { super.onSaveInstanceState(outState); outState.putString(MEDIA_TYPE, mediaType); try { - outState.putParcelableArrayList(PATH_CONTENTS, (ArrayList)adapter.getFileItemList()); + outState.putParcelableArrayList(PATH_CONTENTS, (ArrayList) ((MediaFileListAdapter) getAdapter()).getFileItemList()); } catch (NullPointerException npe) { // adapter is null probably nothing was save in bundle because the directory is empty // ignore this so that the empty message would display later on @@ -112,8 +106,24 @@ public class MediaFileListFragment extends Fragment { outState.putBoolean(ROOT_VISITED, browseRootAlready); } + @Override + protected AdapterView.OnItemClickListener createOnItemClickListener() { + return new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + handleFileSelect(((MediaFileListAdapter) getAdapter()).getItem(position)); + } + }; + } + + @Override + protected BaseAdapter createAdapter() { + return new MediaFileListAdapter(getActivity(), R.layout.grid_item_file); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View root = super.onCreateView(inflater, container, savedInstanceState); Bundle args = getArguments(); if (args != null) { mediaType = args.getString(MEDIA_TYPE, Files.Media.MUSIC); @@ -123,11 +133,8 @@ public class MediaFileListFragment extends Fragment { playlistId = PlaylistType.PICTURE_PLAYLISTID; } } - ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_generic_media_list, container, false); - ButterKnife.inject(this, root); hostManager = HostManager.getInstance(getActivity()); - swipeRefreshLayout.setEnabled(false); emptyView.setOnClickListener(new View.OnClickListener() { @Override @@ -135,18 +142,7 @@ public class MediaFileListFragment extends Fragment { browseSources(); } }); - folderGridView.setEmptyView(emptyView); - folderGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - handleFileSelect(adapter.getItem(position)); - } - }); - if (adapter == null) { - adapter = new MediaFileListAdapter(getActivity(), R.layout.grid_item_file); - } - folderGridView.setAdapter(adapter); if (savedInstanceState != null) { mediaType = savedInstanceState.getString(MEDIA_TYPE); //currentPath = savedInstanceState.getString(CURRENT_PATH); @@ -158,7 +154,7 @@ public class MediaFileListFragment extends Fragment { ArrayList list = savedInstanceState.getParcelableArrayList(PATH_CONTENTS); rootFileLocation = savedInstanceState.getParcelableArrayList(ROOT_PATH_CONTENTS); browseRootAlready = savedInstanceState.getBoolean(ROOT_VISITED); - adapter.setFilelistItems(list); + ((MediaFileListAdapter) getAdapter()).setFilelistItems(list); } else { browseSources(); @@ -187,13 +183,13 @@ public class MediaFileListFragment extends Fragment { public void onBackPressed() { // Emulate a click on .. - handleFileSelect(adapter.getItem(0)); + handleFileSelect(((MediaFileListAdapter) getAdapter()).getItem(0)); } public boolean atRootDirectory() { - if (adapter.getCount() == 0) + if (getAdapter().getCount() == 0) return true; - FileLocation fl = adapter.getItem(0); + FileLocation fl = ((MediaFileListAdapter) getAdapter()).getItem(0); if (fl == null) return true; else @@ -224,7 +220,7 @@ public class MediaFileListFragment extends Fragment { browseRootAlready = true; emptyView.setText(getString(R.string.source_empty)); - adapter.setFilelistItems(rootFileLocation); + ((MediaFileListAdapter) getAdapter()).setFilelistItems(rootFileLocation); } @Override @@ -320,7 +316,7 @@ public class MediaFileListFragment extends Fragment { for (ListType.ItemFile i : result) { flList.add(FileLocation.newInstanceFromItemFile(getActivity(), i)); } - adapter.setFilelistItems(flList); + ((MediaFileListAdapter) getAdapter()).setFilelistItems(flList); browseRootAlready = false; } diff --git a/app/src/main/java/org/xbmc/kore/ui/MovieListFragment.java b/app/src/main/java/org/xbmc/kore/ui/MovieListFragment.java index 0782412..ea6e24d 100644 --- a/app/src/main/java/org/xbmc/kore/ui/MovieListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/MovieListFragment.java @@ -53,7 +53,7 @@ import org.xbmc.kore.utils.Utils; /** * Fragment that presents the movie list */ -public class MovieListFragment extends AbstractListFragment { +public class MovieListFragment extends AbstractCursorListFragment { private static final String TAG = LogUtils.makeLogTag(MovieListFragment.class); public interface OnMovieSelectedListener { diff --git a/app/src/main/java/org/xbmc/kore/ui/MusicVideoListFragment.java b/app/src/main/java/org/xbmc/kore/ui/MusicVideoListFragment.java index 66efd11..5019ce9 100644 --- a/app/src/main/java/org/xbmc/kore/ui/MusicVideoListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/MusicVideoListFragment.java @@ -50,7 +50,7 @@ import org.xbmc.kore.utils.Utils; /** * Fragment that presents the artists list */ -public class MusicVideoListFragment extends AbstractListFragment { +public class MusicVideoListFragment extends AbstractCursorListFragment { private static final String TAG = LogUtils.makeLogTag(MusicVideoListFragment.class); public interface OnMusicVideoSelectedListener { diff --git a/app/src/main/java/org/xbmc/kore/ui/TVShowListFragment.java b/app/src/main/java/org/xbmc/kore/ui/TVShowListFragment.java index b18aecc..bb863a7 100644 --- a/app/src/main/java/org/xbmc/kore/ui/TVShowListFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/TVShowListFragment.java @@ -53,7 +53,7 @@ import org.xbmc.kore.utils.Utils; /** * Fragment that presents the tv show list */ -public class TVShowListFragment extends AbstractListFragment { +public class TVShowListFragment extends AbstractCursorListFragment { private static final String TAG = LogUtils.makeLogTag(TVShowListFragment.class); public interface OnTVShowSelectedListener { diff --git a/app/src/main/res/menu/abstractcursorlistfragment.xml b/app/src/main/res/menu/abstractcursorlistfragment.xml new file mode 100644 index 0000000..e917ba0 --- /dev/null +++ b/app/src/main/res/menu/abstractcursorlistfragment.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/app/src/main/res/menu/abstractlistfragment.xml b/app/src/main/res/menu/abstractlistfragment.xml index 7c7a3cf..a87c076 100644 --- a/app/src/main/res/menu/abstractlistfragment.xml +++ b/app/src/main/res/menu/abstractlistfragment.xml @@ -20,7 +20,4 @@ -