Add support to see all cast on now playing screen

This commit is contained in:
Synced Synapse 2015-07-29 18:37:28 +01:00
parent d48b95d86e
commit a07a819898
5 changed files with 150 additions and 131 deletions

View File

@ -15,6 +15,9 @@
*/
package org.xbmc.kore.jsonrpc.type;
import android.os.Parcel;
import android.os.Parcelable;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.xbmc.kore.utils.JsonUtils;
@ -29,7 +32,7 @@ import java.util.List;
public class VideoType {
private static final String TAG = LogUtils.makeLogTag(VideoType.class);
public static class Cast {
public static class Cast implements Parcelable {
public static final String NAME = "name";
public static final String ORDER = "order";
public static final String ROLE = "role";
@ -72,6 +75,29 @@ public class VideoType {
}
return castList;
}
// Parcelable interface implementation
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeString(name);
out.writeInt(order);
out.writeString(role);
out.writeString(thumbnail);
}
public static final Parcelable.Creator<Cast> CREATOR
= new Parcelable.Creator<Cast>() {
public Cast createFromParcel(Parcel in) {
return new Cast(in.readString(), in.readInt(), in.readString(), in.readString());
}
public Cast[] newArray(int size) {
return new Cast[size];
}
};
}
public static class Resume {

View File

@ -33,17 +33,21 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import org.xbmc.kore.R;
import org.xbmc.kore.host.HostManager;
import org.xbmc.kore.jsonrpc.type.VideoType;
import org.xbmc.kore.provider.MediaContract;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;
import java.util.ArrayList;
import butterknife.ButterKnife;
import butterknife.InjectView;
@ -58,9 +62,11 @@ public class AllCastActivity extends BaseActivity
public static final String EXTRA_CAST_TYPE = "EXTRA_CAST_TYPE";
public static final String EXTRA_ID = "EXTRA_ID";
public static final String EXTRA_TITLE = "EXTRA_TITLE";
public static final String EXTRA_CAST_LIST = "EXTRA_CAST_LIST";
public static final int EXTRA_TYPE_MOVIE = 0;
public static final int EXTRA_TYPE_TVSHOW = 1;
public static final int EXTRA_TYPE_CAST_LIST = 2;
// Loader IDs
private static final int LOADER_CAST = 0;
@ -70,7 +76,9 @@ public class AllCastActivity extends BaseActivity
private int movie_tvshow_id = -1;
private String movie_tvshow_title;
private CursorAdapter adapter;
private ArrayList<VideoType.Cast> castArrayList;
private CursorAdapter cursorAdapter;
NavigationDrawerFragment navigationDrawerFragment;
@InjectView(R.id.cast_list) GridView castGridView;
@ -99,7 +107,7 @@ public class AllCastActivity extends BaseActivity
LogUtils.LOGD(TAG, "Showing cast for: " + movie_tvshow_title);
// Configure the adapter and start the loader
// Configure the grid
castGridView.setEmptyView(emptyView);
castGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
@ -109,10 +117,19 @@ public class AllCastActivity extends BaseActivity
}
});
adapter = new CastAdapter(this, cast_type);
castGridView.setAdapter(adapter);
getLoaderManager().initLoader(LOADER_CAST, null, this);
if (cast_type == EXTRA_TYPE_CAST_LIST) {
if (savedInstanceState == null) {
castArrayList = getIntent().getParcelableArrayListExtra(EXTRA_CAST_LIST);
} else {
castArrayList = savedInstanceState.getParcelableArrayList(EXTRA_CAST_LIST);
}
CastArrayAdapter arrayAdapter = new CastArrayAdapter(this, castArrayList);
castGridView.setAdapter(arrayAdapter);
} else {
cursorAdapter = new CastCursorAdapter(this, cast_type);
castGridView.setAdapter(cursorAdapter);
getLoaderManager().initLoader(LOADER_CAST, null, this);
}
setupActionBar(movie_tvshow_title);
}
@ -133,6 +150,8 @@ public class AllCastActivity extends BaseActivity
outState.putInt(EXTRA_CAST_TYPE, cast_type);
outState.putInt(EXTRA_ID, movie_tvshow_id);
outState.putString(EXTRA_TITLE, movie_tvshow_title);
if (cast_type == EXTRA_TYPE_CAST_LIST)
outState.putParcelableArrayList(EXTRA_CAST_LIST, castArrayList);
}
private void setupActionBar(String title) {
@ -178,7 +197,7 @@ public class AllCastActivity extends BaseActivity
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
LogUtils.LOGD(TAG, "cursor count: " + cursor.getCount());
adapter.swapCursor(cursor);
cursorAdapter.swapCursor(cursor);
// To prevent the empty text from appearing on the first load, set it now
emptyView.setText(getString(R.string.no_cast_info));
}
@ -187,10 +206,67 @@ public class AllCastActivity extends BaseActivity
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
// Release loader's data
adapter.swapCursor(null);
cursorAdapter.swapCursor(null);
}
private static class CastAdapter extends CursorAdapter {
public static class CastArrayAdapter extends ArrayAdapter<VideoType.Cast> {
private HostManager hostManager;
private int artWidth = -1, artHeight = -1;
public CastArrayAdapter(Context context, ArrayList<VideoType.Cast> castArrayList) {
super(context, 0, castArrayList);
this.hostManager = HostManager.getInstance(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext())
.inflate(R.layout.grid_item_cast, parent, false);
if (artWidth == -1) {
Resources resources = getContext().getResources();
int imageMarginPx = resources.getDimensionPixelSize(R.dimen.small_padding);
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
int numColumns = resources.getInteger(R.integer.cast_grid_view_columns);
artWidth = (displayMetrics.widthPixels - (2 + numColumns - 1) * imageMarginPx) / numColumns;
artHeight = (int) (artWidth * 1.5);
LogUtils.LOGD(TAG, "width: " + artWidth);
}
// Setup View holder pattern
ViewHolder viewHolder = new ViewHolder();
viewHolder.roleView = (TextView) convertView.findViewById(R.id.role);
viewHolder.nameView = (TextView) convertView.findViewById(R.id.name);
viewHolder.pictureView = (ImageView) convertView.findViewById(R.id.picture);
convertView.setTag(viewHolder);
convertView.getLayoutParams().width = artWidth;
convertView.getLayoutParams().height = artHeight;
}
final ViewHolder viewHolder = (ViewHolder)convertView.getTag();
VideoType.Cast cast = getItem(position);
viewHolder.roleView.setText(cast.role);
viewHolder.nameView.setText(cast.name);
UIUtils.loadImageWithCharacterAvatar(getContext(), hostManager,
cast.thumbnail, cast.name,
viewHolder.pictureView, artWidth, artHeight);
viewHolder.castName = cast.name;
return convertView;
}
}
private static class CastCursorAdapter extends CursorAdapter {
Context context;
private HostManager hostManager;
private int artWidth = -1, artHeight = -1;
@ -199,7 +275,7 @@ public class AllCastActivity extends BaseActivity
private int role_idx = 3;
private int thumbnail_idx = 4;
public CastAdapter(Context context, int castType) {
public CastCursorAdapter(Context context, int castType) {
super(context, null, false);
this.context = context;
this.hostManager = HostManager.getInstance(context);

View File

@ -16,6 +16,7 @@
package org.xbmc.kore.ui;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Bundle;
@ -28,6 +29,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -39,6 +41,7 @@ import android.widget.TextView;
import android.widget.Toast;
import org.xbmc.kore.R;
import org.xbmc.kore.Settings;
import org.xbmc.kore.host.HostConnectionObserver;
import org.xbmc.kore.host.HostInfo;
import org.xbmc.kore.host.HostManager;
@ -54,11 +57,13 @@ import org.xbmc.kore.jsonrpc.type.ApplicationType;
import org.xbmc.kore.jsonrpc.type.GlobalType;
import org.xbmc.kore.jsonrpc.type.ListType;
import org.xbmc.kore.jsonrpc.type.PlayerType;
import org.xbmc.kore.jsonrpc.type.VideoType;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.RepeatListener;
import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife;
@ -160,8 +165,7 @@ public class NowPlayingFragment extends Fragment
@InjectView(R.id.media_description) TextView mediaDescription;
@InjectView(R.id.cast_list) GridLayout videoCastList;
@InjectView(R.id.additional_cast_list) TextView videoAdditionalCastList;
@InjectView(R.id.additional_cast_title) TextView videoAdditionalCastTitle;
@InjectView(R.id.see_all_cast) Button seeAllCast;
@Override
public void onAttach(Activity activity) {
@ -637,8 +641,8 @@ public class NowPlayingFragment extends Fragment
* @param getItemResult Return from method {@link org.xbmc.kore.jsonrpc.method.Player.GetItem}
*/
private void setNowPlayingInfo(PlayerType.PropertyValue getPropertiesResult,
ListType.ItemsAll getItemResult) {
String title, underTitle, art, poster, genreSeason, year,
final ListType.ItemsAll getItemResult) {
final String title, underTitle, art, poster, genreSeason, year,
descriptionPlot, votes, maxRating;
double rating;
@ -839,8 +843,6 @@ public class NowPlayingFragment extends Fragment
(getPropertiesResult.audiostreams.size() > 0)) {
overflowButton.setVisibility(View.VISIBLE);
videoCastList.setVisibility(View.VISIBLE);
videoAdditionalCastTitle.setVisibility(View.VISIBLE);
videoAdditionalCastList.setVisibility(View.VISIBLE);
// Save subtitles and audiostreams list
availableAudioStreams = getPropertiesResult.audiostreams;
@ -849,12 +851,28 @@ public class NowPlayingFragment extends Fragment
currentSubtitleIndex = getPropertiesResult.currentsubtitle.index;
// Cast list
UIUtils.setupCastInfo(getActivity(), getItemResult.cast, videoCastList, videoAdditionalCastTitle, videoAdditionalCastList);
UIUtils.setupCastInfo(getActivity(), getItemResult.cast, videoCastList);
seeAllCast.setVisibility(
(getItemResult.cast.size() <= Settings.DEFAULT_MAX_CAST_PICTURES) ?
View.GONE : View.VISIBLE);
seeAllCast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent launchIntent = new Intent(getActivity(), AllCastActivity.class)
.putExtra(AllCastActivity.EXTRA_CAST_TYPE, AllCastActivity.EXTRA_TYPE_CAST_LIST)
.putExtra(AllCastActivity.EXTRA_ID, 0)
.putExtra(AllCastActivity.EXTRA_TITLE, title)
.putParcelableArrayListExtra(AllCastActivity.EXTRA_CAST_LIST,
(ArrayList<VideoType.Cast>)getItemResult.cast);
startActivity(launchIntent);
getActivity().overridePendingTransition(R.anim.activity_in, R.anim.activity_out);
}
});
} else {
overflowButton.setVisibility(View.GONE);
videoCastList.setVisibility(View.GONE);
videoAdditionalCastTitle.setVisibility(View.GONE);
videoAdditionalCastList.setVisibility(View.GONE);
seeAllCast.setVisibility(View.GONE);
}
}

