Refactored ListView into RecycleView
Implemented custom RecyclerView to support using an empty view and a auto fitted grid layout. Reenabled shared element transitions for Oreo
This commit is contained in:
parent
f985f4132d
commit
3f5ccefe2e
|
@ -102,6 +102,7 @@ dependencies {
|
|||
implementation "com.android.support:preference-v14:${supportLibVersion}"
|
||||
implementation "com.android.support:support-v13:${supportLibVersion}"
|
||||
implementation "com.android.support:design:${supportLibVersion}"
|
||||
implementation "com.android.support:recyclerview-v7:${supportLibVersion}"
|
||||
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.5.2'
|
||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.support.v4.app.LoaderManager;
|
|||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -35,8 +36,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -48,6 +47,7 @@ import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
|||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.service.library.SyncItem;
|
||||
import org.xbmc.kore.service.library.SyncUtils;
|
||||
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
|
@ -78,6 +78,7 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
|||
|
||||
abstract protected void onListItemClicked(View view);
|
||||
abstract protected CursorLoader createCursorLoader();
|
||||
abstract protected RecyclerViewCursorAdapter createCursorAdapter();
|
||||
|
||||
@TargetApi(16)
|
||||
@Nullable
|
||||
|
@ -136,16 +137,21 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
|||
}
|
||||
|
||||
@Override
|
||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
||||
return new AdapterView.OnItemClickListener() {
|
||||
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
public void onItemClick(View view, int position) {
|
||||
saveSearchState();
|
||||
onListItemClicked(view);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected RecyclerView.Adapter createAdapter() {
|
||||
return createCursorAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.abstractcursorlistfragment, menu);
|
||||
|
@ -305,7 +311,7 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
|||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
|
||||
loaderLoading = false;
|
||||
((CursorAdapter) getAdapter()).swapCursor(cursor);
|
||||
((RecyclerViewCursorAdapter) getAdapter()).swapCursor(cursor);
|
||||
if (TextUtils.isEmpty(searchFilter)) {
|
||||
// To prevent the empty text from appearing on the first load, set it now
|
||||
emptyView.setText(getString(R.string.swipe_down_to_refresh));
|
||||
|
@ -316,7 +322,7 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> cursorLoader) {
|
||||
((CursorAdapter) getAdapter()).swapCursor(null);
|
||||
((RecyclerViewCursorAdapter) getAdapter()).swapCursor(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,43 +23,37 @@ import android.preference.PreferenceManager;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
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.view.ViewTreeObserver;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.xbmc.kore.R;
|
||||
import org.xbmc.kore.Settings;
|
||||
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public abstract class AbstractListFragment extends Fragment implements
|
||||
SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = LogUtils.makeLogTag(AbstractListFragment.class);
|
||||
private BaseAdapter adapter;
|
||||
private RecyclerView.Adapter adapter;
|
||||
|
||||
private final String BUNDLE_SAVEDINSTANCE_LISTPOSITION = "lposition";
|
||||
|
||||
private boolean gridViewUsesMultipleColumns;
|
||||
private Unbinder unbinder;
|
||||
|
||||
protected @BindView(R.id.swipe_refresh_layout) SwipeRefreshLayout swipeRefreshLayout;
|
||||
@BindView(R.id.list) GridView gridView;
|
||||
@BindView(R.id.list) RecyclerViewEmptyViewSupport recyclerView;
|
||||
@BindView(android.R.id.empty) TextView emptyView;
|
||||
|
||||
abstract protected AdapterView.OnItemClickListener createOnItemClickListener();
|
||||
abstract protected BaseAdapter createAdapter();
|
||||
abstract protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener();
|
||||
abstract protected RecyclerViewEmptyViewSupport.Adapter createAdapter();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
@ -76,40 +70,18 @@ public abstract class AbstractListFragment extends Fragment implements
|
|||
|
||||
swipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
||||
gridView.setEmptyView(emptyView);
|
||||
gridView.setOnItemClickListener(createOnItemClickListener());
|
||||
gridView.setAdapter(adapter);
|
||||
recyclerView.setEmptyView(emptyView);
|
||||
recyclerView.setOnItemClickListener(createOnItemClickListener());
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
final int listPosition = savedInstanceState.getInt(BUNDLE_SAVEDINSTANCE_LISTPOSITION);
|
||||
gridView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
gridView.setSelection(listPosition);
|
||||
}
|
||||
});
|
||||
if (PreferenceManager
|
||||
.getDefaultSharedPreferences(getActivity())
|
||||
.getBoolean(Settings.KEY_PREF_SINGLE_COLUMN,
|
||||
Settings.DEFAULT_PREF_SINGLE_COLUMN)) {
|
||||
recyclerView.setColumnCount(1);
|
||||
}
|
||||
|
||||
//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) {
|
||||
gridViewUsesMultipleColumns = true;
|
||||
}
|
||||
|
||||
if (Utils.isJellybeanOrLater()) {
|
||||
gridView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
} else {
|
||||
gridView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
}
|
||||
|
||||
//Make sure menu is update d if it was already created
|
||||
getActivity().invalidateOptionsMenu();
|
||||
}
|
||||
});
|
||||
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
return root;
|
||||
|
@ -121,34 +93,23 @@ public abstract class AbstractListFragment extends Fragment implements
|
|||
unbinder.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (gridView != null) {
|
||||
outState.putInt(BUNDLE_SAVEDINSTANCE_LISTPOSITION, gridView.getFirstVisiblePosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.abstractlistfragment, menu);
|
||||
|
||||
if(gridViewUsesMultipleColumns) {
|
||||
if(recyclerView.isMultiColumnSupported()) {
|
||||
if (PreferenceManager
|
||||
.getDefaultSharedPreferences(getActivity())
|
||||
.getBoolean(Settings.KEY_PREF_SINGLE_COLUMN,
|
||||
Settings.DEFAULT_PREF_SINGLE_COLUMN)) {
|
||||
gridView.setNumColumns(1);
|
||||
recyclerView.setColumnCount(1);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
MenuItem item = menu.findItem(R.id.action_multi_single_columns);
|
||||
item.setTitle(R.string.multi_column);
|
||||
}
|
||||
} else {
|
||||
//Default number of columns for GridView is set to AUTO_FIT.
|
||||
//When this leads to a single column it is not possible
|
||||
//to switch to multiple columns. We therefore disable
|
||||
//the menu item.
|
||||
//Disable menu item when mult-column is not supported
|
||||
MenuItem item = menu.findItem(R.id.action_multi_single_columns);
|
||||
item.setTitle(R.string.multi_column);
|
||||
item.setEnabled(false);
|
||||
|
@ -170,14 +131,14 @@ public abstract class AbstractListFragment extends Fragment implements
|
|||
private void toggleAmountOfColumns(MenuItem item) {
|
||||
SharedPreferences.Editor editor = PreferenceManager
|
||||
.getDefaultSharedPreferences(getActivity()).edit();
|
||||
if (gridView.getNumColumns() == 1) {
|
||||
if (recyclerView.getColumnCount() == 1) {
|
||||
editor.putBoolean(Settings.KEY_PREF_SINGLE_COLUMN, false);
|
||||
item.setTitle(R.string.single_column);
|
||||
gridView.setNumColumns(GridView.AUTO_FIT);
|
||||
recyclerView.setColumnCount(RecyclerViewEmptyViewSupport.AUTO_FIT);
|
||||
} else {
|
||||
editor.putBoolean(Settings.KEY_PREF_SINGLE_COLUMN, true);
|
||||
item.setTitle(R.string.multi_column);
|
||||
gridView.setNumColumns(1);
|
||||
recyclerView.setColumnCount(1);
|
||||
}
|
||||
editor.apply();
|
||||
adapter.notifyDataSetChanged(); //force gridView to redraw
|
||||
|
@ -187,7 +148,7 @@ public abstract class AbstractListFragment extends Fragment implements
|
|||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
public BaseAdapter getAdapter() {
|
||||
public RecyclerView.Adapter getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ import org.xbmc.kore.jsonrpc.method.Player;
|
|||
import org.xbmc.kore.jsonrpc.type.ListType;
|
||||
import org.xbmc.kore.jsonrpc.type.PlayerType;
|
||||
import org.xbmc.kore.ui.generic.NavigationDrawerFragment;
|
||||
import org.xbmc.kore.ui.sections.remote.RemoteActivity;
|
||||
import org.xbmc.kore.ui.generic.VolumeControllerDialogFragmentListener;
|
||||
import org.xbmc.kore.ui.sections.remote.RemoteActivity;
|
||||
import org.xbmc.kore.ui.widgets.MediaProgressIndicator;
|
||||
import org.xbmc.kore.ui.widgets.NowPlayingPanel;
|
||||
import org.xbmc.kore.ui.widgets.VolumeLevelIndicator;
|
||||
|
@ -58,8 +58,8 @@ import org.xbmc.kore.utils.SharedElementTransition;
|
|||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public abstract class BaseMediaActivity extends BaseActivity
|
||||
implements HostConnectionObserver.ApplicationEventsObserver,
|
||||
|
@ -141,7 +141,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
|||
if (fragment == null) {
|
||||
fragment = createFragment();
|
||||
|
||||
if (Utils.isLollipopAndPreOreo()) {
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
fragment.setExitTransition(null);
|
||||
fragment.setReenterTransition(TransitionInflater
|
||||
.from(this)
|
||||
|
@ -154,7 +154,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
|||
.commit();
|
||||
}
|
||||
|
||||
if (Utils.isLollipopAndPreOreo()) {
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
sharedElementTransition.setupExitTransition(this, fragment);
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
|||
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
|
||||
|
||||
// Set up transitions
|
||||
if (Utils.isLollipopAndPreOreo()) {
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
dataHolder.setPosterTransitionName(sharedImageView.getTransitionName());
|
||||
sharedElementTransition.setupEnterTransition(this, fragTrans, fragment, sharedImageView);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2018 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.database.Cursor;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
abstract public class RecyclerViewCursorAdapter extends RecyclerView.Adapter<RecyclerViewCursorAdapter.CursorViewHolder> {
|
||||
|
||||
private boolean dataValid;
|
||||
private int rowIDColumn;
|
||||
private Cursor cursor;
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(CursorViewHolder holder, int position) {
|
||||
if (!dataValid) {
|
||||
throw new IllegalStateException("Cannot bind viewholder when cursor is in invalid state.");
|
||||
}
|
||||
if (!cursor.moveToPosition(position)) {
|
||||
throw new IllegalStateException("Could not move cursor to position " + position + " when trying to bind viewholder");
|
||||
}
|
||||
|
||||
holder.bindView(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
if (dataValid) {
|
||||
return cursor.getCount();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
if (!dataValid) {
|
||||
throw new IllegalStateException("Cursor is in an invalid state.");
|
||||
}
|
||||
if (!cursor.moveToPosition(position)) {
|
||||
throw new IllegalStateException("Could not move cursor to position " + position);
|
||||
}
|
||||
|
||||
return cursor.getLong(rowIDColumn);
|
||||
}
|
||||
|
||||
public void swapCursor(Cursor newCursor) {
|
||||
if (newCursor == cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newCursor != null) {
|
||||
cursor = newCursor;
|
||||
rowIDColumn = cursor.getColumnIndexOrThrow("_id");
|
||||
dataValid = true;
|
||||
notifyDataSetChanged();
|
||||
} else {
|
||||
notifyItemRangeRemoved(0, getItemCount());
|
||||
cursor = null;
|
||||
rowIDColumn = -1;
|
||||
dataValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
abstract public static class CursorViewHolder extends RecyclerView.ViewHolder {
|
||||
public CursorViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
itemView.setTag(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the content of {@link RecyclerView.ViewHolder#itemView} this holder holds.
|
||||
*/
|
||||
abstract public void bindView(Cursor cursor);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,18 +15,15 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui.sections.addon;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -38,10 +35,12 @@ import org.xbmc.kore.jsonrpc.method.Addons;
|
|||
import org.xbmc.kore.jsonrpc.type.AddonType;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.AbstractListFragment;
|
||||
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
@ -65,10 +64,10 @@ public class AddonListFragment extends AbstractListFragment {
|
|||
private Handler callbackHandler = new Handler();
|
||||
|
||||
@Override
|
||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
||||
return new AdapterView.OnItemClickListener() {
|
||||
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
public void onItemClick(View view, int position) {
|
||||
// Get the movie id from the tag
|
||||
ViewHolder tag = (ViewHolder) view.getTag();
|
||||
// Notify the activity
|
||||
|
@ -77,10 +76,9 @@ public class AddonListFragment extends AbstractListFragment {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected BaseAdapter createAdapter() {
|
||||
return new AddonsAdapter(getActivity(), R.layout.grid_item_addon);
|
||||
protected RecyclerView.Adapter createAdapter() {
|
||||
return new AddonsAdapter(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,7 +86,7 @@ public class AddonListFragment extends AbstractListFragment {
|
|||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(false);
|
||||
|
||||
if (getAdapter().getCount() == 0)
|
||||
if (getAdapter().getItemCount() == 0)
|
||||
callGetAddonsAndSetup();
|
||||
}
|
||||
|
||||
|
@ -172,7 +170,7 @@ public class AddonListFragment extends AbstractListFragment {
|
|||
adapter.notifyDataSetChanged();
|
||||
hideRefreshAnimation();
|
||||
|
||||
if (adapter.getCount() == 0) {
|
||||
if (adapter.getItemCount() == 0) {
|
||||
getEmptyView().setText(R.string.no_addons_found_refresh);
|
||||
}
|
||||
}
|
||||
|
@ -190,15 +188,16 @@ public class AddonListFragment extends AbstractListFragment {
|
|||
callbackHandler);
|
||||
}
|
||||
|
||||
private class AddonsAdapter extends ArrayAdapter<AddonType.Details> {
|
||||
private static class AddonsAdapter extends RecyclerView.Adapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
private String author;
|
||||
private String version;
|
||||
private Context context;
|
||||
|
||||
public AddonsAdapter(Context context, int resource) {
|
||||
super(context, resource);
|
||||
private ArrayList<AddonType.Details> items = new ArrayList<>();
|
||||
|
||||
public AddonsAdapter(Context context) {
|
||||
this.context = context;
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
|
||||
// Get the art dimensions
|
||||
|
@ -207,63 +206,96 @@ public class AddonListFragment extends AbstractListFragment {
|
|||
Resources resources = context.getResources();
|
||||
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_width_square);
|
||||
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||
|
||||
author = context.getString(R.string.author);
|
||||
version = context.getString(R.string.version);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getActivity())
|
||||
.inflate(R.layout.grid_item_addon, parent, false);
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_addon, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)convertView.findViewById(R.id.title);
|
||||
viewHolder.detailsView = (TextView)convertView.findViewById(R.id.details);
|
||||
viewHolder.artView = (ImageView)convertView.findViewById(R.id.art);
|
||||
convertView.setTag(viewHolder);
|
||||
}
|
||||
return new ViewHolder(view, context, hostManager, artWidth, artHeight);
|
||||
}
|
||||
|
||||
final ViewHolder viewHolder = (ViewHolder)convertView.getTag();
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
AddonType.Details addonDetails = this.getItem(position);
|
||||
((ViewHolder) holder).onBind(addonDetails);
|
||||
}
|
||||
|
||||
viewHolder.dataHolder.setTitle(addonDetails.name);
|
||||
viewHolder.dataHolder.setDescription(addonDetails.description);
|
||||
viewHolder.dataHolder.setUndertitle(addonDetails.summary);
|
||||
viewHolder.dataHolder.setFanArtUrl(addonDetails.fanart);
|
||||
viewHolder.dataHolder.setPosterUrl(addonDetails.thumbnail);
|
||||
viewHolder.dataHolder.setDetails(author + " " + addonDetails.author + "\n" +
|
||||
version + " " +addonDetails.version);
|
||||
viewHolder.dataHolder.getBundle().putString(AddonInfoFragment.BUNDLE_KEY_ADDONID, addonDetails.addonid);
|
||||
viewHolder.dataHolder.getBundle().putBoolean(AddonInfoFragment.BUNDLE_KEY_BROWSABLE,
|
||||
AddonType.Types.XBMC_PYTHON_PLUGINSOURCE.equals(addonDetails.type));
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
||||
viewHolder.detailsView.setText(addonDetails.summary);
|
||||
public void clear() {
|
||||
items.clear();
|
||||
}
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager,
|
||||
addonDetails.thumbnail, viewHolder.dataHolder.getTitle(),
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
public void add(AddonType.Details item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
if(Utils.isLollipopOrLater()) {
|
||||
viewHolder.artView.setTransitionName("a"+addonDetails.addonid);
|
||||
}
|
||||
return convertView;
|
||||
public AddonType.Details getItem(int position) {
|
||||
return items.get(position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView titleView;
|
||||
TextView detailsView;
|
||||
ImageView artView;
|
||||
private static String author;
|
||||
private static String version;
|
||||
private HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
if( author == null ) {
|
||||
author = context.getString(R.string.author);
|
||||
version = context.getString(R.string.version);
|
||||
}
|
||||
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
detailsView = itemView.findViewById(R.id.details);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
|
||||
itemView.setTag(this);
|
||||
}
|
||||
|
||||
public void onBind(AddonType.Details addonDetails) {
|
||||
dataHolder.setTitle(addonDetails.name);
|
||||
dataHolder.setDescription(addonDetails.description);
|
||||
dataHolder.setUndertitle(addonDetails.summary);
|
||||
dataHolder.setFanArtUrl(addonDetails.fanart);
|
||||
dataHolder.setPosterUrl(addonDetails.thumbnail);
|
||||
dataHolder.setDetails(author + " " + addonDetails.author + "\n" +
|
||||
version + " " +addonDetails.version);
|
||||
dataHolder.getBundle().putString(AddonInfoFragment.BUNDLE_KEY_ADDONID, addonDetails.addonid);
|
||||
dataHolder.getBundle().putBoolean(AddonInfoFragment.BUNDLE_KEY_BROWSABLE,
|
||||
AddonType.Types.XBMC_PYTHON_PLUGINSOURCE.equals(addonDetails.type));
|
||||
|
||||
titleView.setText(dataHolder.getTitle());
|
||||
detailsView.setText(addonDetails.summary);
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
addonDetails.thumbnail, dataHolder.getTitle(),
|
||||
artView, artWidth, artHeight);
|
||||
|
||||
if(Utils.isLollipopOrLater()) {
|
||||
artView.setTransitionName("a"+addonDetails.addonid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui.sections.audio;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -25,6 +24,7 @@ import android.net.Uri;
|
|||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.BaseColumns;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -33,7 +33,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
@ -48,6 +47,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
|||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
@ -162,8 +162,8 @@ public class AlbumListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
return new AlbumsAdapter(getActivity());
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new AlbumsAdapter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -263,113 +263,119 @@ public class AlbumListFragment extends AbstractCursorListFragment {
|
|||
int RATING = 7;
|
||||
}
|
||||
|
||||
private class AlbumsAdapter extends CursorAdapter {
|
||||
private static class AlbumsAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
private Fragment fragment;
|
||||
|
||||
public AlbumsAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
public AlbumsAdapter(Fragment fragment) {
|
||||
this.hostManager = HostManager.getInstance(fragment.getContext());
|
||||
this.fragment = fragment;
|
||||
|
||||
// Get the art dimensions
|
||||
// Use the same dimensions as in the details fragment, so that it hits Picasso's cache when
|
||||
// the user transitions to that fragment, avoiding another call and imediatelly showing the image
|
||||
Resources resources = context.getResources();
|
||||
Resources resources = fragment.getContext().getResources();
|
||||
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_width_square);
|
||||
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_album, parent, false);
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(fragment.getContext())
|
||||
.inflate(R.layout.grid_item_album, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.artistView = (TextView)view.findViewById(R.id.name);
|
||||
viewHolder.genresView = (TextView)view.findViewById(R.id.genres);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
return new ViewHolder(view, fragment.getContext(), hostManager, artWidth, artHeight,
|
||||
albumlistItemMenuClickListener);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
private View.OnClickListener albumlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
viewHolder.dataHolder.setId(cursor.getInt(AlbumListQuery.ALBUMID));
|
||||
viewHolder.dataHolder.setTitle(cursor.getString(AlbumListQuery.TITLE));
|
||||
viewHolder.dataHolder.setUndertitle(cursor.getString(AlbumListQuery.DISPLAYARTIST));
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.albumid = viewHolder.dataHolder.getId();
|
||||
|
||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
||||
viewHolder.artistView.setText(viewHolder.dataHolder.getUnderTitle());
|
||||
int year = cursor.getInt(AlbumListQuery.YEAR);
|
||||
String genres = cursor.getString(AlbumListQuery.GENRE);
|
||||
String desc = (genres != null) ?
|
||||
((year > 0) ? genres + " | " + year : genres) :
|
||||
String.valueOf(year);
|
||||
viewHolder.dataHolder.setDescription(desc);
|
||||
viewHolder.genresView.setText(desc);
|
||||
|
||||
viewHolder.dataHolder.setPosterUrl(cursor.getString(AlbumListQuery.THUMBNAIL));
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
viewHolder.dataHolder.getPosterUrl(),
|
||||
viewHolder.dataHolder.getTitle(),
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(albumlistItemMenuClickListener);
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
viewHolder.artView.setTransitionName("al"+viewHolder.dataHolder.getId());
|
||||
final PopupMenu popupMenu = new PopupMenu(fragment.getContext(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaPlayerUtils.play(fragment, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaPlayerUtils.queue(fragment, playListItem, PlaylistType.GetPlaylistsReturnType.AUDIO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView titleView;
|
||||
TextView artistView;
|
||||
TextView genresView;
|
||||
ImageView artView;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
}
|
||||
|
||||
private View.OnClickListener albumlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight,
|
||||
View.OnClickListener contextMenuClickListener) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
artistView = itemView.findViewById(R.id.name);
|
||||
genresView = itemView.findViewById(R.id.genres);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.albumid = viewHolder.dataHolder.getId();
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaPlayerUtils.play(AlbumListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaPlayerUtils.queue(AlbumListFragment.this, playListItem, PlaylistType.GetPlaylistsReturnType.AUDIO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(this);
|
||||
contextMenu.setOnClickListener(contextMenuClickListener);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
dataHolder.setId(cursor.getInt(AlbumListQuery.ALBUMID));
|
||||
dataHolder.setTitle(cursor.getString(AlbumListQuery.TITLE));
|
||||
dataHolder.setUndertitle(cursor.getString(AlbumListQuery.DISPLAYARTIST));
|
||||
|
||||
titleView.setText(dataHolder.getTitle());
|
||||
artistView.setText(dataHolder.getUnderTitle());
|
||||
int year = cursor.getInt(AlbumListQuery.YEAR);
|
||||
String genres = cursor.getString(AlbumListQuery.GENRE);
|
||||
String desc = (genres != null) ?
|
||||
((year > 0) ? genres + " | " + year : genres) :
|
||||
String.valueOf(year);
|
||||
dataHolder.setDescription(desc);
|
||||
genresView.setText(desc);
|
||||
|
||||
dataHolder.setPosterUrl(cursor.getString(AlbumListQuery.THUMBNAIL));
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
dataHolder.getPosterUrl(),
|
||||
dataHolder.getTitle(),
|
||||
artView, artWidth, artHeight);
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
artView.setTransitionName("al"+dataHolder.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,20 +15,19 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui.sections.audio;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
@ -42,6 +41,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
|||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
@ -72,8 +72,8 @@ public class ArtistListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
return new ArtistsAdapter(getActivity());
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new ArtistsAdapter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -135,105 +135,108 @@ public class ArtistListFragment extends AbstractCursorListFragment {
|
|||
int FANART = 6;
|
||||
}
|
||||
|
||||
private class ArtistsAdapter extends CursorAdapter {
|
||||
private static class ArtistsAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
Fragment fragment;
|
||||
|
||||
public ArtistsAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
public ArtistsAdapter(Fragment fragment) {
|
||||
this.fragment = fragment;
|
||||
this.hostManager = HostManager.getInstance(fragment.getContext());
|
||||
|
||||
// Get the art dimensions
|
||||
Resources resources = context.getResources();
|
||||
Resources resources = fragment.getContext().getResources();
|
||||
artWidth = (int)(resources.getDimension(R.dimen.detail_poster_width_square));
|
||||
artHeight = (int)(resources.getDimension(R.dimen.detail_poster_height_square));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_artist, parent, false);
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(fragment.getContext())
|
||||
.inflate(R.layout.grid_item_artist, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.nameView = (TextView)view.findViewById(R.id.name);
|
||||
viewHolder.genresView = (TextView)view.findViewById(R.id.genres);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
viewHolder.contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
view.setTag(viewHolder);
|
||||
|
||||
return view;
|
||||
return new ViewHolder(view, fragment.getContext(), hostManager, artWidth, artHeight, artistlistItemMenuClickListener);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
private View.OnClickListener artistlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
|
||||
// Save the movie id
|
||||
viewHolder.dataHolder.setId(cursor.getInt(ArtistListQuery.ARTISTID));
|
||||
viewHolder.dataHolder.setTitle(cursor.getString(ArtistListQuery.ARTIST));
|
||||
viewHolder.dataHolder.setUndertitle(cursor.getString(ArtistListQuery.GENRE));
|
||||
viewHolder.dataHolder.setDescription(cursor.getString(ArtistListQuery.DESCRIPTION));
|
||||
viewHolder.dataHolder.setFanArtUrl(cursor.getString(ArtistListQuery.FANART));
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.artistid = viewHolder.dataHolder.getId();
|
||||
|
||||
viewHolder.nameView.setText(cursor.getString(ArtistListQuery.ARTIST));
|
||||
viewHolder.genresView.setText(cursor.getString(ArtistListQuery.GENRE));
|
||||
viewHolder.dataHolder.setPosterUrl(cursor.getString(ArtistListQuery.THUMBNAIL));
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
viewHolder.dataHolder.getPosterUrl(), viewHolder.dataHolder.getTitle(),
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
viewHolder.contextMenu.setTag(viewHolder);
|
||||
viewHolder.contextMenu.setOnClickListener(artistlistItemMenuClickListener);
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
viewHolder.artView.setTransitionName("ar"+viewHolder.dataHolder.getId());
|
||||
final PopupMenu popupMenu = new PopupMenu(fragment.getContext(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaPlayerUtils.play(fragment, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaPlayerUtils.queue(fragment, playListItem, PlaylistType.GetPlaylistsReturnType.AUDIO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView nameView;
|
||||
TextView genresView;
|
||||
ImageView artView;
|
||||
ImageView contextMenu;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
}
|
||||
|
||||
private View.OnClickListener artistlistItemMenuClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight,
|
||||
View.OnClickListener contextMenuClickListener) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
nameView = itemView.findViewById(R.id.name);
|
||||
genresView = itemView.findViewById(R.id.genres);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.artistid = viewHolder.dataHolder.getId();
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_play:
|
||||
MediaPlayerUtils.play(ArtistListFragment.this, playListItem);
|
||||
return true;
|
||||
case R.id.action_queue:
|
||||
MediaPlayerUtils.queue(ArtistListFragment.this, playListItem, PlaylistType.GetPlaylistsReturnType.AUDIO);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
ImageView contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(this);
|
||||
contextMenu.setOnClickListener(contextMenuClickListener);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
dataHolder.setId(cursor.getInt(ArtistListQuery.ARTISTID));
|
||||
dataHolder.setTitle(cursor.getString(ArtistListQuery.ARTIST));
|
||||
dataHolder.setUndertitle(cursor.getString(ArtistListQuery.GENRE));
|
||||
dataHolder.setDescription(cursor.getString(ArtistListQuery.DESCRIPTION));
|
||||
dataHolder.setFanArtUrl(cursor.getString(ArtistListQuery.FANART));
|
||||
|
||||
nameView.setText(cursor.getString(ArtistListQuery.ARTIST));
|
||||
genresView.setText(cursor.getString(ArtistListQuery.GENRE));
|
||||
dataHolder.setPosterUrl(cursor.getString(ArtistListQuery.THUMBNAIL));
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
dataHolder.getPosterUrl(), dataHolder.getTitle(),
|
||||
artView, artWidth, artHeight);
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
artView.setTransitionName("ar"+dataHolder.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import android.view.LayoutInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
@ -39,6 +38,7 @@ import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
|||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
@ -68,7 +68,7 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new AudioGenresAdapter(getActivity());
|
||||
}
|
||||
|
||||
|
@ -125,13 +125,12 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
|||
final int THUMBNAIL = 3;
|
||||
}
|
||||
|
||||
private class AudioGenresAdapter extends CursorAdapter {
|
||||
private class AudioGenresAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
||||
public AudioGenresAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
|
||||
// Get the art dimensions
|
||||
|
@ -142,52 +141,56 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
|||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_audio_genre, parent, false);
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(getContext())
|
||||
.inflate(R.layout.grid_item_audio_genre, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
|
||||
viewHolder.genreId = cursor.getInt(AudioGenreListQuery.GENREID);
|
||||
viewHolder.genreTitle = cursor.getString(AudioGenreListQuery.TITLE);
|
||||
|
||||
viewHolder.titleView.setText(viewHolder.genreTitle);
|
||||
|
||||
String thumbnail = cursor.getString(AudioGenreListQuery.THUMBNAIL);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, viewHolder.genreTitle,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(genrelistItemMenuClickListener);
|
||||
return new ViewHolder(view, getContext(), hostManager, artWidth, artHeight, genrelistItemMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
private static class ViewHolder {
|
||||
private static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView titleView;
|
||||
ImageView artView;
|
||||
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
int genreId;
|
||||
String genreTitle;
|
||||
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight,
|
||||
View.OnClickListener contextMenuClickListener) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
|
||||
ImageView contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(this);
|
||||
contextMenu.setOnClickListener(contextMenuClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
genreId = cursor.getInt(AudioGenreListQuery.GENREID);
|
||||
genreTitle = cursor.getString(AudioGenreListQuery.TITLE);
|
||||
|
||||
titleView.setText(genreTitle);
|
||||
|
||||
String thumbnail = cursor.getString(AudioGenreListQuery.THUMBNAIL);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, genreTitle, artView, artWidth, artHeight);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener genrelistItemMenuClickListener = new View.OnClickListener() {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui.sections.audio;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
@ -27,7 +26,6 @@ import android.text.TextUtils;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -39,6 +37,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
|||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
@ -68,7 +67,7 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new MusicVideosAdapter(getActivity());
|
||||
}
|
||||
|
||||
|
@ -137,13 +136,15 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
|||
int PLOT = 9;
|
||||
}
|
||||
|
||||
private static class MusicVideosAdapter extends CursorAdapter {
|
||||
private static class MusicVideosAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
private Context context;
|
||||
|
||||
public MusicVideosAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
this.context = context;
|
||||
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
|
||||
// Get the art dimensions
|
||||
|
@ -152,38 +153,50 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
|||
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_music_video, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.artistAlbumView = (TextView)view.findViewById(R.id.details);
|
||||
viewHolder.durationGenresView = (TextView)view.findViewById(R.id.duration);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_music_video, parent, false);
|
||||
return new ViewHolder(view, context, hostManager, artWidth, artHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView titleView;
|
||||
TextView artistAlbumView;
|
||||
TextView durationGenresView;
|
||||
ImageView artView;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
artistAlbumView = itemView.findViewById(R.id.details);
|
||||
durationGenresView = itemView.findViewById(R.id.duration);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
}
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
public void bindView(Cursor cursor) {
|
||||
dataHolder.setId(cursor.getInt(MusicVideosListQuery.MUSICVIDEOID));
|
||||
dataHolder.setTitle(cursor.getString(MusicVideosListQuery.TITLE));
|
||||
|
||||
// Save the movie id
|
||||
viewHolder.dataHolder.setId(cursor.getInt(MusicVideosListQuery.MUSICVIDEOID));
|
||||
viewHolder.dataHolder.setTitle(cursor.getString(MusicVideosListQuery.TITLE));
|
||||
|
||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
||||
titleView.setText(dataHolder.getTitle());
|
||||
String artistAlbum = cursor.getString(MusicVideosListQuery.ARTIST) + " | " +
|
||||
cursor.getString(MusicVideosListQuery.ALBUM);
|
||||
viewHolder.artistAlbumView.setText(artistAlbum);
|
||||
viewHolder.dataHolder.setUndertitle(artistAlbum);
|
||||
artistAlbumView.setText(artistAlbum);
|
||||
dataHolder.setUndertitle(artistAlbum);
|
||||
|
||||
int runtime = cursor.getInt(MusicVideosListQuery.RUNTIME);
|
||||
String genres = cursor.getString(MusicVideosListQuery.GENRES);
|
||||
|
@ -191,30 +204,17 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
|||
runtime > 0 ?
|
||||
UIUtils.formatTime(runtime) + " | " + genres :
|
||||
genres;
|
||||
viewHolder.durationGenresView.setText(durationGenres);
|
||||
viewHolder.dataHolder.setDetails(durationGenres);
|
||||
durationGenresView.setText(durationGenres);
|
||||
dataHolder.setDetails(durationGenres);
|
||||
|
||||
String posterUrl = cursor.getString(MusicVideosListQuery.THUMBNAIL);
|
||||
viewHolder.dataHolder.setPosterUrl(posterUrl);
|
||||
dataHolder.setPosterUrl(posterUrl);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager, posterUrl
|
||||
, viewHolder.dataHolder.getTitle(),
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
, dataHolder.getTitle(), artView, artWidth, artHeight);
|
||||
|
||||
if(Utils.isLollipopOrLater()) {
|
||||
viewHolder.artView.setTransitionName("a"+viewHolder.dataHolder.getId());
|
||||
artView.setTransitionName("a"+dataHolder.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
TextView titleView;
|
||||
TextView artistAlbumView;
|
||||
TextView durationGenresView;
|
||||
ImageView artView;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
@ -48,6 +47,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
|||
import org.xbmc.kore.provider.MediaProvider;
|
||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.FileDownloadHelper;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
|
@ -67,7 +67,8 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
|
||||
private int artistId = -1;
|
||||
private int albumId = -1;
|
||||
private String albumTitle = "";
|
||||
private static String albumTitle = "";
|
||||
|
||||
|
||||
private Handler callbackHandler = new Handler();
|
||||
|
||||
|
@ -96,11 +97,21 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_MUSIC; }
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
if (albumId != -1 ) {
|
||||
return new AlbumSongsAdapter(getActivity());
|
||||
return new AlbumSongsAdapter(getContext(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showPopupMenu(v);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return new SongsAdapter(getActivity());
|
||||
return new SongsAdapter(getContext(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showPopupMenu(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,15 +245,17 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
int DISC = 7;
|
||||
}
|
||||
|
||||
private class SongsAdapter extends CursorAdapter {
|
||||
private static class SongsAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
private Context context;
|
||||
private View.OnClickListener contextMenuClickListener;
|
||||
|
||||
public SongsAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
public SongsAdapter(Context context, View.OnClickListener contextMenuClickListener) {
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
|
||||
this.context = context;
|
||||
this.contextMenuClickListener = contextMenuClickListener;
|
||||
// Get the art dimensions
|
||||
// Use the same dimensions as in the details fragment, so that it hits Picasso's cache when
|
||||
// the user transitions to that fragment, avoiding another call and imediatelly showing the image
|
||||
|
@ -251,46 +264,103 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.grid_item_song, parent, false);
|
||||
.inflate(R.layout.grid_item_song, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.title = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.details = (TextView)view.findViewById(R.id.details);
|
||||
viewHolder.art = (ImageView)view.findViewById(R.id.art);
|
||||
viewHolder.artist = (TextView)view.findViewById(R.id.artist);
|
||||
viewHolder.songInfo = new FileDownloadHelper.SongInfo();
|
||||
viewHolder.contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
return new SongViewHolder(view, context, hostManager, artWidth, artHeight,
|
||||
contextMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
private static class AlbumSongsAdapter extends RecyclerViewCursorAdapter {
|
||||
private Context context;
|
||||
private View.OnClickListener contextMenuClickListener;
|
||||
|
||||
public AlbumSongsAdapter(Context context, View.OnClickListener contextMenuClickListener) {
|
||||
this.context = context;
|
||||
this.contextMenuClickListener = contextMenuClickListener;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.list_item_song, parent, false);
|
||||
|
||||
return new AlbumViewHolder(view, contextMenuClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
abstract static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
ImageView art;
|
||||
TextView detailsTextView;
|
||||
TextView artistTextView;
|
||||
ImageView contextMenu;
|
||||
|
||||
FileDownloadHelper.SongInfo songInfo;
|
||||
|
||||
ViewHolder(View itemView, View.OnClickListener contextMenuClickListener) {
|
||||
super(itemView);
|
||||
art = itemView.findViewById(R.id.art);
|
||||
artistTextView = itemView.findViewById(R.id.artist);
|
||||
detailsTextView = itemView.findViewById(R.id.details);
|
||||
contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||
songInfo = new FileDownloadHelper.SongInfo();
|
||||
|
||||
contextMenu.setTag(this);
|
||||
contextMenu.setOnClickListener(contextMenuClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
songInfo.songId = cursor.getInt(SongsListQuery.SONGID);
|
||||
songInfo.title = cursor.getString(SongsListQuery.TITLE);
|
||||
songInfo.fileName = cursor.getString(SongsListQuery.FILE);
|
||||
songInfo.track = cursor.getInt(SongsListQuery.TRACK);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SongViewHolder extends ViewHolder {
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
TextView titleTextView;
|
||||
|
||||
SongViewHolder(View itemView, Context context, HostManager hostManager,
|
||||
int artWidth, int artHeight, View.OnClickListener contextMenuClickListener) {
|
||||
super(itemView, contextMenuClickListener);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
|
||||
titleTextView = itemView.findViewById(R.id.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
super.bindView(cursor);
|
||||
|
||||
String title = cursor.getString(SongsListQuery.TITLE);
|
||||
titleTextView.setText(title);
|
||||
|
||||
viewHolder.title.setText(title);
|
||||
|
||||
String artist = cursor.getString(SongsListQuery.SONGDISPLAYARTIST);
|
||||
viewHolder.artist.setText(artist);
|
||||
artistTextView.setText(cursor.getString(SongsListQuery.SONGDISPLAYARTIST));
|
||||
|
||||
String albumTitle = cursor.getString(SongsListQuery.ALBUMTITLE);
|
||||
int year = cursor.getInt(SongsListQuery.YEAR);
|
||||
if (year > 0) {
|
||||
setDetails(viewHolder.details,
|
||||
setDetails(detailsTextView,
|
||||
albumTitle,
|
||||
String.valueOf(year),
|
||||
cursor.getString(SongsListQuery.GENRE));
|
||||
} else {
|
||||
setDetails(viewHolder.details,
|
||||
setDetails(detailsTextView,
|
||||
albumTitle,
|
||||
cursor.getString(SongsListQuery.GENRE));
|
||||
}
|
||||
|
@ -298,101 +368,60 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
String thumbnail = cursor.getString(SongsListQuery.THUMBNAIL);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, title,
|
||||
viewHolder.art, artWidth, artHeight);
|
||||
art, artWidth, artHeight);
|
||||
}
|
||||
|
||||
viewHolder.songInfo.artist = artist;
|
||||
viewHolder.songInfo.album = albumTitle;
|
||||
viewHolder.songInfo.songId = cursor.getInt(SongsListQuery.SONGID);
|
||||
viewHolder.songInfo.title = cursor.getString(SongsListQuery.TITLE);
|
||||
viewHolder.songInfo.fileName = cursor.getString(SongsListQuery.FILE);
|
||||
viewHolder.songInfo.track = cursor.getInt(SongsListQuery.TRACK);
|
||||
private void setDetails(TextView textView, String... elements) {
|
||||
if ((elements == null) || (elements.length < 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For the popupmenu
|
||||
viewHolder.contextMenu.setTag(viewHolder);
|
||||
viewHolder.contextMenu.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
showPopupMenu(v);
|
||||
}
|
||||
});
|
||||
ArrayList<String> details = new ArrayList<>();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
if (!TextUtils.isEmpty(elements[i]))
|
||||
details.add(elements[i]);
|
||||
}
|
||||
|
||||
textView.setText(TextUtils.join(" | ", details.toArray()));
|
||||
}
|
||||
}
|
||||
|
||||
private class AlbumSongsAdapter extends CursorAdapter {
|
||||
public static class AlbumViewHolder extends ViewHolder {
|
||||
TextView trackNumberTextView;
|
||||
TextView titleTextView;
|
||||
|
||||
public AlbumSongsAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
AlbumViewHolder(View itemView, View.OnClickListener contextMenuClickListener) {
|
||||
super(itemView, contextMenuClickListener);
|
||||
trackNumberTextView = itemView.findViewById(R.id.track_number);
|
||||
titleTextView = itemView.findViewById(R.id.song_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
|
||||
View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.list_item_song, viewGroup, false);
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.trackNumber = (TextView)view.findViewById(R.id.track_number);
|
||||
viewHolder.title = (TextView)view.findViewById(R.id.song_title);
|
||||
viewHolder.details = (TextView)view.findViewById(R.id.details);
|
||||
viewHolder.contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
viewHolder.songInfo = new FileDownloadHelper.SongInfo();
|
||||
public void bindView(Cursor cursor) {
|
||||
super.bindView(cursor);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
trackNumberTextView.setText(String.valueOf(songInfo.track));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
String artist = cursor.getString(AlbumSongsListQuery.ARTIST);
|
||||
|
||||
ViewHolder vh = (ViewHolder) view.getTag();
|
||||
titleTextView.setText(cursor.getString(AlbumSongsListQuery.TITLE));
|
||||
|
||||
vh.title.setText(cursor.getString(AlbumSongsListQuery.TITLE));
|
||||
|
||||
vh.songInfo.artist = artist;
|
||||
vh.songInfo.album = albumTitle;
|
||||
vh.songInfo.songId = cursor.getInt(SongsListQuery.SONGID);
|
||||
vh.songInfo.title = cursor.getString(SongsListQuery.TITLE);
|
||||
vh.songInfo.fileName = cursor.getString(SongsListQuery.FILE);
|
||||
vh.songInfo.track = cursor.getInt(SongsListQuery.TRACK);
|
||||
|
||||
vh.trackNumber.setText(String.valueOf(vh.songInfo.track));
|
||||
songInfo.artist = artist;
|
||||
songInfo.album = albumTitle;
|
||||
|
||||
String duration = UIUtils.formatTime(cursor.getInt(AlbumSongsListQuery.DURATION));
|
||||
String detailsText = TextUtils.isEmpty(artist) ? duration : duration + " | " + artist;
|
||||
vh.details.setText(detailsText);
|
||||
|
||||
vh.contextMenu.setTag(vh);
|
||||
vh.contextMenu.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
showPopupMenu(v);
|
||||
}
|
||||
});
|
||||
detailsTextView.setText(detailsText);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
ImageView art;
|
||||
TextView title;
|
||||
TextView details;
|
||||
TextView artist;
|
||||
TextView trackNumber;
|
||||
ImageView contextMenu;
|
||||
|
||||
FileDownloadHelper.SongInfo songInfo;
|
||||
}
|
||||
|
||||
private void showPopupMenu(View v) {
|
||||
final ViewHolder viewHolder = (ViewHolder) v.getTag();
|
||||
|
||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||
playListItem.songid = viewHolder.songInfo.songId;
|
||||
|
||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
||||
final PopupMenu popupMenu = new PopupMenu(getContext(), v);
|
||||
popupMenu.getMenuInflater().inflate(R.menu.song_item, popupMenu.getMenu());
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
|
@ -407,9 +436,9 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
case R.id.download:
|
||||
ArrayList<FileDownloadHelper.SongInfo> songInfoList = new ArrayList<>();
|
||||
songInfoList.add(viewHolder.songInfo);
|
||||
UIUtils.downloadSongs(getActivity(),
|
||||
UIUtils.downloadSongs(getContext(),
|
||||
songInfoList,
|
||||
HostManager.getInstance(getActivity()).getHostInfo(),
|
||||
HostManager.getInstance(getContext()).getHostInfo(),
|
||||
callbackHandler);
|
||||
}
|
||||
return false;
|
||||
|
@ -417,19 +446,4 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
|
||||
|
||||
private void setDetails(TextView textView, String... elements) {
|
||||
if ((elements == null) || (elements.length < 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<String> details = new ArrayList<>();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
if (!TextUtils.isEmpty(elements[i]))
|
||||
details.add(elements[i]);
|
||||
}
|
||||
|
||||
textView.setText(TextUtils.join(" | ", details.toArray()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,11 @@ import android.support.annotation.NonNull;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -43,14 +41,14 @@ import org.xbmc.kore.jsonrpc.method.GUI;
|
|||
import org.xbmc.kore.jsonrpc.type.FavouriteType;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.ui.AbstractListFragment;
|
||||
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class FavouritesListFragment extends AbstractListFragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||
private static final String TAG = "FavouritesListFragment";
|
||||
|
||||
|
@ -63,7 +61,7 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
}
|
||||
|
||||
@Override
|
||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
||||
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||
final ApiCallback<String> genericApiCallback = new ApiCallback<String>() {
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
|
@ -75,9 +73,9 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
return new AdapterView.OnItemClickListener() {
|
||||
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
public void onItemClick(View view, int position) {
|
||||
final FavouritesAdapter favouritesAdapter = (FavouritesAdapter) getAdapter();
|
||||
final HostManager hostManager = HostManager.getInstance(getActivity());
|
||||
|
||||
|
@ -105,7 +103,7 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
}
|
||||
|
||||
@Override
|
||||
protected BaseAdapter createAdapter() {
|
||||
protected RecyclerView.Adapter createAdapter() {
|
||||
return new FavouritesAdapter(getActivity(), HostManager.getInstance(getActivity()));
|
||||
}
|
||||
|
||||
|
@ -126,7 +124,7 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
|
||||
// To prevent the empty text from appearing on the first load, set it now
|
||||
getEmptyView().setText(getString(R.string.no_channels_found_refresh));
|
||||
setupFavouritesList(result.items);
|
||||
((FavouritesAdapter) getAdapter()).setFavouriteItems(result.items);
|
||||
hideRefreshAnimation();
|
||||
}
|
||||
|
||||
|
@ -143,25 +141,15 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
}, callbackHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set the GridView with the favourites that are coming from the host.
|
||||
*
|
||||
* @param favourites the favourites list that is supplied to the GridView.
|
||||
*/
|
||||
private void setupFavouritesList(List<FavouriteType.DetailsFavourite> favourites) {
|
||||
final FavouritesAdapter favouritesAdapter = (FavouritesAdapter) getAdapter();
|
||||
favouritesAdapter.clear();
|
||||
favouritesAdapter.addAll(favourites);
|
||||
favouritesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private static class FavouritesAdapter extends ArrayAdapter<FavouriteType.DetailsFavourite> {
|
||||
private static class FavouritesAdapter extends RecyclerView.Adapter {
|
||||
|
||||
private final HostManager hostManager;
|
||||
private final int artWidth, artHeight;
|
||||
private Context context;
|
||||
private ArrayList<FavouriteType.DetailsFavourite> favouriteItems = new ArrayList<>();
|
||||
|
||||
FavouritesAdapter(@NonNull Context context, HostManager hostManager) {
|
||||
super(context, R.layout.grid_item_channel);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
Resources resources = context.getResources();
|
||||
artWidth = (int) (resources.getDimension(R.dimen.channellist_art_width) /
|
||||
|
@ -170,23 +158,59 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public void setFavouriteItems(List<FavouriteType.DetailsFavourite> favouriteItems) {
|
||||
this.favouriteItems.clear();
|
||||
this.favouriteItems.addAll(favouriteItems);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public FavouriteType.DetailsFavourite getItem(int position) {
|
||||
return favouriteItems.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item_channel,
|
||||
parent, false);
|
||||
final FavouriteItemViewHolder vh = new FavouriteItemViewHolder(convertView);
|
||||
convertView.setTag(vh);
|
||||
}
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.grid_item_channel,
|
||||
parent, false);
|
||||
return new ViewHolder(view, context, hostManager, artWidth, artHeight);
|
||||
}
|
||||
|
||||
final FavouriteItemViewHolder vh = (FavouriteItemViewHolder) convertView.getTag();
|
||||
final FavouriteType.DetailsFavourite favouriteDetail = getItem(position);
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
((ViewHolder) holder).bindView(favouriteItems.get(position));
|
||||
}
|
||||
|
||||
// We don't need the context menu here.
|
||||
vh.contextMenu.setVisibility(View.GONE);
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return favouriteItems.size();
|
||||
}
|
||||
}
|
||||
|
||||
vh.titleView.setText(favouriteDetail.title);
|
||||
private static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
final ImageView artView;
|
||||
final TextView titleView;
|
||||
final TextView detailView;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
detailView = itemView.findViewById(R.id.details);
|
||||
|
||||
View contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
void bindView(FavouriteType.DetailsFavourite favouriteDetail) {
|
||||
titleView.setText(favouriteDetail.title);
|
||||
|
||||
@StringRes final int typeRes;
|
||||
switch (favouriteDetail.type) {
|
||||
|
@ -202,27 +226,11 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
|||
default:
|
||||
typeRes = R.string.unknown;
|
||||
}
|
||||
vh.detailView.setText(typeRes);
|
||||
detailView.setText(typeRes);
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager,
|
||||
favouriteDetail.thumbnail, favouriteDetail.title,
|
||||
vh.artView, artWidth, artHeight);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private static class FavouriteItemViewHolder {
|
||||
final ImageView artView;
|
||||
final ImageView contextMenu;
|
||||
final TextView titleView;
|
||||
final TextView detailView;
|
||||
|
||||
FavouriteItemViewHolder(View v) {
|
||||
artView = ButterKnife.findById(v, R.id.art);
|
||||
contextMenu = ButterKnife.findById(v, R.id.list_context_menu);
|
||||
titleView = ButterKnife.findById(v, R.id.title);
|
||||
detailView = ButterKnife.findById(v, R.id.details);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
favouriteDetail.thumbnail, favouriteDetail.title,
|
||||
artView, artWidth, artHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,14 +21,12 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
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.ImageView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
@ -45,6 +43,7 @@ import org.xbmc.kore.jsonrpc.type.ListType;
|
|||
import org.xbmc.kore.jsonrpc.type.PlayerType;
|
||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||
import org.xbmc.kore.ui.AbstractListFragment;
|
||||
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
@ -112,17 +111,17 @@ public class MediaFileListFragment extends AbstractListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
||||
return new AdapterView.OnItemClickListener() {
|
||||
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
public void onItemClick(View view, int position) {
|
||||
handleFileSelect(((MediaFileListAdapter) getAdapter()).getItem(position));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseAdapter createAdapter() {
|
||||
protected RecyclerView.Adapter createAdapter() {
|
||||
return new MediaFileListAdapter(getActivity(), R.layout.grid_item_file);
|
||||
}
|
||||
|
||||
|
@ -211,7 +210,7 @@ public class MediaFileListFragment extends AbstractListFragment {
|
|||
}
|
||||
|
||||
public boolean atRootDirectory() {
|
||||
if (getAdapter().getCount() == 0)
|
||||
if (getAdapter().getItemCount() == 0)
|
||||
return true;
|
||||
FileLocation fl = ((MediaFileListAdapter) getAdapter()).getItem(0);
|
||||
if (fl == null)
|
||||
|
@ -500,11 +499,11 @@ public class MediaFileListFragment extends AbstractListFragment {
|
|||
|
||||
}
|
||||
|
||||
private class MediaFileListAdapter extends BaseAdapter implements ListAdapter {
|
||||
private class MediaFileListAdapter extends RecyclerView.Adapter {
|
||||
|
||||
Context ctx;
|
||||
int resource;
|
||||
List<FileLocation> fileLocationItems = null;
|
||||
List<FileLocation> fileLocationItems;
|
||||
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
|
@ -552,7 +551,7 @@ public class MediaFileListFragment extends AbstractListFragment {
|
|||
}
|
||||
};
|
||||
|
||||
public MediaFileListAdapter(Context context, int resource) {
|
||||
MediaFileListAdapter(Context context, int resource) {
|
||||
super();
|
||||
this.ctx = context;
|
||||
this.resource = resource;
|
||||
|
@ -580,20 +579,10 @@ public class MediaFileListFragment extends AbstractListFragment {
|
|||
|
||||
public List<FileLocation> getFileItemList() {
|
||||
if (fileLocationItems == null)
|
||||
return new ArrayList<FileLocation>();
|
||||
return new ArrayList<FileLocation>(fileLocationItems);
|
||||
return new ArrayList<>();
|
||||
return new ArrayList<>(fileLocationItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (fileLocationItems == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return fileLocationItems.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileLocation getItem(int position) {
|
||||
if (fileLocationItems == null) {
|
||||
return null;
|
||||
|
@ -602,74 +591,80 @@ public class MediaFileListFragment extends AbstractListFragment {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(ctx)
|
||||
.inflate(resource, parent, false);
|
||||
return new ViewHolder(view, getContext(), hostManager, artWidth, artHeight, itemMenuClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
FileLocation fileLocation = this.getItem(position);
|
||||
((ViewHolder) holder).bindView(fileLocation, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(ctx)
|
||||
.inflate(resource, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
viewHolder = new ViewHolder();
|
||||
viewHolder.art = (ImageView) convertView.findViewById(R.id.art);
|
||||
viewHolder.title = (TextView) convertView.findViewById(R.id.title);
|
||||
viewHolder.details = (TextView) convertView.findViewById(R.id.details);
|
||||
viewHolder.contextMenu = (ImageView) convertView.findViewById(R.id.list_context_menu);
|
||||
viewHolder.sizeDuration = (TextView) convertView.findViewById(R.id.size_duration);
|
||||
|
||||
convertView.setTag(viewHolder);
|
||||
}
|
||||
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
FileLocation fileLocation = this.getItem(position);
|
||||
|
||||
// if (fileLocation.isDirectory) {
|
||||
// viewHolder.title.setText(fileLocation.title);
|
||||
// viewHolder.details.setText("");
|
||||
// } else {
|
||||
// viewHolder.title.setText("");
|
||||
// viewHolder.details.setText(fileLocation.title);
|
||||
// }
|
||||
viewHolder.title.setText(fileLocation.title);
|
||||
viewHolder.details.setText(fileLocation.details);
|
||||
viewHolder.sizeDuration.setText(fileLocation.sizeDuration);
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(getActivity(), hostManager,
|
||||
fileLocation.artUrl, fileLocation.title,
|
||||
viewHolder.art, artWidth, artHeight);
|
||||
// For the popup menu
|
||||
if (fileLocation.isDirectory) {
|
||||
viewHolder.contextMenu.setVisibility(View.GONE);
|
||||
public int getItemCount() {
|
||||
if (fileLocationItems == null) {
|
||||
return 0;
|
||||
} else {
|
||||
viewHolder.contextMenu.setVisibility(View.VISIBLE);
|
||||
viewHolder.contextMenu.setTag(position);
|
||||
viewHolder.contextMenu.setOnClickListener(itemMenuClickListener);
|
||||
return fileLocationItems.size();
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
private static class ViewHolder {
|
||||
private static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView art;
|
||||
TextView title;
|
||||
TextView details;
|
||||
TextView sizeDuration;
|
||||
ImageView contextMenu;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
|
||||
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight,
|
||||
View.OnClickListener itemMenuClickListener) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
art = itemView.findViewById(R.id.art);
|
||||
title = itemView.findViewById(R.id.title);
|
||||
details = itemView.findViewById(R.id.details);
|
||||
contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||
sizeDuration = itemView.findViewById(R.id.size_duration);
|
||||
contextMenu.setOnClickListener(itemMenuClickListener);
|
||||
}
|
||||
|
||||
public void bindView(FileLocation fileLocation, int position) {
|
||||
title.setText(fileLocation.title);
|
||||
details.setText(fileLocation.details);
|
||||
sizeDuration.setText(fileLocation.sizeDuration);
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
fileLocation.artUrl, fileLocation.title,
|
||||
art, artWidth, artHeight);
|
||||
// For the popup menu
|
||||
if (fileLocation.isDirectory) {
|
||||
contextMenu.setVisibility(View.GONE);
|
||||
} else {
|
||||
contextMenu.setVisibility(View.VISIBLE);
|
||||
contextMenu.setTag(position);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileLocation implements Parcelable {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui.sections.video;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -33,7 +32,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -45,7 +43,8 @@ import org.xbmc.kore.provider.MediaContract;
|
|||
import org.xbmc.kore.provider.MediaDatabase;
|
||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.AbstractFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
@ -63,7 +62,7 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
|||
// Activity listener
|
||||
private OnMovieSelectedListener listenerActivity;
|
||||
|
||||
private boolean showWatchedStatus;
|
||||
private static boolean showWatchedStatus;
|
||||
|
||||
@Override
|
||||
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_MOVIES; }
|
||||
|
@ -77,7 +76,7 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new MoviesAdapter(getActivity());
|
||||
}
|
||||
|
||||
|
@ -310,15 +309,13 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
|||
int PLAYCOUNT = 9;
|
||||
}
|
||||
|
||||
private class MoviesAdapter extends CursorAdapter {
|
||||
private class MoviesAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
private int themeAccentColor;
|
||||
|
||||
public MoviesAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
|
||||
MoviesAdapter(Context context) {
|
||||
// Get the default accent color
|
||||
Resources.Theme theme = context.getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||
|
@ -340,83 +337,90 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
|||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
final View view = LayoutInflater.from(getContext())
|
||||
.inflate(R.layout.grid_item_movie, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.detailsView = (TextView)view.findViewById(R.id.details);
|
||||
viewHolder.durationView = (TextView)view.findViewById(R.id.duration);
|
||||
viewHolder.checkmarkView = (ImageView)view.findViewById(R.id.checkmark);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
|
||||
// Save the movie id
|
||||
viewHolder.dataHolder.setId(cursor.getInt(MovieListQuery.MOVIEID));
|
||||
viewHolder.dataHolder.setTitle(cursor.getString(MovieListQuery.TITLE));
|
||||
viewHolder.dataHolder.setUndertitle(cursor.getString(MovieListQuery.TAGLINE));
|
||||
|
||||
int movieYear = cursor.getInt(MovieListQuery.YEAR);
|
||||
viewHolder.dataHolder.setRating(cursor.getDouble(MovieListQuery.RATING));
|
||||
viewHolder.dataHolder.setMaxRating(10);
|
||||
|
||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
||||
|
||||
String genres = cursor.getString(MovieListQuery.GENRES);
|
||||
String details = TextUtils.isEmpty(viewHolder.dataHolder.getUnderTitle()) ?
|
||||
genres : viewHolder.dataHolder.getUnderTitle();
|
||||
viewHolder.detailsView.setText(details);
|
||||
|
||||
int runtime = cursor.getInt(MovieListQuery.RUNTIME) / 60;
|
||||
String duration = runtime > 0 ?
|
||||
String.format(context.getString(R.string.minutes_abbrev), String.valueOf(runtime)) +
|
||||
" | " + movieYear :
|
||||
String.valueOf(movieYear);
|
||||
viewHolder.durationView.setText(duration);
|
||||
viewHolder.dataHolder.setDetails(duration + "\n" + details);
|
||||
|
||||
viewHolder.dataHolder.setPosterUrl(cursor.getString(MovieListQuery.THUMBNAIL));
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
viewHolder.dataHolder.getPosterUrl(),
|
||||
viewHolder.dataHolder.getTitle(),
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
if (showWatchedStatus && (cursor.getInt(MovieListQuery.PLAYCOUNT) > 0)) {
|
||||
viewHolder.checkmarkView.setVisibility(View.VISIBLE);
|
||||
viewHolder.checkmarkView.setColorFilter(themeAccentColor);
|
||||
} else {
|
||||
viewHolder.checkmarkView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
viewHolder.artView.setTransitionName("a" + viewHolder.dataHolder.getId());
|
||||
}
|
||||
return new ViewHolder(view, getContext(), themeAccentColor, hostManager, artWidth, artHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView titleView;
|
||||
TextView detailsView;
|
||||
TextView durationView;
|
||||
ImageView checkmarkView;
|
||||
ImageView artView;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
int themeAccentColor;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
AbstractFragment.DataHolder dataHolder = new AbstractFragment.DataHolder(0);
|
||||
|
||||
ViewHolder(View itemView, Context context, int themeAccentColor,
|
||||
HostManager hostManager,
|
||||
int artWidth, int artHeight) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.themeAccentColor = themeAccentColor;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
detailsView = itemView.findViewById(R.id.details);
|
||||
durationView = itemView.findViewById(R.id.duration);
|
||||
checkmarkView = itemView.findViewById(R.id.checkmark);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
// Save the movie id
|
||||
dataHolder.setId(cursor.getInt(MovieListQuery.MOVIEID));
|
||||
dataHolder.setTitle(cursor.getString(MovieListQuery.TITLE));
|
||||
dataHolder.setUndertitle(cursor.getString(MovieListQuery.TAGLINE));
|
||||
|
||||
int movieYear = cursor.getInt(MovieListQuery.YEAR);
|
||||
dataHolder.setRating(cursor.getDouble(MovieListQuery.RATING));
|
||||
dataHolder.setMaxRating(10);
|
||||
|
||||
titleView.setText(dataHolder.getTitle());
|
||||
|
||||
String genres = cursor.getString(MovieListQuery.GENRES);
|
||||
String details = TextUtils.isEmpty(dataHolder.getUnderTitle()) ?
|
||||
genres : dataHolder.getUnderTitle();
|
||||
detailsView.setText(details);
|
||||
|
||||
int runtime = cursor.getInt(MovieListQuery.RUNTIME) / 60;
|
||||
String duration = runtime > 0 ?
|
||||
String.format(context.getString(R.string.minutes_abbrev), String.valueOf(runtime)) +
|
||||
" | " + movieYear :
|
||||
String.valueOf(movieYear);
|
||||
durationView.setText(duration);
|
||||
dataHolder.setDetails(duration + "\n" + details);
|
||||
|
||||
dataHolder.setPosterUrl(cursor.getString(MovieListQuery.THUMBNAIL));
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
dataHolder.getPosterUrl(),
|
||||
dataHolder.getTitle(),
|
||||
artView, artWidth, artHeight);
|
||||
|
||||
if (showWatchedStatus && (cursor.getInt(MovieListQuery.PLAYCOUNT) > 0)) {
|
||||
checkmarkView.setVisibility(View.VISIBLE);
|
||||
checkmarkView.setColorFilter(themeAccentColor);
|
||||
} else {
|
||||
checkmarkView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
artView.setTransitionName("a" + dataHolder.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@ import org.xbmc.kore.utils.UIUtils;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
/**
|
||||
|
@ -96,7 +96,7 @@ public class PVRChannelsListFragment extends Fragment
|
|||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_generic_media_list, container, false);
|
||||
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pvr_list, container, false);
|
||||
unbinder = ButterKnife.bind(this, root);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
|
|
|
@ -42,8 +42,8 @@ import org.xbmc.kore.utils.UIUtils;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
/**
|
||||
|
@ -75,7 +75,7 @@ public class PVRRecordingsListFragment extends Fragment
|
|||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_generic_media_list, container, false);
|
||||
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pvr_list, container, false);
|
||||
unbinder = ButterKnife.bind(this, root);
|
||||
|
||||
hostManager = HostManager.getInstance(getActivity());
|
||||
|
|
|
@ -33,7 +33,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
@ -46,7 +45,8 @@ import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
|||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.AbstractFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
@ -114,9 +114,8 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
|||
listenerActivity.onEpisodeSelected(tvshowId, tag);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new SeasonsEpisodesAdapter(getActivity());
|
||||
}
|
||||
|
||||
|
@ -137,7 +136,6 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
|||
EpisodesListQuery.PROJECTION, selection.toString(), null, EpisodesListQuery.SORT);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
|
@ -218,25 +216,23 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
|
||||
private class SeasonsEpisodesAdapter extends CursorAdapter {
|
||||
private class SeasonsEpisodesAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
private int themeAccentColor;
|
||||
private HostManager hostManager;
|
||||
private int artWidth;
|
||||
private int artHeight;
|
||||
|
||||
public SeasonsEpisodesAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
|
||||
SeasonsEpisodesAdapter(Context context) {
|
||||
// Get the default accent color
|
||||
Resources.Theme theme = context.getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||
R.attr.colorAccent
|
||||
});
|
||||
|
||||
themeAccentColor = styledAttributes.getColor(styledAttributes.getIndex(0), getResources().getColor(R.color.accent_default));
|
||||
styledAttributes.recycle();
|
||||
|
||||
this.hostManager = HostManager.getInstance(context);
|
||||
hostManager = HostManager.getInstance(context);
|
||||
|
||||
// Get the art dimensions
|
||||
Resources resources = context.getResources();
|
||||
|
@ -246,77 +242,84 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
|||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
.inflate(R.layout.list_item_episode, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.detailsView = (TextView)view.findViewById(R.id.details);
|
||||
viewHolder.episodenumberView = (TextView)view.findViewById(R.id.episode_number);
|
||||
viewHolder.contextMenuView = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
viewHolder.checkmarkView = (ImageView)view.findViewById(R.id.checkmark);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
|
||||
// Save the episode id
|
||||
viewHolder.dataHolder.setId(cursor.getInt(EpisodesListQuery.EPISODEID));
|
||||
viewHolder.dataHolder.setTitle(cursor.getString(EpisodesListQuery.TITLE));
|
||||
|
||||
viewHolder.episodenumberView.setText(
|
||||
String.format(context.getString(R.string.episode_number),
|
||||
cursor.getInt(EpisodesListQuery.EPISODE)));
|
||||
int runtime = cursor.getInt(EpisodesListQuery.RUNTIME) / 60;
|
||||
String duration = runtime > 0 ?
|
||||
String.format(context.getString(R.string.minutes_abbrev), String.valueOf(runtime)) +
|
||||
" | " + cursor.getString(EpisodesListQuery.FIRSTAIRED) :
|
||||
cursor.getString(EpisodesListQuery.FIRSTAIRED);
|
||||
viewHolder.titleView.setText(cursor.getString(EpisodesListQuery.TITLE));
|
||||
viewHolder.detailsView.setText(duration);
|
||||
|
||||
if (cursor.getInt(EpisodesListQuery.PLAYCOUNT) > 0) {
|
||||
viewHolder.checkmarkView.setVisibility(View.VISIBLE);
|
||||
viewHolder.checkmarkView.setColorFilter(themeAccentColor);
|
||||
} else {
|
||||
viewHolder.checkmarkView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
cursor.getString(EpisodesListQuery.THUMBNAIL),
|
||||
viewHolder.dataHolder.getTitle(),
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
// For the popupmenu
|
||||
ImageView contextMenu = (ImageView)view.findViewById(R.id.list_context_menu);
|
||||
contextMenu.setTag(viewHolder);
|
||||
contextMenu.setOnClickListener(contextlistItemMenuClickListener);
|
||||
public RecyclerViewCursorAdapter.CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(getActivity())
|
||||
.inflate(R.layout.list_item_episode, parent, false);
|
||||
return new ViewHolder(view, getActivity(), themeAccentColor,
|
||||
contextlistItemMenuClickListener, hostManager,
|
||||
artWidth, artHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern, only for episodes
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView titleView;
|
||||
TextView detailsView;
|
||||
TextView episodenumberView;
|
||||
ImageView contextMenuView;
|
||||
ImageView checkmarkView;
|
||||
ImageView artView;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
Context context;
|
||||
int themeAccentColor;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
AbstractFragment.DataHolder dataHolder = new AbstractFragment.DataHolder(0);
|
||||
|
||||
ViewHolder(View itemView, Context context, int themeAccentColor,
|
||||
View.OnClickListener contextlistItemMenuClickListener,
|
||||
HostManager hostManager,
|
||||
int artWidth, int artHeight) {
|
||||
super(itemView);
|
||||
this.context = context;
|
||||
this.themeAccentColor = themeAccentColor;
|
||||
this.hostManager = hostManager;
|
||||
this.artWidth = artWidth;
|
||||
this.artHeight = artHeight;
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
detailsView = itemView.findViewById(R.id.details);
|
||||
episodenumberView = itemView.findViewById(R.id.episode_number);
|
||||
contextMenuView = itemView.findViewById(R.id.list_context_menu);
|
||||
checkmarkView = itemView.findViewById(R.id.checkmark);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
contextMenuView.setOnClickListener(contextlistItemMenuClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
// Save the episode id
|
||||
dataHolder.setId(cursor.getInt(EpisodesListQuery.EPISODEID));
|
||||
dataHolder.setTitle(cursor.getString(EpisodesListQuery.TITLE));
|
||||
|
||||
episodenumberView.setText(
|
||||
String.format(context.getString(R.string.episode_number),
|
||||
cursor.getInt(EpisodesListQuery.EPISODE)));
|
||||
int runtime = cursor.getInt(EpisodesListQuery.RUNTIME) / 60;
|
||||
String duration = runtime > 0 ?
|
||||
String.format(context.getString(R.string.minutes_abbrev), String.valueOf(runtime)) +
|
||||
" | " + cursor.getString(EpisodesListQuery.FIRSTAIRED) :
|
||||
cursor.getString(EpisodesListQuery.FIRSTAIRED);
|
||||
titleView.setText(cursor.getString(EpisodesListQuery.TITLE));
|
||||
detailsView.setText(duration);
|
||||
|
||||
if (cursor.getInt(EpisodesListQuery.PLAYCOUNT) > 0) {
|
||||
checkmarkView.setVisibility(View.VISIBLE);
|
||||
checkmarkView.setColorFilter(themeAccentColor);
|
||||
} else {
|
||||
checkmarkView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
cursor.getString(EpisodesListQuery.THUMBNAIL),
|
||||
dataHolder.getTitle(),
|
||||
artView, artWidth, artHeight);
|
||||
|
||||
contextMenuView.setTag(this);
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener contextlistItemMenuClickListener = new View.OnClickListener() {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui.sections.video;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -34,7 +33,6 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
@ -48,6 +46,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
|||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
@ -65,7 +64,7 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
|||
// Activity listener
|
||||
private OnTVShowSelectedListener listenerActivity;
|
||||
|
||||
private boolean showWatchedStatus;
|
||||
private static boolean showWatchedStatus;
|
||||
|
||||
@Override
|
||||
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_TVSHOWS; }
|
||||
|
@ -79,7 +78,7 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CursorAdapter createAdapter() {
|
||||
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||
return new TVShowsAdapter(getActivity());
|
||||
}
|
||||
|
||||
|
@ -309,7 +308,7 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
|||
int GENRES = 13;
|
||||
}
|
||||
|
||||
private class TVShowsAdapter extends CursorAdapter {
|
||||
private class TVShowsAdapter extends RecyclerViewCursorAdapter {
|
||||
|
||||
private HostManager hostManager;
|
||||
private int artWidth, artHeight;
|
||||
|
@ -317,8 +316,6 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
|||
inProgressColor, finishedColor;
|
||||
|
||||
public TVShowsAdapter(Context context) {
|
||||
super(context, null, 0);
|
||||
|
||||
// Get the default accent color
|
||||
Resources.Theme theme = context.getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||
|
@ -344,82 +341,98 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
|||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
||||
final View view = LayoutInflater.from(context)
|
||||
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
final View view = LayoutInflater.from(getContext())
|
||||
.inflate(R.layout.grid_item_tvshow, parent, false);
|
||||
|
||||
// Setup View holder pattern
|
||||
ViewHolder viewHolder = new ViewHolder();
|
||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
||||
viewHolder.detailsView = (TextView)view.findViewById(R.id.details);
|
||||
viewHolder.premieredView = (TextView)view.findViewById(R.id.premiered);
|
||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
||||
viewHolder.watchedProgressView = (ProgressBar)view.findViewById(R.id.tv_shows_progress_bar);
|
||||
ViewHolder viewHolder = new ViewHolder(view, getContext(),
|
||||
themeAccentColor, inProgressColor, finishedColor,
|
||||
hostManager,
|
||||
artWidth, artHeight);
|
||||
|
||||
view.setTag(viewHolder);
|
||||
return view;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder vh = (ViewHolder)view.getTag();
|
||||
|
||||
// Save the movie id
|
||||
vh.dataHolder.setId(cursor.getInt(TVShowListQuery.TVSHOWID));
|
||||
vh.dataHolder.setTitle(cursor.getString(TVShowListQuery.TITLE));
|
||||
vh.dataHolder.setDescription(cursor.getString(TVShowListQuery.PLOT));
|
||||
vh.dataHolder.setRating(cursor.getInt(TVShowListQuery.RATING));
|
||||
int numEpisodes = cursor.getInt(TVShowListQuery.EPISODE);
|
||||
int watchedEpisodes = cursor.getInt(TVShowListQuery.WATCHEDEPISODES);
|
||||
|
||||
vh.titleView.setText(vh.dataHolder.getTitle());
|
||||
String details = String.format(context.getString(R.string.num_episodes),
|
||||
numEpisodes, numEpisodes - watchedEpisodes);
|
||||
vh.detailsView.setText(details);
|
||||
vh.dataHolder.setUndertitle(details);
|
||||
|
||||
String premiered = String.format(context.getString(R.string.premiered),
|
||||
cursor.getString(TVShowListQuery.PREMIERED));
|
||||
vh.premieredView.setText(premiered);
|
||||
vh.dataHolder.setDetails(premiered);
|
||||
vh.dataHolder.setPosterUrl(cursor.getString(TVShowListQuery.THUMBNAIL));
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
vh.dataHolder.getPosterUrl(),
|
||||
vh.dataHolder.getTitle(),
|
||||
vh.artView, artWidth, artHeight);
|
||||
|
||||
if (showWatchedStatus) {
|
||||
vh.watchedProgressView.setVisibility(View.VISIBLE);
|
||||
vh.watchedProgressView.setMax(numEpisodes);
|
||||
vh.watchedProgressView.setProgress(watchedEpisodes);
|
||||
} else {
|
||||
vh.watchedProgressView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
if (showWatchedStatus) {
|
||||
int watchedColor = (numEpisodes - watchedEpisodes == 0)? finishedColor : inProgressColor;
|
||||
vh.watchedProgressView.setProgressTintList(ColorStateList.valueOf(watchedColor));
|
||||
}
|
||||
vh.artView.setTransitionName("a" + vh.dataHolder.getId());
|
||||
}
|
||||
return viewHolder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
public static class ViewHolder {
|
||||
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||
TextView titleView;
|
||||
TextView detailsView;
|
||||
TextView premieredView;
|
||||
ImageView artView;
|
||||
ProgressBar watchedProgressView;
|
||||
Context context;
|
||||
int themeAccentColor, inProgressColor, finishedColor;
|
||||
HostManager hostManager;
|
||||
int artWidth;
|
||||
int artHeight;
|
||||
|
||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||
|
||||
ViewHolder(View itemView, Context context,
|
||||
int themeAccentColor, int inProgressColor, int finishedColor,
|
||||
HostManager hostManager,
|
||||
int artWidth, int artHeight) {
|
||||
super(itemView);
|
||||
this.hostManager = hostManager;
|
||||
this.context = context;
|
||||
this.artHeight = artHeight;
|
||||
this.artWidth = artWidth;
|
||||
this.themeAccentColor = themeAccentColor;
|
||||
this.inProgressColor = inProgressColor;
|
||||
this.finishedColor = finishedColor;
|
||||
titleView = itemView.findViewById(R.id.title);
|
||||
detailsView = itemView.findViewById(R.id.details);
|
||||
premieredView = itemView.findViewById(R.id.premiered);
|
||||
artView = itemView.findViewById(R.id.art);
|
||||
watchedProgressView = itemView.findViewById(R.id.tv_shows_progress_bar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(Cursor cursor) {
|
||||
// Save the movie id
|
||||
dataHolder.setId(cursor.getInt(TVShowListQuery.TVSHOWID));
|
||||
dataHolder.setTitle(cursor.getString(TVShowListQuery.TITLE));
|
||||
dataHolder.setDescription(cursor.getString(TVShowListQuery.PLOT));
|
||||
dataHolder.setRating(cursor.getInt(TVShowListQuery.RATING));
|
||||
int numEpisodes = cursor.getInt(TVShowListQuery.EPISODE);
|
||||
int watchedEpisodes = cursor.getInt(TVShowListQuery.WATCHEDEPISODES);
|
||||
|
||||
titleView.setText(dataHolder.getTitle());
|
||||
String details = String.format(context.getString(R.string.num_episodes),
|
||||
numEpisodes, numEpisodes - watchedEpisodes);
|
||||
detailsView.setText(details);
|
||||
dataHolder.setUndertitle(details);
|
||||
|
||||
String premiered = String.format(context.getString(R.string.premiered),
|
||||
cursor.getString(TVShowListQuery.PREMIERED));
|
||||
premieredView.setText(premiered);
|
||||
dataHolder.setDetails(premiered);
|
||||
dataHolder.setPosterUrl(cursor.getString(TVShowListQuery.THUMBNAIL));
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
dataHolder.getPosterUrl(),
|
||||
dataHolder.getTitle(),
|
||||
artView, artWidth, artHeight);
|
||||
|
||||
if (showWatchedStatus) {
|
||||
watchedProgressView.setVisibility(View.VISIBLE);
|
||||
watchedProgressView.setMax(numEpisodes);
|
||||
watchedProgressView.setProgress(watchedEpisodes);
|
||||
} else {
|
||||
watchedProgressView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
if (showWatchedStatus) {
|
||||
int watchedColor = (numEpisodes - watchedEpisodes == 0)? finishedColor : inProgressColor;
|
||||
watchedProgressView.setProgressTintList(ColorStateList.valueOf(watchedColor));
|
||||
}
|
||||
artView.setTransitionName("a" + dataHolder.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright 2018 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.viewgroups;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* <p>A Recycler view using a grid layout that supports auto sizing and showing an empty view when the adapter
|
||||
* has no items.
|
||||
* </p>
|
||||
* <p>
|
||||
* You can set the column width and column count using styleables:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>android:columnWidth=INTEGER</li>
|
||||
* <li>android:columnCount=INTEGER</li>
|
||||
* </ul>
|
||||
*
|
||||
* Inspired by <a href="http://blog.sqisland.com/2014/12/recyclerview-autofit-grid.html">RecyclerView: Autofit grid</a>
|
||||
*/
|
||||
public class RecyclerViewEmptyViewSupport extends RecyclerView {
|
||||
|
||||
public final static int AUTO_FIT = -1;
|
||||
|
||||
private View emptyView;
|
||||
private OnItemClickListener onItemClickListener;
|
||||
private int columnWidth;
|
||||
private int columnCount = AUTO_FIT;
|
||||
private GridLayoutManager gridLayoutManager;
|
||||
private boolean multiColumnSupported;
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(View v, int position);
|
||||
}
|
||||
|
||||
public RecyclerViewEmptyViewSupport(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public RecyclerViewEmptyViewSupport(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ResourceType")
|
||||
public RecyclerViewEmptyViewSupport(Context context, @Nullable AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
setSaveEnabled(true);
|
||||
|
||||
if (attrs != null) {
|
||||
int[] attrsArray = {
|
||||
android.R.attr.columnWidth, android.R.attr.columnCount
|
||||
};
|
||||
TypedArray array = context.obtainStyledAttributes(
|
||||
attrs, attrsArray);
|
||||
columnWidth = array.getDimensionPixelSize(0, -1);
|
||||
columnCount = array.getInteger(1, AUTO_FIT);
|
||||
array.recycle();
|
||||
}
|
||||
|
||||
gridLayoutManager = new GridLayoutManager(getContext(), 1);
|
||||
setLayoutManager(gridLayoutManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdapter(final Adapter adapter) {
|
||||
super.setAdapter(adapter);
|
||||
|
||||
if (adapter == null)
|
||||
return;
|
||||
|
||||
adapter.registerAdapterDataObserver(new AdapterDataObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
super.onChanged();
|
||||
|
||||
if (emptyView == null)
|
||||
return;
|
||||
|
||||
if (adapter.getItemCount() == 0) {
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
setVisibility(View.GONE);
|
||||
} else {
|
||||
emptyView.setVisibility(View.GONE);
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(final View child) {
|
||||
super.onViewAdded(child);
|
||||
child.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onItemClickListener.onItemClick(v, getChildAdapterPosition(child));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthSpec, int heightSpec) {
|
||||
super.onMeasure(widthSpec, heightSpec);
|
||||
|
||||
int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
|
||||
multiColumnSupported = spanCount > 1;
|
||||
|
||||
if (columnCount == AUTO_FIT) {
|
||||
gridLayoutManager.setSpanCount(spanCount);
|
||||
} else {
|
||||
gridLayoutManager.setSpanCount(columnCount);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMultiColumnSupported() {
|
||||
return multiColumnSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of columns.
|
||||
* @param count amount of columns to use. Use {@link #AUTO_FIT}
|
||||
* to calculate the amount based on available screen width
|
||||
* and the specified column width
|
||||
*/
|
||||
public void setColumnCount(int count) {
|
||||
columnCount = count;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return columnCount;
|
||||
}
|
||||
|
||||
public void setEmptyView(View emptyView) {
|
||||
this.emptyView = emptyView;
|
||||
}
|
||||
|
||||
public View getEmptyView() {
|
||||
return emptyView;
|
||||
}
|
||||
|
||||
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
|
||||
this.onItemClickListener = onItemClickListener;
|
||||
}
|
||||
}
|
|
@ -27,19 +27,11 @@
|
|||
android:id="@+id/swipe_refresh_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<GridView
|
||||
<org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/small_padding"
|
||||
android:paddingRight="@dimen/small_padding"
|
||||
android:paddingTop="@dimen/small_padding"
|
||||
android:paddingBottom="@dimen/default_padding"
|
||||
android:clipToPadding="false"
|
||||
android:choiceMode="none"
|
||||
android:listSelector="?attr/selectableItemBackground"
|
||||
android:drawSelectorOnTop="true"
|
||||
style="@style/Widget.GridView"/>
|
||||
style="@style/GridLayoutRecyclerView"/>
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015 Synced Synapse. 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.
|
||||
-->
|
||||
|
||||
<!-- TODO: replace gridview with RecyclerViewEmptyViewSupport -->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/empty_view"/>
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/swipe_refresh_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<GridView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/small_padding"
|
||||
android:paddingRight="@dimen/small_padding"
|
||||
android:paddingTop="@dimen/small_padding"
|
||||
android:paddingBottom="@dimen/default_padding"
|
||||
android:clipToPadding="false"
|
||||
android:choiceMode="none"
|
||||
android:listSelector="?attr/selectableItemBackground"
|
||||
android:drawSelectorOnTop="true"
|
||||
style="@style/Widget.GridView"/>
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor"
|
||||
style="@style/Widget.CardView">
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground">
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
card_view:cardElevation="@dimen/default_card_elevation"
|
||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
||||
style="@style/Widget.CardView">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
-->
|
||||
<resources>
|
||||
<!-- Default spacing because cardview on lollipop doesn't add padding -->
|
||||
<dimen name="default_grid_horizontal_spacing">8dp</dimen>
|
||||
<dimen name="default_grid_vertical_spacing">8dp</dimen>
|
||||
<dimen name="default_grid_horizontal_spacing">4dp</dimen>
|
||||
<dimen name="default_grid_vertical_spacing">4dp</dimen>
|
||||
|
||||
<dimen name="default_card_margin">8dp</dimen>
|
||||
</resources>
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
<dimen name="card_corner_radius">2dp</dimen>
|
||||
<dimen name="default_card_elevation">2dp</dimen>
|
||||
<dimen name="default_card_margin">2dp</dimen>
|
||||
|
||||
<dimen name="text_size_small">12sp</dimen>
|
||||
<dimen name="text_size_medium">14sp</dimen>
|
||||
|
|
|
@ -54,6 +54,21 @@
|
|||
<item name="android:fastScrollEnabled">true</item>
|
||||
</style>
|
||||
|
||||
<style name="GridLayoutRecyclerView">
|
||||
<item name="android:clipToPadding">false</item>
|
||||
<item name="android:scrollbars">vertical</item>
|
||||
<item name="android:paddingBottom">@dimen/default_padding</item>
|
||||
<item name="android:paddingLeft">@dimen/default_card_margin</item>
|
||||
<item name="android:columnWidth">@dimen/default_grid_column_width</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.CardView">
|
||||
<item name="cardElevation">@dimen/default_card_elevation</item>
|
||||
<item name="cardBackgroundColor">?attr/appCardBackgroundColor</item>
|
||||
<item name="android:layout_marginRight">@dimen/default_card_margin</item>
|
||||
<item name="android:layout_marginTop">@dimen/default_card_margin</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.ListView">
|
||||
<item name="android:fastScrollEnabled">true</item>
|
||||
<item name="android:divider">@null</item>
|
||||
|
|
Loading…
Reference in New Issue