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:preference-v14:${supportLibVersion}"
|
||||||
implementation "com.android.support:support-v13:${supportLibVersion}"
|
implementation "com.android.support:support-v13:${supportLibVersion}"
|
||||||
implementation "com.android.support:design:${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.fasterxml.jackson.core:jackson-databind:2.5.2'
|
||||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
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.CursorLoader;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -35,8 +36,6 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Toast;
|
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.LibrarySyncService;
|
||||||
import org.xbmc.kore.service.library.SyncItem;
|
import org.xbmc.kore.service.library.SyncItem;
|
||||||
import org.xbmc.kore.service.library.SyncUtils;
|
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.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
||||||
|
|
||||||
abstract protected void onListItemClicked(View view);
|
abstract protected void onListItemClicked(View view);
|
||||||
abstract protected CursorLoader createCursorLoader();
|
abstract protected CursorLoader createCursorLoader();
|
||||||
|
abstract protected RecyclerViewCursorAdapter createCursorAdapter();
|
||||||
|
|
||||||
@TargetApi(16)
|
@TargetApi(16)
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -136,16 +137,21 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||||
return new AdapterView.OnItemClickListener() {
|
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(View view, int position) {
|
||||||
saveSearchState();
|
saveSearchState();
|
||||||
onListItemClicked(view);
|
onListItemClicked(view);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
final protected RecyclerView.Adapter createAdapter() {
|
||||||
|
return createCursorAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.abstractcursorlistfragment, menu);
|
inflater.inflate(R.menu.abstractcursorlistfragment, menu);
|
||||||
|
@ -305,7 +311,7 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
|
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
|
||||||
loaderLoading = false;
|
loaderLoading = false;
|
||||||
((CursorAdapter) getAdapter()).swapCursor(cursor);
|
((RecyclerViewCursorAdapter) getAdapter()).swapCursor(cursor);
|
||||||
if (TextUtils.isEmpty(searchFilter)) {
|
if (TextUtils.isEmpty(searchFilter)) {
|
||||||
// To prevent the empty text from appearing on the first load, set it now
|
// To prevent the empty text from appearing on the first load, set it now
|
||||||
emptyView.setText(getString(R.string.swipe_down_to_refresh));
|
emptyView.setText(getString(R.string.swipe_down_to_refresh));
|
||||||
|
@ -316,7 +322,7 @@ public abstract class AbstractCursorListFragment extends AbstractListFragment
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public void onLoaderReset(Loader<Cursor> cursorLoader) {
|
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.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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 android.widget.TextView;
|
||||||
|
|
||||||
import org.xbmc.kore.R;
|
import org.xbmc.kore.R;
|
||||||
import org.xbmc.kore.Settings;
|
import org.xbmc.kore.Settings;
|
||||||
|
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
import butterknife.Unbinder;
|
import butterknife.Unbinder;
|
||||||
|
|
||||||
public abstract class AbstractListFragment extends Fragment implements
|
public abstract class AbstractListFragment extends Fragment implements
|
||||||
SwipeRefreshLayout.OnRefreshListener {
|
SwipeRefreshLayout.OnRefreshListener {
|
||||||
private static final String TAG = LogUtils.makeLogTag(AbstractListFragment.class);
|
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;
|
private Unbinder unbinder;
|
||||||
|
|
||||||
protected @BindView(R.id.swipe_refresh_layout) SwipeRefreshLayout swipeRefreshLayout;
|
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;
|
@BindView(android.R.id.empty) TextView emptyView;
|
||||||
|
|
||||||
abstract protected AdapterView.OnItemClickListener createOnItemClickListener();
|
abstract protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener();
|
||||||
abstract protected BaseAdapter createAdapter();
|
abstract protected RecyclerViewEmptyViewSupport.Adapter createAdapter();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
@ -76,40 +70,18 @@ public abstract class AbstractListFragment extends Fragment implements
|
||||||
|
|
||||||
swipeRefreshLayout.setOnRefreshListener(this);
|
swipeRefreshLayout.setOnRefreshListener(this);
|
||||||
|
|
||||||
gridView.setEmptyView(emptyView);
|
recyclerView.setEmptyView(emptyView);
|
||||||
gridView.setOnItemClickListener(createOnItemClickListener());
|
recyclerView.setOnItemClickListener(createOnItemClickListener());
|
||||||
gridView.setAdapter(adapter);
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (PreferenceManager
|
||||||
final int listPosition = savedInstanceState.getInt(BUNDLE_SAVEDINSTANCE_LISTPOSITION);
|
.getDefaultSharedPreferences(getActivity())
|
||||||
gridView.post(new Runnable() {
|
.getBoolean(Settings.KEY_PREF_SINGLE_COLUMN,
|
||||||
@Override
|
Settings.DEFAULT_PREF_SINGLE_COLUMN)) {
|
||||||
public void run() {
|
recyclerView.setColumnCount(1);
|
||||||
gridView.setSelection(listPosition);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Listener added to be able to determine if multiple-columns is at all possible for the current grid
|
recyclerView.setAdapter(adapter);
|
||||||
//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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
@ -121,34 +93,23 @@ public abstract class AbstractListFragment extends Fragment implements
|
||||||
unbinder.unbind();
|
unbinder.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
if (gridView != null) {
|
|
||||||
outState.putInt(BUNDLE_SAVEDINSTANCE_LISTPOSITION, gridView.getFirstVisiblePosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.abstractlistfragment, menu);
|
inflater.inflate(R.menu.abstractlistfragment, menu);
|
||||||
|
|
||||||
if(gridViewUsesMultipleColumns) {
|
if(recyclerView.isMultiColumnSupported()) {
|
||||||
if (PreferenceManager
|
if (PreferenceManager
|
||||||
.getDefaultSharedPreferences(getActivity())
|
.getDefaultSharedPreferences(getActivity())
|
||||||
.getBoolean(Settings.KEY_PREF_SINGLE_COLUMN,
|
.getBoolean(Settings.KEY_PREF_SINGLE_COLUMN,
|
||||||
Settings.DEFAULT_PREF_SINGLE_COLUMN)) {
|
Settings.DEFAULT_PREF_SINGLE_COLUMN)) {
|
||||||
gridView.setNumColumns(1);
|
recyclerView.setColumnCount(1);
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
MenuItem item = menu.findItem(R.id.action_multi_single_columns);
|
MenuItem item = menu.findItem(R.id.action_multi_single_columns);
|
||||||
item.setTitle(R.string.multi_column);
|
item.setTitle(R.string.multi_column);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Default number of columns for GridView is set to AUTO_FIT.
|
//Disable menu item when mult-column is not supported
|
||||||
//When this leads to a single column it is not possible
|
|
||||||
//to switch to multiple columns. We therefore disable
|
|
||||||
//the menu item.
|
|
||||||
MenuItem item = menu.findItem(R.id.action_multi_single_columns);
|
MenuItem item = menu.findItem(R.id.action_multi_single_columns);
|
||||||
item.setTitle(R.string.multi_column);
|
item.setTitle(R.string.multi_column);
|
||||||
item.setEnabled(false);
|
item.setEnabled(false);
|
||||||
|
@ -170,14 +131,14 @@ public abstract class AbstractListFragment extends Fragment implements
|
||||||
private void toggleAmountOfColumns(MenuItem item) {
|
private void toggleAmountOfColumns(MenuItem item) {
|
||||||
SharedPreferences.Editor editor = PreferenceManager
|
SharedPreferences.Editor editor = PreferenceManager
|
||||||
.getDefaultSharedPreferences(getActivity()).edit();
|
.getDefaultSharedPreferences(getActivity()).edit();
|
||||||
if (gridView.getNumColumns() == 1) {
|
if (recyclerView.getColumnCount() == 1) {
|
||||||
editor.putBoolean(Settings.KEY_PREF_SINGLE_COLUMN, false);
|
editor.putBoolean(Settings.KEY_PREF_SINGLE_COLUMN, false);
|
||||||
item.setTitle(R.string.single_column);
|
item.setTitle(R.string.single_column);
|
||||||
gridView.setNumColumns(GridView.AUTO_FIT);
|
recyclerView.setColumnCount(RecyclerViewEmptyViewSupport.AUTO_FIT);
|
||||||
} else {
|
} else {
|
||||||
editor.putBoolean(Settings.KEY_PREF_SINGLE_COLUMN, true);
|
editor.putBoolean(Settings.KEY_PREF_SINGLE_COLUMN, true);
|
||||||
item.setTitle(R.string.multi_column);
|
item.setTitle(R.string.multi_column);
|
||||||
gridView.setNumColumns(1);
|
recyclerView.setColumnCount(1);
|
||||||
}
|
}
|
||||||
editor.apply();
|
editor.apply();
|
||||||
adapter.notifyDataSetChanged(); //force gridView to redraw
|
adapter.notifyDataSetChanged(); //force gridView to redraw
|
||||||
|
@ -187,7 +148,7 @@ public abstract class AbstractListFragment extends Fragment implements
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseAdapter getAdapter() {
|
public RecyclerView.Adapter getAdapter() {
|
||||||
return adapter;
|
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.ListType;
|
||||||
import org.xbmc.kore.jsonrpc.type.PlayerType;
|
import org.xbmc.kore.jsonrpc.type.PlayerType;
|
||||||
import org.xbmc.kore.ui.generic.NavigationDrawerFragment;
|
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.generic.VolumeControllerDialogFragmentListener;
|
||||||
|
import org.xbmc.kore.ui.sections.remote.RemoteActivity;
|
||||||
import org.xbmc.kore.ui.widgets.MediaProgressIndicator;
|
import org.xbmc.kore.ui.widgets.MediaProgressIndicator;
|
||||||
import org.xbmc.kore.ui.widgets.NowPlayingPanel;
|
import org.xbmc.kore.ui.widgets.NowPlayingPanel;
|
||||||
import org.xbmc.kore.ui.widgets.VolumeLevelIndicator;
|
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.UIUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
import org.xbmc.kore.utils.Utils;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
public abstract class BaseMediaActivity extends BaseActivity
|
public abstract class BaseMediaActivity extends BaseActivity
|
||||||
implements HostConnectionObserver.ApplicationEventsObserver,
|
implements HostConnectionObserver.ApplicationEventsObserver,
|
||||||
|
@ -141,7 +141,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
if (fragment == null) {
|
if (fragment == null) {
|
||||||
fragment = createFragment();
|
fragment = createFragment();
|
||||||
|
|
||||||
if (Utils.isLollipopAndPreOreo()) {
|
if (Utils.isLollipopOrLater()) {
|
||||||
fragment.setExitTransition(null);
|
fragment.setExitTransition(null);
|
||||||
fragment.setReenterTransition(TransitionInflater
|
fragment.setReenterTransition(TransitionInflater
|
||||||
.from(this)
|
.from(this)
|
||||||
|
@ -154,7 +154,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.isLollipopAndPreOreo()) {
|
if (Utils.isLollipopOrLater()) {
|
||||||
sharedElementTransition.setupExitTransition(this, fragment);
|
sharedElementTransition.setupExitTransition(this, fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ public abstract class BaseMediaActivity extends BaseActivity
|
||||||
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
|
||||||
|
|
||||||
// Set up transitions
|
// Set up transitions
|
||||||
if (Utils.isLollipopAndPreOreo()) {
|
if (Utils.isLollipopOrLater()) {
|
||||||
dataHolder.setPosterTransitionName(sharedImageView.getTransitionName());
|
dataHolder.setPosterTransitionName(sharedImageView.getTransitionName());
|
||||||
sharedElementTransition.setupEnterTransition(this, fragTrans, fragment, sharedImageView);
|
sharedElementTransition.setupEnterTransition(this, fragTrans, fragment, sharedImageView);
|
||||||
} else {
|
} 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;
|
package org.xbmc.kore.ui.sections.addon;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
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.jsonrpc.type.AddonType;
|
||||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||||
import org.xbmc.kore.ui.AbstractListFragment;
|
import org.xbmc.kore.ui.AbstractListFragment;
|
||||||
|
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
import org.xbmc.kore.utils.Utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -65,10 +64,10 @@ public class AddonListFragment extends AbstractListFragment {
|
||||||
private Handler callbackHandler = new Handler();
|
private Handler callbackHandler = new Handler();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||||
return new AdapterView.OnItemClickListener() {
|
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||||
@Override
|
@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
|
// Get the movie id from the tag
|
||||||
ViewHolder tag = (ViewHolder) view.getTag();
|
ViewHolder tag = (ViewHolder) view.getTag();
|
||||||
// Notify the activity
|
// Notify the activity
|
||||||
|
@ -77,10 +76,9 @@ public class AddonListFragment extends AbstractListFragment {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseAdapter createAdapter() {
|
protected RecyclerView.Adapter createAdapter() {
|
||||||
return new AddonsAdapter(getActivity(), R.layout.grid_item_addon);
|
return new AddonsAdapter(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,7 +86,7 @@ public class AddonListFragment extends AbstractListFragment {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
setHasOptionsMenu(false);
|
setHasOptionsMenu(false);
|
||||||
|
|
||||||
if (getAdapter().getCount() == 0)
|
if (getAdapter().getItemCount() == 0)
|
||||||
callGetAddonsAndSetup();
|
callGetAddonsAndSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +170,7 @@ public class AddonListFragment extends AbstractListFragment {
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
hideRefreshAnimation();
|
hideRefreshAnimation();
|
||||||
|
|
||||||
if (adapter.getCount() == 0) {
|
if (adapter.getItemCount() == 0) {
|
||||||
getEmptyView().setText(R.string.no_addons_found_refresh);
|
getEmptyView().setText(R.string.no_addons_found_refresh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,15 +188,16 @@ public class AddonListFragment extends AbstractListFragment {
|
||||||
callbackHandler);
|
callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AddonsAdapter extends ArrayAdapter<AddonType.Details> {
|
private static class AddonsAdapter extends RecyclerView.Adapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
private String author;
|
private Context context;
|
||||||
private String version;
|
|
||||||
|
|
||||||
public AddonsAdapter(Context context, int resource) {
|
private ArrayList<AddonType.Details> items = new ArrayList<>();
|
||||||
super(context, resource);
|
|
||||||
|
public AddonsAdapter(Context context) {
|
||||||
|
this.context = context;
|
||||||
this.hostManager = HostManager.getInstance(context);
|
this.hostManager = HostManager.getInstance(context);
|
||||||
|
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
|
@ -207,63 +206,96 @@ public class AddonListFragment extends AbstractListFragment {
|
||||||
Resources resources = context.getResources();
|
Resources resources = context.getResources();
|
||||||
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_width_square);
|
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_width_square);
|
||||||
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_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
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
if (convertView == null) {
|
View view = LayoutInflater.from(context)
|
||||||
convertView = LayoutInflater.from(getActivity())
|
.inflate(R.layout.grid_item_addon, parent, false);
|
||||||
.inflate(R.layout.grid_item_addon, parent, false);
|
|
||||||
|
|
||||||
// Setup View holder pattern
|
return new ViewHolder(view, context, hostManager, artWidth, artHeight);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ViewHolder viewHolder = (ViewHolder)convertView.getTag();
|
@Override
|
||||||
|
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||||
AddonType.Details addonDetails = this.getItem(position);
|
AddonType.Details addonDetails = this.getItem(position);
|
||||||
|
((ViewHolder) holder).onBind(addonDetails);
|
||||||
|
}
|
||||||
|
|
||||||
viewHolder.dataHolder.setTitle(addonDetails.name);
|
@Override
|
||||||
viewHolder.dataHolder.setDescription(addonDetails.description);
|
public int getItemCount() {
|
||||||
viewHolder.dataHolder.setUndertitle(addonDetails.summary);
|
return items.size();
|
||||||
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));
|
|
||||||
|
|
||||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
public void clear() {
|
||||||
viewHolder.detailsView.setText(addonDetails.summary);
|
items.clear();
|
||||||
|
}
|
||||||
|
|
||||||
UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager,
|
public void add(AddonType.Details item) {
|
||||||
addonDetails.thumbnail, viewHolder.dataHolder.getTitle(),
|
items.add(item);
|
||||||
viewHolder.artView, artWidth, artHeight);
|
}
|
||||||
|
|
||||||
if(Utils.isLollipopOrLater()) {
|
public AddonType.Details getItem(int position) {
|
||||||
viewHolder.artView.setTransitionName("a"+addonDetails.addonid);
|
return items.get(position);
|
||||||
}
|
|
||||||
return convertView;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
public static class ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView titleView;
|
TextView titleView;
|
||||||
TextView detailsView;
|
TextView detailsView;
|
||||||
ImageView artView;
|
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);
|
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;
|
package org.xbmc.kore.ui.sections.audio;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -25,6 +24,7 @@ import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.CursorLoader;
|
import android.support.v4.content.CursorLoader;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -33,7 +33,6 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
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.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||||
|
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
@ -162,8 +162,8 @@ public class AlbumListFragment extends AbstractCursorListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new AlbumsAdapter(getActivity());
|
return new AlbumsAdapter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -263,113 +263,119 @@ public class AlbumListFragment extends AbstractCursorListFragment {
|
||||||
int RATING = 7;
|
int RATING = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AlbumsAdapter extends CursorAdapter {
|
private static class AlbumsAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
|
private Fragment fragment;
|
||||||
|
|
||||||
public AlbumsAdapter(Context context) {
|
public AlbumsAdapter(Fragment fragment) {
|
||||||
super(context, null, 0);
|
this.hostManager = HostManager.getInstance(fragment.getContext());
|
||||||
this.hostManager = HostManager.getInstance(context);
|
this.fragment = fragment;
|
||||||
|
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
// Use the same dimensions as in the details fragment, so that it hits Picasso's cache when
|
// 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
|
// 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);
|
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_width_square);
|
||||||
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
View view = LayoutInflater.from(fragment.getContext())
|
||||||
.inflate(R.layout.grid_item_album, parent, false);
|
.inflate(R.layout.grid_item_album, parent, false);
|
||||||
|
|
||||||
// Setup View holder pattern
|
return new ViewHolder(view, fragment.getContext(), hostManager, artWidth, artHeight,
|
||||||
ViewHolder viewHolder = new ViewHolder();
|
albumlistItemMenuClickListener);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
private View.OnClickListener albumlistItemMenuClickListener = new View.OnClickListener() {
|
||||||
@TargetApi(21)
|
@Override
|
||||||
@Override
|
public void onClick(final View v) {
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
|
||||||
|
|
||||||
viewHolder.dataHolder.setId(cursor.getInt(AlbumListQuery.ALBUMID));
|
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||||
viewHolder.dataHolder.setTitle(cursor.getString(AlbumListQuery.TITLE));
|
playListItem.albumid = viewHolder.dataHolder.getId();
|
||||||
viewHolder.dataHolder.setUndertitle(cursor.getString(AlbumListQuery.DISPLAYARTIST));
|
|
||||||
|
|
||||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
final PopupMenu popupMenu = new PopupMenu(fragment.getContext(), v);
|
||||||
viewHolder.artistView.setText(viewHolder.dataHolder.getUnderTitle());
|
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||||
int year = cursor.getInt(AlbumListQuery.YEAR);
|
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
String genres = cursor.getString(AlbumListQuery.GENRE);
|
@Override
|
||||||
String desc = (genres != null) ?
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
((year > 0) ? genres + " | " + year : genres) :
|
switch (item.getItemId()) {
|
||||||
String.valueOf(year);
|
case R.id.action_play:
|
||||||
viewHolder.dataHolder.setDescription(desc);
|
MediaPlayerUtils.play(fragment, playListItem);
|
||||||
viewHolder.genresView.setText(desc);
|
return true;
|
||||||
|
case R.id.action_queue:
|
||||||
viewHolder.dataHolder.setPosterUrl(cursor.getString(AlbumListQuery.THUMBNAIL));
|
MediaPlayerUtils.queue(fragment, playListItem, PlaylistType.GetPlaylistsReturnType.AUDIO);
|
||||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
return true;
|
||||||
viewHolder.dataHolder.getPosterUrl(),
|
}
|
||||||
viewHolder.dataHolder.getTitle(),
|
return false;
|
||||||
viewHolder.artView, artWidth, artHeight);
|
}
|
||||||
|
});
|
||||||
// For the popupmenu
|
popupMenu.show();
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
public static class ViewHolder {
|
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||||
TextView titleView;
|
TextView titleView;
|
||||||
TextView artistView;
|
TextView artistView;
|
||||||
TextView genresView;
|
TextView genresView;
|
||||||
ImageView artView;
|
ImageView artView;
|
||||||
|
HostManager hostManager;
|
||||||
|
int artWidth;
|
||||||
|
int artHeight;
|
||||||
|
Context context;
|
||||||
|
|
||||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||||
}
|
|
||||||
|
|
||||||
private View.OnClickListener albumlistItemMenuClickListener = new View.OnClickListener() {
|
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight,
|
||||||
@Override
|
View.OnClickListener contextMenuClickListener) {
|
||||||
public void onClick(final View v) {
|
super(itemView);
|
||||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
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();
|
// For the popupmenu
|
||||||
playListItem.albumid = viewHolder.dataHolder.getId();
|
ImageView contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||||
|
contextMenu.setTag(this);
|
||||||
final PopupMenu popupMenu = new PopupMenu(getActivity(), v);
|
contextMenu.setOnClickListener(contextMenuClickListener);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
};
|
@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;
|
package org.xbmc.kore.ui.sections.audio;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.BaseColumns;
|
import android.provider.BaseColumns;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.CursorLoader;
|
import android.support.v4.content.CursorLoader;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
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.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||||
|
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
@ -72,8 +72,8 @@ public class ArtistListFragment extends AbstractCursorListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new ArtistsAdapter(getActivity());
|
return new ArtistsAdapter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -135,105 +135,108 @@ public class ArtistListFragment extends AbstractCursorListFragment {
|
||||||
int FANART = 6;
|
int FANART = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArtistsAdapter extends CursorAdapter {
|
private static class ArtistsAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
|
Fragment fragment;
|
||||||
|
|
||||||
public ArtistsAdapter(Context context) {
|
public ArtistsAdapter(Fragment fragment) {
|
||||||
super(context, null, 0);
|
this.fragment = fragment;
|
||||||
this.hostManager = HostManager.getInstance(context);
|
this.hostManager = HostManager.getInstance(fragment.getContext());
|
||||||
|
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
Resources resources = context.getResources();
|
Resources resources = fragment.getContext().getResources();
|
||||||
artWidth = (int)(resources.getDimension(R.dimen.detail_poster_width_square));
|
artWidth = (int)(resources.getDimension(R.dimen.detail_poster_width_square));
|
||||||
artHeight = (int)(resources.getDimension(R.dimen.detail_poster_height_square));
|
artHeight = (int)(resources.getDimension(R.dimen.detail_poster_height_square));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
View view = LayoutInflater.from(fragment.getContext())
|
||||||
.inflate(R.layout.grid_item_artist, parent, false);
|
.inflate(R.layout.grid_item_artist, parent, false);
|
||||||
|
|
||||||
// Setup View holder pattern
|
return new ViewHolder(view, fragment.getContext(), hostManager, artWidth, artHeight, artistlistItemMenuClickListener);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
private View.OnClickListener artistlistItemMenuClickListener = new View.OnClickListener() {
|
||||||
@TargetApi(21)
|
@Override
|
||||||
@Override
|
public void onClick(final View v) {
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
||||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
|
||||||
|
|
||||||
// Save the movie id
|
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||||
viewHolder.dataHolder.setId(cursor.getInt(ArtistListQuery.ARTISTID));
|
playListItem.artistid = viewHolder.dataHolder.getId();
|
||||||
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));
|
|
||||||
|
|
||||||
viewHolder.nameView.setText(cursor.getString(ArtistListQuery.ARTIST));
|
final PopupMenu popupMenu = new PopupMenu(fragment.getContext(), v);
|
||||||
viewHolder.genresView.setText(cursor.getString(ArtistListQuery.GENRE));
|
popupMenu.getMenuInflater().inflate(R.menu.musiclist_item, popupMenu.getMenu());
|
||||||
viewHolder.dataHolder.setPosterUrl(cursor.getString(ArtistListQuery.THUMBNAIL));
|
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
viewHolder.dataHolder.getPosterUrl(), viewHolder.dataHolder.getTitle(),
|
switch (item.getItemId()) {
|
||||||
viewHolder.artView, artWidth, artHeight);
|
case R.id.action_play:
|
||||||
|
MediaPlayerUtils.play(fragment, playListItem);
|
||||||
viewHolder.contextMenu.setTag(viewHolder);
|
return true;
|
||||||
viewHolder.contextMenu.setOnClickListener(artistlistItemMenuClickListener);
|
case R.id.action_queue:
|
||||||
|
MediaPlayerUtils.queue(fragment, playListItem, PlaylistType.GetPlaylistsReturnType.AUDIO);
|
||||||
if (Utils.isLollipopOrLater()) {
|
return true;
|
||||||
viewHolder.artView.setTransitionName("ar"+viewHolder.dataHolder.getId());
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popupMenu.show();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
public static class ViewHolder {
|
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||||
TextView nameView;
|
TextView nameView;
|
||||||
TextView genresView;
|
TextView genresView;
|
||||||
ImageView artView;
|
ImageView artView;
|
||||||
ImageView contextMenu;
|
HostManager hostManager;
|
||||||
|
int artWidth;
|
||||||
|
int artHeight;
|
||||||
|
Context context;
|
||||||
|
|
||||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
||||||
}
|
|
||||||
|
|
||||||
private View.OnClickListener artistlistItemMenuClickListener = new View.OnClickListener() {
|
ViewHolder(View itemView, Context context, HostManager hostManager, int artWidth, int artHeight,
|
||||||
@Override
|
View.OnClickListener contextMenuClickListener) {
|
||||||
public void onClick(final View v) {
|
super(itemView);
|
||||||
final ViewHolder viewHolder = (ViewHolder)v.getTag();
|
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();
|
ImageView contextMenu = itemView.findViewById(R.id.list_context_menu);
|
||||||
playListItem.artistid = viewHolder.dataHolder.getId();
|
contextMenu.setTag(this);
|
||||||
|
contextMenu.setOnClickListener(contextMenuClickListener);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
@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.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
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.provider.MediaContract;
|
||||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||||
|
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
@ -68,7 +68,7 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new AudioGenresAdapter(getActivity());
|
return new AudioGenresAdapter(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,13 +125,12 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
||||||
final int THUMBNAIL = 3;
|
final int THUMBNAIL = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AudioGenresAdapter extends CursorAdapter {
|
private class AudioGenresAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
|
|
||||||
public AudioGenresAdapter(Context context) {
|
public AudioGenresAdapter(Context context) {
|
||||||
super(context, null, 0);
|
|
||||||
this.hostManager = HostManager.getInstance(context);
|
this.hostManager = HostManager.getInstance(context);
|
||||||
|
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
|
@ -142,52 +141,56 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
||||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
View view = LayoutInflater.from(getContext())
|
||||||
.inflate(R.layout.grid_item_audio_genre, parent, false);
|
.inflate(R.layout.grid_item_audio_genre, parent, false);
|
||||||
|
|
||||||
// Setup View holder pattern
|
return new ViewHolder(view, getContext(), hostManager, artWidth, artHeight, genrelistItemMenuClickListener);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
private static class ViewHolder {
|
private static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||||
TextView titleView;
|
TextView titleView;
|
||||||
ImageView artView;
|
ImageView artView;
|
||||||
|
HostManager hostManager;
|
||||||
|
int artWidth;
|
||||||
|
int artHeight;
|
||||||
|
Context context;
|
||||||
int genreId;
|
int genreId;
|
||||||
String genreTitle;
|
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() {
|
private View.OnClickListener genrelistItemMenuClickListener = new View.OnClickListener() {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.xbmc.kore.ui.sections.audio;
|
package org.xbmc.kore.ui.sections.audio;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
@ -27,7 +26,6 @@ import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
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.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||||
|
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
import org.xbmc.kore.utils.Utils;
|
||||||
|
@ -68,7 +67,7 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new MusicVideosAdapter(getActivity());
|
return new MusicVideosAdapter(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,13 +136,15 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
||||||
int PLOT = 9;
|
int PLOT = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MusicVideosAdapter extends CursorAdapter {
|
private static class MusicVideosAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
public MusicVideosAdapter(Context context) {
|
public MusicVideosAdapter(Context context) {
|
||||||
super(context, null, 0);
|
this.context = context;
|
||||||
|
|
||||||
this.hostManager = HostManager.getInstance(context);
|
this.hostManager = HostManager.getInstance(context);
|
||||||
|
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
|
@ -152,38 +153,50 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
||||||
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
artWidth = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
View view = LayoutInflater.from(context)
|
||||||
.inflate(R.layout.grid_item_music_video, parent, false);
|
.inflate(R.layout.grid_item_music_video, parent, false);
|
||||||
|
return new ViewHolder(view, context, hostManager, artWidth, artHeight);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** {@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
|
@Override
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
public void bindView(Cursor cursor) {
|
||||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
dataHolder.setId(cursor.getInt(MusicVideosListQuery.MUSICVIDEOID));
|
||||||
|
dataHolder.setTitle(cursor.getString(MusicVideosListQuery.TITLE));
|
||||||
|
|
||||||
// Save the movie id
|
titleView.setText(dataHolder.getTitle());
|
||||||
viewHolder.dataHolder.setId(cursor.getInt(MusicVideosListQuery.MUSICVIDEOID));
|
|
||||||
viewHolder.dataHolder.setTitle(cursor.getString(MusicVideosListQuery.TITLE));
|
|
||||||
|
|
||||||
viewHolder.titleView.setText(viewHolder.dataHolder.getTitle());
|
|
||||||
String artistAlbum = cursor.getString(MusicVideosListQuery.ARTIST) + " | " +
|
String artistAlbum = cursor.getString(MusicVideosListQuery.ARTIST) + " | " +
|
||||||
cursor.getString(MusicVideosListQuery.ALBUM);
|
cursor.getString(MusicVideosListQuery.ALBUM);
|
||||||
viewHolder.artistAlbumView.setText(artistAlbum);
|
artistAlbumView.setText(artistAlbum);
|
||||||
viewHolder.dataHolder.setUndertitle(artistAlbum);
|
dataHolder.setUndertitle(artistAlbum);
|
||||||
|
|
||||||
int runtime = cursor.getInt(MusicVideosListQuery.RUNTIME);
|
int runtime = cursor.getInt(MusicVideosListQuery.RUNTIME);
|
||||||
String genres = cursor.getString(MusicVideosListQuery.GENRES);
|
String genres = cursor.getString(MusicVideosListQuery.GENRES);
|
||||||
|
@ -191,30 +204,17 @@ public class MusicVideoListFragment extends AbstractCursorListFragment {
|
||||||
runtime > 0 ?
|
runtime > 0 ?
|
||||||
UIUtils.formatTime(runtime) + " | " + genres :
|
UIUtils.formatTime(runtime) + " | " + genres :
|
||||||
genres;
|
genres;
|
||||||
viewHolder.durationGenresView.setText(durationGenres);
|
durationGenresView.setText(durationGenres);
|
||||||
viewHolder.dataHolder.setDetails(durationGenres);
|
dataHolder.setDetails(durationGenres);
|
||||||
|
|
||||||
String posterUrl = cursor.getString(MusicVideosListQuery.THUMBNAIL);
|
String posterUrl = cursor.getString(MusicVideosListQuery.THUMBNAIL);
|
||||||
viewHolder.dataHolder.setPosterUrl(posterUrl);
|
dataHolder.setPosterUrl(posterUrl);
|
||||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager, posterUrl
|
UIUtils.loadImageWithCharacterAvatar(context, hostManager, posterUrl
|
||||||
, viewHolder.dataHolder.getTitle(),
|
, dataHolder.getTitle(), artView, artWidth, artHeight);
|
||||||
viewHolder.artView, artWidth, artHeight);
|
|
||||||
|
|
||||||
if(Utils.isLollipopOrLater()) {
|
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.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -48,6 +47,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
||||||
import org.xbmc.kore.provider.MediaProvider;
|
import org.xbmc.kore.provider.MediaProvider;
|
||||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||||
|
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||||
import org.xbmc.kore.utils.FileDownloadHelper;
|
import org.xbmc.kore.utils.FileDownloadHelper;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||||
|
@ -67,7 +67,8 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
||||||
|
|
||||||
private int artistId = -1;
|
private int artistId = -1;
|
||||||
private int albumId = -1;
|
private int albumId = -1;
|
||||||
private String albumTitle = "";
|
private static String albumTitle = "";
|
||||||
|
|
||||||
|
|
||||||
private Handler callbackHandler = new Handler();
|
private Handler callbackHandler = new Handler();
|
||||||
|
|
||||||
|
@ -96,11 +97,21 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
||||||
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_MUSIC; }
|
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_MUSIC; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
if (albumId != -1 ) {
|
if (albumId != -1 ) {
|
||||||
return new AlbumSongsAdapter(getActivity());
|
return new AlbumSongsAdapter(getContext(), new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
showPopupMenu(v);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} 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;
|
int DISC = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SongsAdapter extends CursorAdapter {
|
private static class SongsAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
|
private Context context;
|
||||||
|
private View.OnClickListener contextMenuClickListener;
|
||||||
|
|
||||||
public SongsAdapter(Context context) {
|
public SongsAdapter(Context context, View.OnClickListener contextMenuClickListener) {
|
||||||
super(context, null, 0);
|
|
||||||
this.hostManager = HostManager.getInstance(context);
|
this.hostManager = HostManager.getInstance(context);
|
||||||
|
this.context = context;
|
||||||
|
this.contextMenuClickListener = contextMenuClickListener;
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
// Use the same dimensions as in the details fragment, so that it hits Picasso's cache when
|
// 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
|
// 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);
|
artHeight = resources.getDimensionPixelOffset(R.dimen.detail_poster_height_square);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(context)
|
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
|
return new SongViewHolder(view, context, hostManager, artWidth, artHeight,
|
||||||
ViewHolder viewHolder = new ViewHolder();
|
contextMenuClickListener);
|
||||||
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);
|
|
||||||
|
|
||||||
view.setTag(viewHolder);
|
private static class AlbumSongsAdapter extends RecyclerViewCursorAdapter {
|
||||||
return view;
|
private Context context;
|
||||||
|
private View.OnClickListener contextMenuClickListener;
|
||||||
|
|
||||||
|
public AlbumSongsAdapter(Context context, View.OnClickListener contextMenuClickListener) {
|
||||||
|
this.context = context;
|
||||||
|
this.contextMenuClickListener = contextMenuClickListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
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);
|
String title = cursor.getString(SongsListQuery.TITLE);
|
||||||
|
titleTextView.setText(title);
|
||||||
|
|
||||||
viewHolder.title.setText(title);
|
artistTextView.setText(cursor.getString(SongsListQuery.SONGDISPLAYARTIST));
|
||||||
|
|
||||||
String artist = cursor.getString(SongsListQuery.SONGDISPLAYARTIST);
|
|
||||||
viewHolder.artist.setText(artist);
|
|
||||||
|
|
||||||
String albumTitle = cursor.getString(SongsListQuery.ALBUMTITLE);
|
String albumTitle = cursor.getString(SongsListQuery.ALBUMTITLE);
|
||||||
int year = cursor.getInt(SongsListQuery.YEAR);
|
int year = cursor.getInt(SongsListQuery.YEAR);
|
||||||
if (year > 0) {
|
if (year > 0) {
|
||||||
setDetails(viewHolder.details,
|
setDetails(detailsTextView,
|
||||||
albumTitle,
|
albumTitle,
|
||||||
String.valueOf(year),
|
String.valueOf(year),
|
||||||
cursor.getString(SongsListQuery.GENRE));
|
cursor.getString(SongsListQuery.GENRE));
|
||||||
} else {
|
} else {
|
||||||
setDetails(viewHolder.details,
|
setDetails(detailsTextView,
|
||||||
albumTitle,
|
albumTitle,
|
||||||
cursor.getString(SongsListQuery.GENRE));
|
cursor.getString(SongsListQuery.GENRE));
|
||||||
}
|
}
|
||||||
|
@ -298,101 +368,60 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
||||||
String thumbnail = cursor.getString(SongsListQuery.THUMBNAIL);
|
String thumbnail = cursor.getString(SongsListQuery.THUMBNAIL);
|
||||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||||
thumbnail, title,
|
thumbnail, title,
|
||||||
viewHolder.art, artWidth, artHeight);
|
art, artWidth, artHeight);
|
||||||
|
}
|
||||||
|
|
||||||
viewHolder.songInfo.artist = artist;
|
private void setDetails(TextView textView, String... elements) {
|
||||||
viewHolder.songInfo.album = albumTitle;
|
if ((elements == null) || (elements.length < 1)) {
|
||||||
viewHolder.songInfo.songId = cursor.getInt(SongsListQuery.SONGID);
|
return;
|
||||||
viewHolder.songInfo.title = cursor.getString(SongsListQuery.TITLE);
|
}
|
||||||
viewHolder.songInfo.fileName = cursor.getString(SongsListQuery.FILE);
|
|
||||||
viewHolder.songInfo.track = cursor.getInt(SongsListQuery.TRACK);
|
|
||||||
|
|
||||||
// For the popupmenu
|
ArrayList<String> details = new ArrayList<>();
|
||||||
viewHolder.contextMenu.setTag(viewHolder);
|
for (int i = 0; i < elements.length; i++) {
|
||||||
viewHolder.contextMenu.setOnClickListener(new View.OnClickListener() {
|
if (!TextUtils.isEmpty(elements[i]))
|
||||||
@Override
|
details.add(elements[i]);
|
||||||
public void onClick(final View v) {
|
}
|
||||||
showPopupMenu(v);
|
|
||||||
}
|
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) {
|
AlbumViewHolder(View itemView, View.OnClickListener contextMenuClickListener) {
|
||||||
super(context, null, 0);
|
super(itemView, contextMenuClickListener);
|
||||||
|
trackNumberTextView = itemView.findViewById(R.id.track_number);
|
||||||
|
titleTextView = itemView.findViewById(R.id.song_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
|
public void bindView(Cursor cursor) {
|
||||||
View view = LayoutInflater.from(context)
|
super.bindView(cursor);
|
||||||
.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();
|
|
||||||
|
|
||||||
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);
|
String artist = cursor.getString(AlbumSongsListQuery.ARTIST);
|
||||||
|
|
||||||
ViewHolder vh = (ViewHolder) view.getTag();
|
titleTextView.setText(cursor.getString(AlbumSongsListQuery.TITLE));
|
||||||
|
|
||||||
vh.title.setText(cursor.getString(AlbumSongsListQuery.TITLE));
|
songInfo.artist = artist;
|
||||||
|
songInfo.album = albumTitle;
|
||||||
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));
|
|
||||||
|
|
||||||
String duration = UIUtils.formatTime(cursor.getInt(AlbumSongsListQuery.DURATION));
|
String duration = UIUtils.formatTime(cursor.getInt(AlbumSongsListQuery.DURATION));
|
||||||
String detailsText = TextUtils.isEmpty(artist) ? duration : duration + " | " + artist;
|
String detailsText = TextUtils.isEmpty(artist) ? duration : duration + " | " + artist;
|
||||||
vh.details.setText(detailsText);
|
detailsTextView.setText(detailsText);
|
||||||
|
|
||||||
vh.contextMenu.setTag(vh);
|
|
||||||
vh.contextMenu.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(final View v) {
|
|
||||||
showPopupMenu(v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) {
|
private void showPopupMenu(View v) {
|
||||||
final ViewHolder viewHolder = (ViewHolder) v.getTag();
|
final ViewHolder viewHolder = (ViewHolder) v.getTag();
|
||||||
|
|
||||||
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
final PlaylistType.Item playListItem = new PlaylistType.Item();
|
||||||
playListItem.songid = viewHolder.songInfo.songId;
|
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.getMenuInflater().inflate(R.menu.song_item, popupMenu.getMenu());
|
||||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -407,9 +436,9 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
||||||
case R.id.download:
|
case R.id.download:
|
||||||
ArrayList<FileDownloadHelper.SongInfo> songInfoList = new ArrayList<>();
|
ArrayList<FileDownloadHelper.SongInfo> songInfoList = new ArrayList<>();
|
||||||
songInfoList.add(viewHolder.songInfo);
|
songInfoList.add(viewHolder.songInfo);
|
||||||
UIUtils.downloadSongs(getActivity(),
|
UIUtils.downloadSongs(getContext(),
|
||||||
songInfoList,
|
songInfoList,
|
||||||
HostManager.getInstance(getActivity()).getHostInfo(),
|
HostManager.getInstance(getContext()).getHostInfo(),
|
||||||
callbackHandler);
|
callbackHandler);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -417,19 +446,4 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
||||||
});
|
});
|
||||||
popupMenu.show();
|
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.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
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.FavouriteType;
|
||||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||||
import org.xbmc.kore.ui.AbstractListFragment;
|
import org.xbmc.kore.ui.AbstractListFragment;
|
||||||
|
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class FavouritesListFragment extends AbstractListFragment implements SwipeRefreshLayout.OnRefreshListener {
|
public class FavouritesListFragment extends AbstractListFragment implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
private static final String TAG = "FavouritesListFragment";
|
private static final String TAG = "FavouritesListFragment";
|
||||||
|
|
||||||
|
@ -63,7 +61,7 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||||
final ApiCallback<String> genericApiCallback = new ApiCallback<String>() {
|
final ApiCallback<String> genericApiCallback = new ApiCallback<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(String result) {
|
public void onSuccess(String result) {
|
||||||
|
@ -75,9 +73,9 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
||||||
Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return new AdapterView.OnItemClickListener() {
|
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||||
@Override
|
@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 FavouritesAdapter favouritesAdapter = (FavouritesAdapter) getAdapter();
|
||||||
final HostManager hostManager = HostManager.getInstance(getActivity());
|
final HostManager hostManager = HostManager.getInstance(getActivity());
|
||||||
|
|
||||||
|
@ -105,7 +103,7 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseAdapter createAdapter() {
|
protected RecyclerView.Adapter createAdapter() {
|
||||||
return new FavouritesAdapter(getActivity(), HostManager.getInstance(getActivity()));
|
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
|
// To prevent the empty text from appearing on the first load, set it now
|
||||||
getEmptyView().setText(getString(R.string.no_channels_found_refresh));
|
getEmptyView().setText(getString(R.string.no_channels_found_refresh));
|
||||||
setupFavouritesList(result.items);
|
((FavouritesAdapter) getAdapter()).setFavouriteItems(result.items);
|
||||||
hideRefreshAnimation();
|
hideRefreshAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,25 +141,15 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
||||||
}, callbackHandler);
|
}, callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static class FavouritesAdapter extends RecyclerView.Adapter {
|
||||||
* 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 final HostManager hostManager;
|
private final HostManager hostManager;
|
||||||
private final int artWidth, artHeight;
|
private final int artWidth, artHeight;
|
||||||
|
private Context context;
|
||||||
|
private ArrayList<FavouriteType.DetailsFavourite> favouriteItems = new ArrayList<>();
|
||||||
|
|
||||||
FavouritesAdapter(@NonNull Context context, HostManager hostManager) {
|
FavouritesAdapter(@NonNull Context context, HostManager hostManager) {
|
||||||
super(context, R.layout.grid_item_channel);
|
this.context = context;
|
||||||
this.hostManager = hostManager;
|
this.hostManager = hostManager;
|
||||||
Resources resources = context.getResources();
|
Resources resources = context.getResources();
|
||||||
artWidth = (int) (resources.getDimension(R.dimen.channellist_art_width) /
|
artWidth = (int) (resources.getDimension(R.dimen.channellist_art_width) /
|
||||||
|
@ -170,23 +158,59 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
||||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
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
|
@Override
|
||||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
if (convertView == null) {
|
View view = LayoutInflater.from(context).inflate(R.layout.grid_item_channel,
|
||||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item_channel,
|
parent, false);
|
||||||
parent, false);
|
return new ViewHolder(view, context, hostManager, artWidth, artHeight);
|
||||||
final FavouriteItemViewHolder vh = new FavouriteItemViewHolder(convertView);
|
}
|
||||||
convertView.setTag(vh);
|
|
||||||
}
|
|
||||||
|
|
||||||
final FavouriteItemViewHolder vh = (FavouriteItemViewHolder) convertView.getTag();
|
@Override
|
||||||
final FavouriteType.DetailsFavourite favouriteDetail = getItem(position);
|
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||||
|
((ViewHolder) holder).bindView(favouriteItems.get(position));
|
||||||
|
}
|
||||||
|
|
||||||
// We don't need the context menu here.
|
@Override
|
||||||
vh.contextMenu.setVisibility(View.GONE);
|
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;
|
@StringRes final int typeRes;
|
||||||
switch (favouriteDetail.type) {
|
switch (favouriteDetail.type) {
|
||||||
|
@ -202,27 +226,11 @@ public class FavouritesListFragment extends AbstractListFragment implements Swip
|
||||||
default:
|
default:
|
||||||
typeRes = R.string.unknown;
|
typeRes = R.string.unknown;
|
||||||
}
|
}
|
||||||
vh.detailView.setText(typeRes);
|
detailView.setText(typeRes);
|
||||||
|
|
||||||
UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager,
|
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||||
favouriteDetail.thumbnail, favouriteDetail.title,
|
favouriteDetail.thumbnail, favouriteDetail.title,
|
||||||
vh.artView, artWidth, artHeight);
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,12 @@ import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ListAdapter;
|
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
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.PlayerType;
|
||||||
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
import org.xbmc.kore.jsonrpc.type.PlaylistType;
|
||||||
import org.xbmc.kore.ui.AbstractListFragment;
|
import org.xbmc.kore.ui.AbstractListFragment;
|
||||||
|
import org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
import org.xbmc.kore.utils.Utils;
|
||||||
|
@ -112,17 +111,17 @@ public class MediaFileListFragment extends AbstractListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AdapterView.OnItemClickListener createOnItemClickListener() {
|
protected RecyclerViewEmptyViewSupport.OnItemClickListener createOnItemClickListener() {
|
||||||
return new AdapterView.OnItemClickListener() {
|
return new RecyclerViewEmptyViewSupport.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(View view, int position) {
|
||||||
handleFileSelect(((MediaFileListAdapter) getAdapter()).getItem(position));
|
handleFileSelect(((MediaFileListAdapter) getAdapter()).getItem(position));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BaseAdapter createAdapter() {
|
protected RecyclerView.Adapter createAdapter() {
|
||||||
return new MediaFileListAdapter(getActivity(), R.layout.grid_item_file);
|
return new MediaFileListAdapter(getActivity(), R.layout.grid_item_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +210,7 @@ public class MediaFileListFragment extends AbstractListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean atRootDirectory() {
|
public boolean atRootDirectory() {
|
||||||
if (getAdapter().getCount() == 0)
|
if (getAdapter().getItemCount() == 0)
|
||||||
return true;
|
return true;
|
||||||
FileLocation fl = ((MediaFileListAdapter) getAdapter()).getItem(0);
|
FileLocation fl = ((MediaFileListAdapter) getAdapter()).getItem(0);
|
||||||
if (fl == null)
|
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;
|
Context ctx;
|
||||||
int resource;
|
int resource;
|
||||||
List<FileLocation> fileLocationItems = null;
|
List<FileLocation> fileLocationItems;
|
||||||
|
|
||||||
int artWidth;
|
int artWidth;
|
||||||
int artHeight;
|
int artHeight;
|
||||||
|
@ -552,7 +551,7 @@ public class MediaFileListFragment extends AbstractListFragment {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public MediaFileListAdapter(Context context, int resource) {
|
MediaFileListAdapter(Context context, int resource) {
|
||||||
super();
|
super();
|
||||||
this.ctx = context;
|
this.ctx = context;
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
|
@ -580,20 +579,10 @@ public class MediaFileListFragment extends AbstractListFragment {
|
||||||
|
|
||||||
public List<FileLocation> getFileItemList() {
|
public List<FileLocation> getFileItemList() {
|
||||||
if (fileLocationItems == null)
|
if (fileLocationItems == null)
|
||||||
return new ArrayList<FileLocation>();
|
return new ArrayList<>();
|
||||||
return new ArrayList<FileLocation>(fileLocationItems);
|
return new ArrayList<>(fileLocationItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
if (fileLocationItems == null) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return fileLocationItems.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileLocation getItem(int position) {
|
public FileLocation getItem(int position) {
|
||||||
if (fileLocationItems == null) {
|
if (fileLocationItems == null) {
|
||||||
return 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
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getViewTypeCount () {
|
public int getItemCount() {
|
||||||
return 1;
|
if (fileLocationItems == null) {
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
/** {@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);
|
|
||||||
} else {
|
} else {
|
||||||
viewHolder.contextMenu.setVisibility(View.VISIBLE);
|
return fileLocationItems.size();
|
||||||
viewHolder.contextMenu.setTag(position);
|
|
||||||
viewHolder.contextMenu.setOnClickListener(itemMenuClickListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertView;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
private static class ViewHolder {
|
private static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
ImageView art;
|
ImageView art;
|
||||||
TextView title;
|
TextView title;
|
||||||
TextView details;
|
TextView details;
|
||||||
TextView sizeDuration;
|
TextView sizeDuration;
|
||||||
ImageView contextMenu;
|
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 {
|
public static class FileLocation implements Parcelable {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.xbmc.kore.ui.sections.video;
|
package org.xbmc.kore.ui.sections.video;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -33,7 +32,6 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -45,7 +43,8 @@ import org.xbmc.kore.provider.MediaContract;
|
||||||
import org.xbmc.kore.provider.MediaDatabase;
|
import org.xbmc.kore.provider.MediaDatabase;
|
||||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
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.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
import org.xbmc.kore.utils.Utils;
|
||||||
|
@ -63,7 +62,7 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
||||||
// Activity listener
|
// Activity listener
|
||||||
private OnMovieSelectedListener listenerActivity;
|
private OnMovieSelectedListener listenerActivity;
|
||||||
|
|
||||||
private boolean showWatchedStatus;
|
private static boolean showWatchedStatus;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_MOVIES; }
|
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_MOVIES; }
|
||||||
|
@ -77,7 +76,7 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new MoviesAdapter(getActivity());
|
return new MoviesAdapter(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,15 +309,13 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
||||||
int PLAYCOUNT = 9;
|
int PLAYCOUNT = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MoviesAdapter extends CursorAdapter {
|
private class MoviesAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
private int themeAccentColor;
|
private int themeAccentColor;
|
||||||
|
|
||||||
public MoviesAdapter(Context context) {
|
MoviesAdapter(Context context) {
|
||||||
super(context, null, 0);
|
|
||||||
|
|
||||||
// Get the default accent color
|
// Get the default accent color
|
||||||
Resources.Theme theme = context.getTheme();
|
Resources.Theme theme = context.getTheme();
|
||||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||||
|
@ -340,83 +337,90 @@ public class MovieListFragment extends AbstractCursorListFragment {
|
||||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
final View view = LayoutInflater.from(getContext())
|
||||||
.inflate(R.layout.grid_item_movie, parent, false);
|
.inflate(R.layout.grid_item_movie, parent, false);
|
||||||
|
|
||||||
// Setup View holder pattern
|
return new ViewHolder(view, getContext(), themeAccentColor, hostManager, artWidth, artHeight);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
public static class ViewHolder {
|
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||||
TextView titleView;
|
TextView titleView;
|
||||||
TextView detailsView;
|
TextView detailsView;
|
||||||
TextView durationView;
|
TextView durationView;
|
||||||
ImageView checkmarkView;
|
ImageView checkmarkView;
|
||||||
ImageView artView;
|
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 java.util.List;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
import butterknife.Unbinder;
|
import butterknife.Unbinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +96,7 @@ public class PVRChannelsListFragment extends Fragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
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);
|
unbinder = ButterKnife.bind(this, root);
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
|
|
|
@ -42,8 +42,8 @@ import org.xbmc.kore.utils.UIUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
import butterknife.Unbinder;
|
import butterknife.Unbinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,7 +75,7 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
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);
|
unbinder = ButterKnife.bind(this, root);
|
||||||
|
|
||||||
hostManager = HostManager.getInstance(getActivity());
|
hostManager = HostManager.getInstance(getActivity());
|
||||||
|
|
|
@ -33,7 +33,6 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
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.provider.MediaContract;
|
||||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
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.LogUtils;
|
||||||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
@ -114,9 +114,8 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
||||||
listenerActivity.onEpisodeSelected(tvshowId, tag);
|
listenerActivity.onEpisodeSelected(tvshowId, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new SeasonsEpisodesAdapter(getActivity());
|
return new SeasonsEpisodesAdapter(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +136,6 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
||||||
EpisodesListQuery.PROJECTION, selection.toString(), null, EpisodesListQuery.SORT);
|
EpisodesListQuery.PROJECTION, selection.toString(), null, EpisodesListQuery.SORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(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 int themeAccentColor;
|
||||||
|
private HostManager hostManager;
|
||||||
|
private int artWidth;
|
||||||
|
private int artHeight;
|
||||||
|
|
||||||
public SeasonsEpisodesAdapter(Context context) {
|
SeasonsEpisodesAdapter(Context context) {
|
||||||
super(context, null, 0);
|
|
||||||
|
|
||||||
// Get the default accent color
|
// Get the default accent color
|
||||||
Resources.Theme theme = context.getTheme();
|
Resources.Theme theme = context.getTheme();
|
||||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||||
R.attr.colorAccent
|
R.attr.colorAccent
|
||||||
});
|
});
|
||||||
|
|
||||||
themeAccentColor = styledAttributes.getColor(styledAttributes.getIndex(0), getResources().getColor(R.color.accent_default));
|
themeAccentColor = styledAttributes.getColor(styledAttributes.getIndex(0), getResources().getColor(R.color.accent_default));
|
||||||
styledAttributes.recycle();
|
styledAttributes.recycle();
|
||||||
|
|
||||||
this.hostManager = HostManager.getInstance(context);
|
hostManager = HostManager.getInstance(context);
|
||||||
|
|
||||||
// Get the art dimensions
|
// Get the art dimensions
|
||||||
Resources resources = context.getResources();
|
Resources resources = context.getResources();
|
||||||
|
@ -246,77 +242,84 @@ public class TVShowEpisodeListFragment extends AbstractCursorListFragment {
|
||||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public RecyclerViewCursorAdapter.CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
View view = LayoutInflater.from(getActivity())
|
||||||
.inflate(R.layout.list_item_episode, parent, false);
|
.inflate(R.layout.list_item_episode, parent, false);
|
||||||
|
return new ViewHolder(view, getActivity(), themeAccentColor,
|
||||||
// Setup View holder pattern
|
contextlistItemMenuClickListener, hostManager,
|
||||||
ViewHolder viewHolder = new ViewHolder();
|
artWidth, artHeight);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern, only for episodes
|
* View holder pattern, only for episodes
|
||||||
*/
|
*/
|
||||||
public static class ViewHolder {
|
static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||||
TextView titleView;
|
TextView titleView;
|
||||||
TextView detailsView;
|
TextView detailsView;
|
||||||
TextView episodenumberView;
|
TextView episodenumberView;
|
||||||
ImageView contextMenuView;
|
ImageView contextMenuView;
|
||||||
ImageView checkmarkView;
|
ImageView checkmarkView;
|
||||||
ImageView artView;
|
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() {
|
private View.OnClickListener contextlistItemMenuClickListener = new View.OnClickListener() {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.xbmc.kore.ui.sections.video;
|
package org.xbmc.kore.ui.sections.video;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -34,7 +33,6 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
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.service.library.LibrarySyncService;
|
||||||
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
import org.xbmc.kore.ui.AbstractCursorListFragment;
|
||||||
import org.xbmc.kore.ui.AbstractInfoFragment;
|
import org.xbmc.kore.ui.AbstractInfoFragment;
|
||||||
|
import org.xbmc.kore.ui.RecyclerViewCursorAdapter;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
import org.xbmc.kore.utils.Utils;
|
import org.xbmc.kore.utils.Utils;
|
||||||
|
@ -65,7 +64,7 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
||||||
// Activity listener
|
// Activity listener
|
||||||
private OnTVShowSelectedListener listenerActivity;
|
private OnTVShowSelectedListener listenerActivity;
|
||||||
|
|
||||||
private boolean showWatchedStatus;
|
private static boolean showWatchedStatus;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_TVSHOWS; }
|
protected String getListSyncType() { return LibrarySyncService.SYNC_ALL_TVSHOWS; }
|
||||||
|
@ -79,7 +78,7 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CursorAdapter createAdapter() {
|
protected RecyclerViewCursorAdapter createCursorAdapter() {
|
||||||
return new TVShowsAdapter(getActivity());
|
return new TVShowsAdapter(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +308,7 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
||||||
int GENRES = 13;
|
int GENRES = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TVShowsAdapter extends CursorAdapter {
|
private class TVShowsAdapter extends RecyclerViewCursorAdapter {
|
||||||
|
|
||||||
private HostManager hostManager;
|
private HostManager hostManager;
|
||||||
private int artWidth, artHeight;
|
private int artWidth, artHeight;
|
||||||
|
@ -317,8 +316,6 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
||||||
inProgressColor, finishedColor;
|
inProgressColor, finishedColor;
|
||||||
|
|
||||||
public TVShowsAdapter(Context context) {
|
public TVShowsAdapter(Context context) {
|
||||||
super(context, null, 0);
|
|
||||||
|
|
||||||
// Get the default accent color
|
// Get the default accent color
|
||||||
Resources.Theme theme = context.getTheme();
|
Resources.Theme theme = context.getTheme();
|
||||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||||
|
@ -344,82 +341,98 @@ public class TVShowListFragment extends AbstractCursorListFragment {
|
||||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
|
public CursorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = LayoutInflater.from(context)
|
final View view = LayoutInflater.from(getContext())
|
||||||
.inflate(R.layout.grid_item_tvshow, parent, false);
|
.inflate(R.layout.grid_item_tvshow, parent, false);
|
||||||
|
|
||||||
// Setup View holder pattern
|
// Setup View holder pattern
|
||||||
ViewHolder viewHolder = new ViewHolder();
|
ViewHolder viewHolder = new ViewHolder(view, getContext(),
|
||||||
viewHolder.titleView = (TextView)view.findViewById(R.id.title);
|
themeAccentColor, inProgressColor, finishedColor,
|
||||||
viewHolder.detailsView = (TextView)view.findViewById(R.id.details);
|
hostManager,
|
||||||
viewHolder.premieredView = (TextView)view.findViewById(R.id.premiered);
|
artWidth, artHeight);
|
||||||
viewHolder.artView = (ImageView)view.findViewById(R.id.art);
|
|
||||||
viewHolder.watchedProgressView = (ProgressBar)view.findViewById(R.id.tv_shows_progress_bar);
|
|
||||||
|
|
||||||
view.setTag(viewHolder);
|
return 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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View holder pattern
|
* View holder pattern
|
||||||
*/
|
*/
|
||||||
public static class ViewHolder {
|
public static class ViewHolder extends RecyclerViewCursorAdapter.CursorViewHolder {
|
||||||
TextView titleView;
|
TextView titleView;
|
||||||
TextView detailsView;
|
TextView detailsView;
|
||||||
TextView premieredView;
|
TextView premieredView;
|
||||||
ImageView artView;
|
ImageView artView;
|
||||||
ProgressBar watchedProgressView;
|
ProgressBar watchedProgressView;
|
||||||
|
Context context;
|
||||||
|
int themeAccentColor, inProgressColor, finishedColor;
|
||||||
|
HostManager hostManager;
|
||||||
|
int artWidth;
|
||||||
|
int artHeight;
|
||||||
|
|
||||||
AbstractInfoFragment.DataHolder dataHolder = new AbstractInfoFragment.DataHolder(0);
|
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:id="@+id/swipe_refresh_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
<GridView
|
<org.xbmc.kore.ui.viewgroups.RecyclerViewEmptyViewSupport
|
||||||
android:id="@+id/list"
|
android:id="@+id/list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="@dimen/small_padding"
|
style="@style/GridLayoutRecyclerView"/>
|
||||||
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>
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</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
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -17,12 +17,10 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/card"
|
android:id="@+id/card"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor"
|
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:foreground="?android:attr/selectableItemBackground">
|
android:foreground="?android:attr/selectableItemBackground">
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<android.support.v7.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
card_view:cardElevation="@dimen/default_card_elevation"
|
style="@style/Widget.CardView">
|
||||||
card_view:cardBackgroundColor="?attr/appCardBackgroundColor">
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Default spacing because cardview on lollipop doesn't add padding -->
|
<!-- Default spacing because cardview on lollipop doesn't add padding -->
|
||||||
<dimen name="default_grid_horizontal_spacing">8dp</dimen>
|
<dimen name="default_grid_horizontal_spacing">4dp</dimen>
|
||||||
<dimen name="default_grid_vertical_spacing">8dp</dimen>
|
<dimen name="default_grid_vertical_spacing">4dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="default_card_margin">8dp</dimen>
|
||||||
</resources>
|
</resources>
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
<dimen name="card_corner_radius">2dp</dimen>
|
<dimen name="card_corner_radius">2dp</dimen>
|
||||||
<dimen name="default_card_elevation">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_small">12sp</dimen>
|
||||||
<dimen name="text_size_medium">14sp</dimen>
|
<dimen name="text_size_medium">14sp</dimen>
|
||||||
|
|
|
@ -54,6 +54,21 @@
|
||||||
<item name="android:fastScrollEnabled">true</item>
|
<item name="android:fastScrollEnabled">true</item>
|
||||||
</style>
|
</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">
|
<style name="Widget.ListView">
|
||||||
<item name="android:fastScrollEnabled">true</item>
|
<item name="android:fastScrollEnabled">true</item>
|
||||||
<item name="android:divider">@null</item>
|
<item name="android:divider">@null</item>
|
||||||
|
|
Loading…
Reference in New Issue