Merge pull request #145 from poisdeux/sharedelementtransitions_tvshows

Implemented shared element transition for TV shows
This commit is contained in:
Synced Synapse 2015-12-10 23:04:16 +00:00
commit fce521a9bb
6 changed files with 207 additions and 67 deletions

View File

@ -15,6 +15,7 @@
*/ */
package org.xbmc.kore.ui; package org.xbmc.kore.ui;
import android.annotation.TargetApi;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
@ -23,9 +24,12 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.astuetz.PagerSlidingTabStrip; import com.astuetz.PagerSlidingTabStrip;
import org.xbmc.kore.R; import org.xbmc.kore.R;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.TabsAdapter; import org.xbmc.kore.utils.TabsAdapter;
import org.xbmc.kore.utils.UIUtils;
import org.xbmc.kore.utils.Utils;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.InjectView; import butterknife.InjectView;
@ -36,22 +40,45 @@ import butterknife.InjectView;
public class TVShowDetailsFragment extends Fragment { public class TVShowDetailsFragment extends Fragment {
private static final String TAG = LogUtils.makeLogTag(TVShowDetailsFragment.class); private static final String TAG = LogUtils.makeLogTag(TVShowDetailsFragment.class);
public static final String TVSHOWID = "tvshow_id"; public static final String POSTER_TRANS_NAME = "POSTER_TRANS_NAME";
public static final String BUNDLE_KEY_TVSHOWID = "tvshow_id";
public static final String BUNDLE_KEY_TITLE = "title";
public static final String BUNDLE_KEY_PREMIERED = "premiered";
public static final String BUNDLE_KEY_STUDIO = "studio";
public static final String BUNDLE_KEY_EPISODE = "episode";
public static final String BUNDLE_KEY_WATCHEDEPISODES = "watchedepisodes";
public static final String BUNDLE_KEY_RATING = "rating";
public static final String BUNDLE_KEY_PLOT = "plot";
public static final String BUNDLE_KEY_GENRES = "genres";
// Displayed movie id // Displayed movie id
private int tvshowId = -1; private int tvshowId = -1;
private TabsAdapter tabsAdapter;
@InjectView(R.id.pager_tab_strip) PagerSlidingTabStrip pagerTabStrip; @InjectView(R.id.pager_tab_strip) PagerSlidingTabStrip pagerTabStrip;
@InjectView(R.id.pager) ViewPager viewPager; @InjectView(R.id.pager) ViewPager viewPager;
/** /**
* Create a new instance of this, initialized to show tvshowId * Create a new instance of this, initialized to show tvshowId
*/ */
public static TVShowDetailsFragment newInstance(int tvshowId) { @TargetApi(21)
public static TVShowDetailsFragment newInstance(TVShowListFragment.ViewHolder vh) {
TVShowDetailsFragment fragment = new TVShowDetailsFragment(); TVShowDetailsFragment fragment = new TVShowDetailsFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putInt(TVSHOWID, tvshowId); args.putInt(BUNDLE_KEY_TVSHOWID, vh.tvshowId);
args.putInt(BUNDLE_KEY_EPISODE, vh.episode);
args.putString(BUNDLE_KEY_GENRES, vh.genres);
args.putString(BUNDLE_KEY_PLOT, vh.plot);
args.putString(BUNDLE_KEY_PREMIERED, vh.premiered);
args.putDouble(BUNDLE_KEY_RATING, vh.rating);
args.putString(BUNDLE_KEY_STUDIO, vh.studio);
args.putString(BUNDLE_KEY_TITLE, vh.tvshowTitle);
args.putInt(BUNDLE_KEY_WATCHEDEPISODES, vh.watchedEpisodes);
if( Utils.isLollipopOrLater()) {
args.putString(POSTER_TRANS_NAME, vh.artView.getTransitionName());
}
fragment.setArguments(args); fragment.setArguments(args);
return fragment; return fragment;
} }
@ -63,7 +90,7 @@ public class TVShowDetailsFragment extends Fragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
tvshowId = getArguments().getInt(TVSHOWID, -1); tvshowId = getArguments().getInt(BUNDLE_KEY_TVSHOWID, -1);
if ((container == null) || (tvshowId == -1)) { if ((container == null) || (tvshowId == -1)) {
// We're not being shown or there's nothing to show // We're not being shown or there's nothing to show
@ -74,7 +101,7 @@ public class TVShowDetailsFragment extends Fragment {
ButterKnife.inject(this, root); ButterKnife.inject(this, root);
long baseFragmentId = tvshowId * 10; long baseFragmentId = tvshowId * 10;
TabsAdapter tabsAdapter = new TabsAdapter(getActivity(), getChildFragmentManager()) tabsAdapter = new TabsAdapter(getActivity(), getChildFragmentManager())
.addTab(TVShowOverviewFragment.class, getArguments(), R.string.tvshow_overview, .addTab(TVShowOverviewFragment.class, getArguments(), R.string.tvshow_overview,
baseFragmentId) baseFragmentId)
.addTab(TVShowEpisodeListFragment.class, getArguments(), .addTab(TVShowEpisodeListFragment.class, getArguments(),
@ -92,19 +119,26 @@ public class TVShowDetailsFragment extends Fragment {
setHasOptionsMenu(false); setHasOptionsMenu(false);
} }
@Override public Fragment getCurrentTabFragment() {
public void onResume() { return tabsAdapter.getItem(viewPager.getCurrentItem());
super.onResume();
} }
@Override public View getSharedElement() {
public void onPause() { View view = getView();
super.onPause(); if (view == null)
} return null;
@Override //Note: this works as R.id.poster is only used in TVShowOverviewFragment.
public void onSaveInstanceState(Bundle outState) { //If the same id is used in other fragments in the TabsAdapter we
super.onSaveInstanceState(outState); //need to check which fragment is currently displayed
// outState.putInt(TVSHOWID, tvshowId); View artView = view.findViewById(R.id.poster);
View scrollView = view.findViewById(R.id.media_panel);
if (( artView != null ) &&
( scrollView != null ) &&
UIUtils.isViewInBounds(scrollView, artView)) {
return artView;
}
return null;
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.xbmc.kore.ui; package org.xbmc.kore.ui;
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;
@ -47,6 +48,7 @@ import org.xbmc.kore.provider.MediaDatabase;
import org.xbmc.kore.service.LibrarySyncService; import org.xbmc.kore.service.LibrarySyncService;
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;
/** /**
* Fragment that presents the tv show list * Fragment that presents the tv show list
@ -55,7 +57,7 @@ public class TVShowListFragment extends AbstractListFragment {
private static final String TAG = LogUtils.makeLogTag(TVShowListFragment.class); private static final String TAG = LogUtils.makeLogTag(TVShowListFragment.class);
public interface OnTVShowSelectedListener { public interface OnTVShowSelectedListener {
public void onTVShowSelected(int tvshowId, String tvshowTitle); public void onTVShowSelected(TVShowListFragment.ViewHolder vh);
} }
// Activity listener // Activity listener
@ -72,7 +74,7 @@ public class TVShowListFragment extends AbstractListFragment {
// 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
listenerActivity.onTVShowSelected(tag.tvshowId, tag.tvshowTitle); listenerActivity.onTVShowSelected(tag);
} }
}; };
} }
@ -225,9 +227,16 @@ public class TVShowListFragment extends AbstractListFragment {
MediaContract.TVShows.TVSHOWID, MediaContract.TVShows.TVSHOWID,
MediaContract.TVShows.TITLE, MediaContract.TVShows.TITLE,
MediaContract.TVShows.THUMBNAIL, MediaContract.TVShows.THUMBNAIL,
MediaContract.TVShows.FANART,
MediaContract.TVShows.PREMIERED, MediaContract.TVShows.PREMIERED,
MediaContract.TVShows.STUDIO,
MediaContract.TVShows.EPISODE, MediaContract.TVShows.EPISODE,
MediaContract.TVShows.WATCHEDEPISODES, MediaContract.TVShows.WATCHEDEPISODES,
MediaContract.TVShows.RATING,
MediaContract.TVShows.PLOT,
MediaContract.TVShows.PLAYCOUNT,
MediaContract.TVShows.IMDBNUMBER,
MediaContract.TVShows.GENRES,
}; };
String SORT_BY_NAME = MediaContract.TVShows.TITLE + " ASC"; String SORT_BY_NAME = MediaContract.TVShows.TITLE + " ASC";
@ -238,9 +247,16 @@ public class TVShowListFragment extends AbstractListFragment {
final int TVSHOWID = 1; final int TVSHOWID = 1;
final int TITLE = 2; final int TITLE = 2;
final int THUMBNAIL = 3; final int THUMBNAIL = 3;
final int PREMIERED = 4; final int FANART = 4;
final int EPISODE = 5; final int PREMIERED = 5;
final int WATCHEDEPISODES = 6; final int STUDIO = 6;
final int EPISODE = 7;
final int WATCHEDEPISODES = 8;
final int RATING = 9;
final int PLOT = 10;
final int PLAYCOUNT = 11;
final int IMDBNUMBER = 12;
final int GENRES = 13;
} }
private static class TVShowsAdapter extends CursorAdapter { private static class TVShowsAdapter extends CursorAdapter {
@ -257,16 +273,16 @@ public class TVShowListFragment extends AbstractListFragment {
// 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 = context.getResources();
artWidth = (int)(resources.getDimension(R.dimen.now_playing_poster_width) / artWidth = (int)(resources.getDimension(R.dimen.now_playing_poster_width) /
UIUtils.IMAGE_RESIZE_FACTOR); UIUtils.IMAGE_RESIZE_FACTOR);
artHeight = (int)(resources.getDimension(R.dimen.now_playing_poster_height) / artHeight = (int)(resources.getDimension(R.dimen.now_playing_poster_height) /
UIUtils.IMAGE_RESIZE_FACTOR); UIUtils.IMAGE_RESIZE_FACTOR);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public View newView(Context context, final Cursor cursor, ViewGroup parent) { public View newView(Context context, final Cursor cursor, ViewGroup parent) {
final View view = LayoutInflater.from(context) final View view = LayoutInflater.from(context)
.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();
@ -281,6 +297,7 @@ public class TVShowListFragment extends AbstractListFragment {
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@TargetApi(21)
@Override @Override
public void bindView(View view, Context context, Cursor cursor) { public void bindView(View view, Context context, Cursor cursor) {
final ViewHolder viewHolder = (ViewHolder)view.getTag(); final ViewHolder viewHolder = (ViewHolder)view.getTag();
@ -288,16 +305,25 @@ public class TVShowListFragment extends AbstractListFragment {
// Save the movie id // Save the movie id
viewHolder.tvshowId = cursor.getInt(TVShowListQuery.TVSHOWID); viewHolder.tvshowId = cursor.getInt(TVShowListQuery.TVSHOWID);
viewHolder.tvshowTitle = cursor.getString(TVShowListQuery.TITLE); viewHolder.tvshowTitle = cursor.getString(TVShowListQuery.TITLE);
viewHolder.episode = cursor.getInt(TVShowListQuery.EPISODE);
viewHolder.genres = cursor.getString(TVShowListQuery.GENRES);
viewHolder.plot = cursor.getString(TVShowListQuery.PLOT);
viewHolder.premiered = cursor.getString(TVShowListQuery.PREMIERED);
viewHolder.rating = cursor.getInt(TVShowListQuery.RATING);
viewHolder.studio = cursor.getString(TVShowListQuery.STUDIO);
viewHolder.watchedEpisodes = cursor.getInt(TVShowListQuery.WATCHEDEPISODES);
if(Utils.isLollipopOrLater()) {
viewHolder.artView.setTransitionName("a"+viewHolder.tvshowId);
}
viewHolder.titleView.setText(viewHolder.tvshowTitle); viewHolder.titleView.setText(viewHolder.tvshowTitle);
int numEpisodes = cursor.getInt(TVShowListQuery.EPISODE),
watchedEpisodes = cursor.getInt(TVShowListQuery.WATCHEDEPISODES);
String details = String.format(context.getString(R.string.num_episodes), String details = String.format(context.getString(R.string.num_episodes),
numEpisodes, numEpisodes - watchedEpisodes); viewHolder.episode, viewHolder.episode - viewHolder.watchedEpisodes);
viewHolder.detailsView.setText(details); viewHolder.detailsView.setText(details);
String premiered = String.format(context.getString(R.string.premiered), String premiered = String.format(context.getString(R.string.premiered),
cursor.getString(TVShowListQuery.PREMIERED)); viewHolder.premiered);
viewHolder.premieredView.setText(premiered); viewHolder.premieredView.setText(premiered);
UIUtils.loadImageWithCharacterAvatar(context, hostManager, UIUtils.loadImageWithCharacterAvatar(context, hostManager,
cursor.getString(TVShowListQuery.THUMBNAIL), viewHolder.tvshowTitle, cursor.getString(TVShowListQuery.THUMBNAIL), viewHolder.tvshowTitle,
@ -308,14 +334,21 @@ public class TVShowListFragment extends AbstractListFragment {
/** /**
* View holder pattern * View holder pattern
*/ */
private static class ViewHolder { public static class ViewHolder {
TextView titleView; TextView titleView;
TextView detailsView; TextView detailsView;
// TextView yearView; // TextView yearView;
TextView premieredView; TextView premieredView;
ImageView artView; ImageView artView;
int tvshowId; int tvshowId;
String tvshowTitle; String tvshowTitle;
String premiered;
String studio;
int episode;
int watchedEpisodes;
double rating;
String plot;
String genres;
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.xbmc.kore.ui; package org.xbmc.kore.ui;
import android.annotation.TargetApi;
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;
@ -42,6 +43,7 @@ import org.xbmc.kore.provider.MediaContract;
import org.xbmc.kore.service.LibrarySyncService; import org.xbmc.kore.service.LibrarySyncService;
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 java.util.ArrayList; import java.util.ArrayList;
@ -105,8 +107,10 @@ public class TVShowOverviewFragment extends AbstractDetailsFragment
} }
@Override @Override
@TargetApi(21)
protected View createView(LayoutInflater inflater, ViewGroup container) { protected View createView(LayoutInflater inflater, ViewGroup container) {
tvshowId = getArguments().getInt(TVSHOWID, -1); Bundle bundle = getArguments();
tvshowId = bundle.getInt(TVShowDetailsFragment.BUNDLE_KEY_TVSHOWID, -1);
if (tvshowId == -1) { if (tvshowId == -1) {
// There's nothing to show // There's nothing to show
@ -130,6 +134,18 @@ public class TVShowOverviewFragment extends AbstractDetailsFragment
} }
}); });
tvshowTitle = bundle.getString(TVShowDetailsFragment.BUNDLE_KEY_TITLE);
mediaTitle.setText(tvshowTitle);
setMediaUndertitle(bundle.getInt(TVShowDetailsFragment.BUNDLE_KEY_EPISODE), bundle.getInt(TVShowDetailsFragment.BUNDLE_KEY_WATCHEDEPISODES));
setMediaPremiered(bundle.getString(TVShowDetailsFragment.BUNDLE_KEY_PREMIERED), bundle.getString(TVShowDetailsFragment.BUNDLE_KEY_STUDIO));
mediaGenres.setText(bundle.getString(TVShowDetailsFragment.BUNDLE_KEY_GENRES));
setMediaRating(bundle.getDouble(TVShowDetailsFragment.BUNDLE_KEY_RATING));
mediaDescription.setText(bundle.getString(TVShowDetailsFragment.BUNDLE_KEY_PLOT));
if(Utils.isLollipopOrLater()) {
mediaPoster.setTransitionName(getArguments().getString(TVShowDetailsFragment.POSTER_TRANS_NAME));
}
// Pad main content view to overlap with bottom system bar // Pad main content view to overlap with bottom system bar
// UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true); // UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true);
// mediaPanel.setClipToPadding(false); // mediaPanel.setClipToPadding(false);
@ -244,26 +260,13 @@ public class TVShowOverviewFragment extends AbstractDetailsFragment
mediaTitle.setText(tvshowTitle); mediaTitle.setText(tvshowTitle);
int numEpisodes = cursor.getInt(TVShowDetailsQuery.EPISODE), int numEpisodes = cursor.getInt(TVShowDetailsQuery.EPISODE),
watchedEpisodes = cursor.getInt(TVShowDetailsQuery.WATCHEDEPISODES); watchedEpisodes = cursor.getInt(TVShowDetailsQuery.WATCHEDEPISODES);
String episodes = String.format(getString(R.string.num_episodes), setMediaUndertitle(numEpisodes, watchedEpisodes);
numEpisodes, numEpisodes - watchedEpisodes);
mediaUndertitle.setText(episodes); setMediaPremiered(cursor.getString(TVShowDetailsQuery.PREMIERED), cursor.getString(TVShowDetailsQuery.STUDIO));
String premiered = String.format(getString(R.string.premiered),
cursor.getString(TVShowDetailsQuery.PREMIERED)) +
" | " + cursor.getString(TVShowDetailsQuery.STUDIO);
mediaPremiered.setText(premiered);
mediaGenres.setText(cursor.getString(TVShowDetailsQuery.GENRES)); mediaGenres.setText(cursor.getString(TVShowDetailsQuery.GENRES));
double rating = cursor.getDouble(TVShowDetailsQuery.RATING); setMediaRating(cursor.getDouble(TVShowDetailsQuery.RATING));
if (rating > 0) {
mediaRating.setVisibility(View.VISIBLE);
mediaMaxRating.setVisibility(View.VISIBLE);
mediaRating.setText(String.format("%01.01f", rating));
mediaMaxRating.setText(getString(R.string.max_rating_video));
} else {
mediaRating.setVisibility(View.INVISIBLE);
mediaMaxRating.setVisibility(View.INVISIBLE);
}
mediaDescription.setText(cursor.getString(TVShowDetailsQuery.PLOT)); mediaDescription.setText(cursor.getString(TVShowDetailsQuery.PLOT));
@ -286,6 +289,28 @@ public class TVShowOverviewFragment extends AbstractDetailsFragment
mediaArt, displayMetrics.widthPixels, artHeight); mediaArt, displayMetrics.widthPixels, artHeight);
} }
private void setMediaUndertitle(int numEpisodes, int watchedEpisodes) {
String episodes = String.format(getString(R.string.num_episodes),
numEpisodes, numEpisodes - watchedEpisodes);
mediaUndertitle.setText(episodes);
}
private void setMediaPremiered(String premiered, String studio) {
mediaPremiered.setText(String.format(getString(R.string.premiered),
premiered) + " | " + studio);
}
private void setMediaRating(double rating) {
if (rating > 0) {
mediaRating.setVisibility(View.VISIBLE);
mediaMaxRating.setVisibility(View.VISIBLE);
mediaRating.setText(String.format("%01.01f", rating));
mediaMaxRating.setText(getString(R.string.max_rating_video));
} else {
mediaRating.setVisibility(View.INVISIBLE);
mediaMaxRating.setVisibility(View.INVISIBLE);
}
}
/** /**
* Display the cast details * Display the cast details
* *

View File

@ -22,15 +22,20 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.transition.Transition;
import android.transition.TransitionInflater; import android.transition.TransitionInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import android.view.Window; import android.view.Window;
import org.xbmc.kore.R; import org.xbmc.kore.R;
import org.xbmc.kore.utils.LogUtils; import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.Utils; import org.xbmc.kore.utils.Utils;
import java.util.List;
import java.util.Map;
/** /**
* Controls the presentation of TV Shows information (list, details) * Controls the presentation of TV Shows information (list, details)
* All the information is presented by specific fragments * All the information is presented by specific fragments
@ -48,6 +53,9 @@ public class TVShowsActivity extends BaseActivity
private String selectedTVShowTitle = null; private String selectedTVShowTitle = null;
private int selectedEpisodeId = -1; private int selectedEpisodeId = -1;
private TVShowDetailsFragment tvshowDetailsFragment;
private boolean clearSharedElements;
private NavigationDrawerFragment navigationDrawerFragment; private NavigationDrawerFragment navigationDrawerFragment;
@TargetApi(21) @TargetApi(21)
@ -70,10 +78,27 @@ public class TVShowsActivity extends BaseActivity
// Setup animations // Setup animations
if (Utils.isLollipopOrLater()) { if (Utils.isLollipopOrLater()) {
tvshowListFragment.setExitTransition(null); //Fade added to prevent shared element from disappearing very shortly at the start of the transition.
tvshowListFragment.setReenterTransition(TransitionInflater Transition fade = TransitionInflater
.from(this) .from(this)
.inflateTransition(android.R.transition.fade)); .inflateTransition(android.R.transition.fade);
tvshowListFragment.setExitTransition(fade);
tvshowListFragment.setReenterTransition(fade);
tvshowListFragment.setSharedElementReturnTransition(TransitionInflater.from(
this).inflateTransition(R.transition.change_image));
android.support.v4.app.SharedElementCallback seCallback = new android.support.v4.app.SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (clearSharedElements) {
names.clear();
sharedElements.clear();
clearSharedElements = false;
}
}
};
tvshowListFragment.setExitSharedElementCallback(seCallback);
} }
getSupportFragmentManager() getSupportFragmentManager()
.beginTransaction() .beginTransaction()
@ -93,16 +118,6 @@ public class TVShowsActivity extends BaseActivity
// UIUtils.setPaddingForSystemBars(this, findViewById(R.id.drawer_layout), true, true, true); // UIUtils.setPaddingForSystemBars(this, findViewById(R.id.drawer_layout), true, true, true);
} }
@Override
public void onResume() {
super.onResume();
}
@Override
public void onPause() {
super.onPause();
}
@Override @Override
protected void onSaveInstanceState (Bundle outState) { protected void onSaveInstanceState (Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
@ -192,24 +207,46 @@ public class TVShowsActivity extends BaseActivity
/** /**
* Callback from tvshows list fragment when a show is selected. * Callback from tvshows list fragment when a show is selected.
* Switch fragment in portrait * Switch fragment in portrait
* @param tvshowId Selected show * @param vh
* @param tvshowTitle Title
*/ */
@TargetApi(21) @TargetApi(21)
public void onTVShowSelected(int tvshowId, String tvshowTitle) { public void onTVShowSelected(TVShowListFragment.ViewHolder vh) {
selectedTVShowId = tvshowId; selectedTVShowId = vh.tvshowId;
selectedTVShowTitle = tvshowTitle; selectedTVShowTitle = vh.tvshowTitle;
// Replace list fragment // Replace list fragment
TVShowDetailsFragment tvshowDetailsFragment = TVShowDetailsFragment.newInstance(tvshowId); tvshowDetailsFragment = TVShowDetailsFragment.newInstance(vh);
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction(); FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
// Set up transitions // Set up transitions
if (Utils.isLollipopOrLater()) { if (Utils.isLollipopOrLater()) {
android.support.v4.app.SharedElementCallback seCallback = new android.support.v4.app.SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
//On returning onMapSharedElements for the exiting fragment is called before the onMapSharedElements
// for the reentering fragment. We use this to determine if we are returning and if
// we should clear the shared element lists. Note that, clearing must be done in the reentering fragment
// as this is called last. Otherwise it the app will crash during transition setup. Not sure, but might
// be a v4 support package bug.
if (tvshowDetailsFragment.isVisible()) {
View sharedView = tvshowDetailsFragment.getSharedElement();
if (sharedView == null) { // shared element not visible
clearSharedElements = true;
}
}
}
};
tvshowDetailsFragment.setEnterSharedElementCallback(seCallback);
tvshowDetailsFragment.setEnterTransition(TransitionInflater tvshowDetailsFragment.setEnterTransition(TransitionInflater
.from(this) .from(this)
.inflateTransition(R.transition.media_details)); .inflateTransition(R.transition.media_details));
tvshowDetailsFragment.setReturnTransition(null); tvshowDetailsFragment.setReturnTransition(null);
Transition changeImageTransition = TransitionInflater.from(
this).inflateTransition(R.transition.change_image);
tvshowDetailsFragment.setSharedElementReturnTransition(changeImageTransition);
tvshowDetailsFragment.setSharedElementEnterTransition(changeImageTransition);
fragTrans.addSharedElement(vh.artView, vh.artView.getTransitionName());
} else { } else {
fragTrans.setCustomAnimations(R.anim.fragment_details_enter, 0, fragTrans.setCustomAnimations(R.anim.fragment_details_enter, 0,
R.anim.fragment_list_popenter, 0); R.anim.fragment_list_popenter, 0);

View File

@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Rect;
import android.os.Vibrator; import android.os.Vibrator;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@ -462,4 +463,13 @@ public class UIUtils {
} }
}); });
} }
/**
* Returns true if {@param view} is contained within {@param container}'s bounds.
*/
public static boolean isViewInBounds(@NonNull View container, @NonNull View view) {
Rect containerBounds = new Rect();
container.getHitRect(containerBounds);
return view.getLocalVisibleRect(containerBounds);
}
} }

View File

@ -18,6 +18,7 @@
<fade> <fade>
<targets> <targets>
<target android:targetId="@id/art"/> <target android:targetId="@id/art"/>
<target android:targetId="@id/pager_tab_strip"/>
</targets> </targets>
</fade> </fade>