View File

@ -219,97 +219,6 @@ public class UIUtils {
view.setImageResource((speed == 1) ? iconPauseResId: iconPlayResId);
}
/**
* Fills the standard cast info list, consisting of a {@link android.widget.GridLayout}
* with actor images and a Textview with the name and the role of the additional cast.
* The number of actor presented on the {@link android.widget.GridLayout} is controlled
* through the global setting, and only actors with images are presented.
* The rest are presented in the additionalCastView TextView
*
* @param context Activity
* @param castList Cast list
* @param castListView GridLayout on which too show actors that have images
* @param additionalCastTitleView View with additional cast title
* @param additionalCastView Additional cast
*/
public static void setupCastInfo(final Context context,
List<VideoType.Cast> castList, GridLayout castListView,
TextView additionalCastTitleView, TextView additionalCastView) {
HostManager hostManager = HostManager.getInstance(context);
Resources resources = context.getResources();
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
View.OnClickListener castListClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Utils.openImdbForPerson(context, (String)v.getTag());
}
};
castListView.removeAllViews();
int numColumns = castListView.getColumnCount();
int layoutMarginPx = 2 * resources.getDimensionPixelSize(R.dimen.remote_content_hmargin);
int imageMarginPx = 2 * resources.getDimensionPixelSize(R.dimen.image_grid_margin);
int imageWidth = (displayMetrics.widthPixels - layoutMarginPx - numColumns * imageMarginPx) / numColumns;
int imageHeight = (int)(imageWidth * 1.5);
List<VideoType.Cast> noPicturesCastList = new ArrayList<VideoType.Cast>();
int maxCastPictures = Settings.DEFAULT_MAX_CAST_PICTURES;
int currentPictureNumber = 0;
for (int i = 0; i < castList.size(); i++) {
VideoType.Cast actor = castList.get(i);
if ((currentPictureNumber < maxCastPictures) && (actor.thumbnail != null)) {
// Present the picture
currentPictureNumber++;
View castView = LayoutInflater.from(context).inflate(R.layout.grid_item_cast, castListView, false);
ImageView castPicture = (ImageView) castView.findViewById(R.id.picture);
TextView castName = (TextView) castView.findViewById(R.id.name);
TextView castRole = (TextView) castView.findViewById(R.id.role);
castView.getLayoutParams().width = imageWidth;
castView.getLayoutParams().height = imageHeight;
castView.setTag(actor.name);
castView.setOnClickListener(castListClickListener);
castName.setText(actor.name);
castRole.setText(actor.role);
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
actor.thumbnail, actor.name,
castPicture, imageWidth, imageHeight);
castListView.addView(castView);
} else {
noPicturesCastList.add(actor);
}
}
// Additional cast
if (noPicturesCastList.size() > 0) {
additionalCastTitleView.setVisibility(View.VISIBLE);
additionalCastView.setVisibility(View.VISIBLE);
StringBuilder castListText = new StringBuilder();
boolean first = true;
for (VideoType.Cast cast : noPicturesCastList) {
if (!first) castListText.append("\n");
first = false;
if (!TextUtils.isEmpty(cast.role)) {
castListText.append(String.format(context.getString(R.string.cast_list_text),
cast.name, cast.role));
} else {
castListText.append(cast.name);
}
}
additionalCastView.setText(castListText);
} else {
additionalCastTitleView.setVisibility(View.GONE);
additionalCastView.setVisibility(View.GONE);
}
}
/**
* Fills the standard cast info list, consisting of a {@link android.widget.GridLayout}
* with actor images and a Textview with the name and the role of the additional cast.

View File

@ -42,7 +42,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/remote_content_hmargin"
android:layout_marginRight="@dimen/remote_content_hmargin">
android:layout_marginRight="@dimen/remote_content_hmargin"
android:paddingBottom="@dimen/default_padding">
<TextView
android:id="@+id/media_title"
@ -305,27 +306,16 @@
android:columnCount="@integer/cast_grid_view_columns"
android:orientation="horizontal"/>
<TextView
android:id="@+id/additional_cast_title"
android:layout_width="match_parent"
<Button
android:id="@+id/see_all_cast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/cast_list"
style="@style/TextAppearance.Media.Title"
android:layout_marginTop="@dimen/default_padding"
android:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding"
android:text="@string/additional_cast"/>
<TextView
android:id="@+id/additional_cast_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/additional_cast_title"
style="@style/TextAppearance.Media.Info"
android:textColor="?attr/appTextColorSecondary"
android:layout_marginBottom="@dimen/default_padding"
android:paddingLeft="@dimen/default_padding"
android:paddingRight="@dimen/default_padding"/>
android:layout_alignRight="@id/cast_list"
android:layout_alignEnd="@id/cast_list"
android:layout_marginRight="@dimen/small_padding"
android:layout_marginEnd="@dimen/small_padding"
android:text="@string/see_all_cast"/>
</RelativeLayout>
</ScrollView>