Merge pull request #154 from poisdeux/sharedelementtransition_musicvideos
Implemented shared element transitions for music videos
This commit is contained in:
commit
05906fe081
|
@ -19,6 +19,7 @@ import android.annotation.TargetApi;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.app.SharedElementCallback;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
@ -66,6 +67,8 @@ public class MusicActivity extends BaseActivity
|
|||
|
||||
private NavigationDrawerFragment navigationDrawerFragment;
|
||||
|
||||
private MusicListFragment musicListFragment;
|
||||
|
||||
private boolean clearSharedElements;
|
||||
|
||||
@TargetApi(21)
|
||||
|
@ -80,7 +83,7 @@ public class MusicActivity extends BaseActivity
|
|||
navigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout));
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
MusicListFragment musicListFragment = new MusicListFragment();
|
||||
musicListFragment = new MusicListFragment();
|
||||
|
||||
// Setup animations
|
||||
if (Utils.isLollipopOrLater()) {
|
||||
|
@ -88,6 +91,16 @@ public class MusicActivity extends BaseActivity
|
|||
musicListFragment.setReenterTransition(TransitionInflater
|
||||
.from(this)
|
||||
.inflateTransition(android.R.transition.fade));
|
||||
musicListFragment.setExitSharedElementCallback(new SharedElementCallback() {
|
||||
@Override
|
||||
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
|
||||
if (clearSharedElements) {
|
||||
names.clear();
|
||||
sharedElements.clear();
|
||||
clearSharedElements = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
|
@ -360,20 +373,46 @@ public class MusicActivity extends BaseActivity
|
|||
}
|
||||
|
||||
@TargetApi(21)
|
||||
public void onMusicVideoSelected(int musicVideoId, String musicVideoTitle) {
|
||||
selectedMusicVideoId = musicVideoId;
|
||||
selectedMusicVideoTitle = musicVideoTitle;
|
||||
public void onMusicVideoSelected(MusicVideoListFragment.ViewHolder vh) {
|
||||
selectedMusicVideoId = vh.musicVideoId;
|
||||
selectedMusicVideoTitle = vh.musicVideoTitle;
|
||||
|
||||
// Replace list fragment
|
||||
MusicVideoDetailsFragment detailsFragment = MusicVideoDetailsFragment.newInstance(musicVideoId);
|
||||
final MusicVideoDetailsFragment detailsFragment = MusicVideoDetailsFragment.newInstance(vh);
|
||||
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
|
||||
|
||||
// Set up transitions
|
||||
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 (detailsFragment.isVisible()) {
|
||||
View sharedView = detailsFragment.getSharedElement();
|
||||
if (sharedView == null) { // shared element not visible
|
||||
LogUtils.LOGD(TAG, "onMusicVideoSelected: setting clearedSharedElements to true");
|
||||
clearSharedElements = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
detailsFragment.setEnterSharedElementCallback(seCallback);
|
||||
|
||||
detailsFragment.setEnterTransition(TransitionInflater
|
||||
.from(this)
|
||||
.inflateTransition(R.transition.media_details));
|
||||
detailsFragment.setReturnTransition(null);
|
||||
|
||||
Transition changeImageTransition = TransitionInflater.from(
|
||||
this).inflateTransition(R.transition.change_image);
|
||||
detailsFragment.setSharedElementReturnTransition(changeImageTransition);
|
||||
detailsFragment.setSharedElementEnterTransition(changeImageTransition);
|
||||
|
||||
fragTrans.addSharedElement(vh.artView, vh.artView.getTransitionName());
|
||||
} else {
|
||||
fragTrans.setCustomAnimations(R.anim.fragment_details_enter, 0,
|
||||
R.anim.fragment_list_popenter, 0);
|
||||
|
@ -382,6 +421,6 @@ public class MusicActivity extends BaseActivity
|
|||
fragTrans.replace(R.id.fragment_container, detailsFragment)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
setupActionBar(null, null, null, musicVideoTitle);
|
||||
setupActionBar(null, null, null, selectedMusicVideoTitle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
|
@ -55,6 +56,7 @@ import org.xbmc.kore.service.LibrarySyncService;
|
|||
import org.xbmc.kore.utils.FileDownloadHelper;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
@ -70,7 +72,15 @@ public class MusicVideoDetailsFragment extends AbstractDetailsFragment
|
|||
implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
private static final String TAG = LogUtils.makeLogTag(MusicVideoDetailsFragment.class);
|
||||
|
||||
public static final String MUSICVIDEOID = "music_video_id";
|
||||
public static final String BUNDLE_KEY_ID = "music_video_id";
|
||||
public static final String BUNDLE_KEY_ALBUM = "album";
|
||||
public static final String POSTER_TRANS_NAME = "POSTER_TRANS_NAME";
|
||||
public static final String BUNDLE_KEY_ARTIST = "artist";
|
||||
public static final String BUNDLE_KEY_TITLE = "title";
|
||||
public static final String BUNDLE_KEY_GENRES = "genre";
|
||||
public static final String BUNDLE_KEY_YEAR = "year";
|
||||
public static final String BUNDLE_KEY_PLOT = "plot";
|
||||
public static final String BUNDLE_KEY_RUNTIME = "runtime";
|
||||
|
||||
// Loader IDs
|
||||
private static final int LOADER_MUSIC_VIDEO = 0;
|
||||
|
@ -114,18 +124,32 @@ public class MusicVideoDetailsFragment extends AbstractDetailsFragment
|
|||
/**
|
||||
* Create a new instance of this, initialized to show the video musicVideoId
|
||||
*/
|
||||
public static MusicVideoDetailsFragment newInstance(int musicVideoId) {
|
||||
@TargetApi(21)
|
||||
public static MusicVideoDetailsFragment newInstance(MusicVideoListFragment.ViewHolder vh) {
|
||||
MusicVideoDetailsFragment fragment = new MusicVideoDetailsFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(MUSICVIDEOID, musicVideoId);
|
||||
args.putInt(BUNDLE_KEY_ID, vh.musicVideoId);
|
||||
args.putString(BUNDLE_KEY_TITLE, vh.musicVideoTitle);
|
||||
args.putString(BUNDLE_KEY_ALBUM, vh.album);
|
||||
args.putString(BUNDLE_KEY_ARTIST, vh.artist);
|
||||
args.putString(BUNDLE_KEY_GENRES, vh.genres);
|
||||
args.putString(BUNDLE_KEY_PLOT, vh.plot);
|
||||
args.putInt(BUNDLE_KEY_RUNTIME, vh.runtime);
|
||||
args.putInt(BUNDLE_KEY_YEAR, vh.year);
|
||||
|
||||
if( Utils.isLollipopOrLater()) {
|
||||
args.putString(POSTER_TRANS_NAME, vh.artView.getTransitionName());
|
||||
}
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
protected View createView(LayoutInflater inflater, ViewGroup container) {
|
||||
musicVideoId = getArguments().getInt(MUSICVIDEOID, -1);
|
||||
Bundle bundle = getArguments();
|
||||
musicVideoId = bundle.getInt(BUNDLE_KEY_ID, -1);
|
||||
|
||||
if (musicVideoId == -1) {
|
||||
// There's nothing to show
|
||||
|
@ -152,6 +176,16 @@ public class MusicVideoDetailsFragment extends AbstractDetailsFragment
|
|||
FloatingActionButton fab = (FloatingActionButton)fabButton;
|
||||
fab.attachToScrollView((ObservableScrollView) mediaPanel);
|
||||
|
||||
mediaTitle.setText(bundle.getString(BUNDLE_KEY_TITLE));
|
||||
setMediaUndertitle(bundle.getString(BUNDLE_KEY_ARTIST), bundle.getString(BUNDLE_KEY_ALBUM));
|
||||
setMediaYear(bundle.getInt(BUNDLE_KEY_RUNTIME), bundle.getInt(BUNDLE_KEY_YEAR));
|
||||
mediaGenres.setText(bundle.getString(BUNDLE_KEY_GENRES));
|
||||
mediaDescription.setText(bundle.getString(BUNDLE_KEY_PLOT));
|
||||
|
||||
if(Utils.isLollipopOrLater()) {
|
||||
mediaPoster.setTransitionName(bundle.getString(POSTER_TRANS_NAME));
|
||||
}
|
||||
|
||||
// Pad main content view to overlap with bottom system bar
|
||||
// UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true);
|
||||
// mediaPanel.setClipToPadding(false);
|
||||
|
@ -380,16 +414,11 @@ public class MusicVideoDetailsFragment extends AbstractDetailsFragment
|
|||
cursor.moveToFirst();
|
||||
String musicVideoTitle = cursor.getString(MusicVideoDetailsQuery.TITLE);
|
||||
mediaTitle.setText(musicVideoTitle);
|
||||
String artistAlbum = cursor.getString(MusicVideoDetailsQuery.ARTIST) + " | " +
|
||||
cursor.getString(MusicVideoDetailsQuery.ALBUM);
|
||||
mediaUndertitle.setText(artistAlbum);
|
||||
|
||||
int runtime = cursor.getInt(MusicVideoDetailsQuery.RUNTIME);
|
||||
String durationYear = runtime > 0 ?
|
||||
UIUtils.formatTime(runtime) + " | " +
|
||||
String.valueOf(cursor.getInt(MusicVideoDetailsQuery.YEAR)) :
|
||||
String.valueOf(cursor.getInt(MusicVideoDetailsQuery.YEAR));
|
||||
mediaYear.setText(durationYear);
|
||||
setMediaUndertitle(cursor.getString(MusicVideoDetailsQuery.ARTIST), cursor.getString(MusicVideoDetailsQuery.ALBUM));
|
||||
|
||||
setMediaYear(cursor.getInt(MusicVideoDetailsQuery.RUNTIME), cursor.getInt(MusicVideoDetailsQuery.YEAR));
|
||||
|
||||
mediaGenres.setText(cursor.getString(MusicVideoDetailsQuery.GENRES));
|
||||
|
||||
mediaDescription.setText(cursor.getString(MusicVideoDetailsQuery.PLOT));
|
||||
|
@ -404,41 +433,20 @@ public class MusicVideoDetailsFragment extends AbstractDetailsFragment
|
|||
|
||||
int artHeight = resources.getDimensionPixelOffset(R.dimen.now_playing_art_height),
|
||||
artWidth = displayMetrics.widthPixels;
|
||||
if (!TextUtils.isEmpty(fanart)) {
|
||||
int posterWidth = resources.getDimensionPixelOffset(R.dimen.musicvideodetail_poster_width);
|
||||
int posterHeight = resources.getDimensionPixelOffset(R.dimen.musicvideodetail_poster_heigth);
|
||||
mediaPoster.setVisibility(View.VISIBLE);
|
||||
UIUtils.loadImageWithCharacterAvatar(getActivity(), getHostManager(),
|
||||
poster, musicVideoTitle,
|
||||
mediaPoster, posterWidth, posterHeight);
|
||||
UIUtils.loadImageIntoImageview(getHostManager(),
|
||||
fanart,
|
||||
mediaArt, artWidth, artHeight);
|
||||
} else {
|
||||
// No fanart, just present the poster
|
||||
mediaPoster.setVisibility(View.GONE);
|
||||
UIUtils.loadImageIntoImageview(getHostManager(),
|
||||
poster,
|
||||
mediaArt, artWidth, artHeight);
|
||||
// Reset padding
|
||||
int paddingLeft = mediaTitle.getPaddingRight(),
|
||||
paddingRight = mediaTitle.getPaddingRight(),
|
||||
paddingTop = mediaTitle.getPaddingTop(),
|
||||
paddingBottom = mediaTitle.getPaddingBottom();
|
||||
mediaTitle.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
mediaUndertitle.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int posterWidth = resources.getDimensionPixelOffset(R.dimen.musicvideodetail_poster_width);
|
||||
int posterHeight = resources.getDimensionPixelOffset(R.dimen.musicvideodetail_poster_width);
|
||||
UIUtils.loadImageWithCharacterAvatar(getActivity(), getHostManager(),
|
||||
poster, musicVideoTitle,
|
||||
mediaPoster, posterWidth, posterHeight);
|
||||
UIUtils.loadImageIntoImageview(getHostManager(),
|
||||
TextUtils.isEmpty(fanart)? poster : fanart,
|
||||
mediaArt, artWidth, artHeight);
|
||||
|
||||
// Setup download info
|
||||
musicVideoDownloadInfo = new FileDownloadHelper.MusicVideoInfo(
|
||||
musicVideoTitle, cursor.getString(MusicVideoDetailsQuery.FILE));
|
||||
|
||||
// Check if downloaded file exists
|
||||
downloadButton.setVisibility(View.VISIBLE);
|
||||
if (musicVideoDownloadInfo.downloadFileExists()) {
|
||||
Resources.Theme theme = getActivity().getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[]{
|
||||
|
@ -452,6 +460,30 @@ public class MusicVideoDetailsFragment extends AbstractDetailsFragment
|
|||
}
|
||||
}
|
||||
|
||||
private void setMediaUndertitle(String artist, String album) {
|
||||
mediaUndertitle.setText(artist + " | " + album);
|
||||
}
|
||||
|
||||
private void setMediaYear(int runtime, int year) {
|
||||
String durationYear = runtime > 0 ?
|
||||
UIUtils.formatTime(runtime) + " | " +
|
||||
String.valueOf(year) :
|
||||
String.valueOf(year);
|
||||
mediaYear.setText(durationYear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared element if visible
|
||||
* @return View if visible, null otherwise
|
||||
*/
|
||||
public View getSharedElement() {
|
||||
if (UIUtils.isViewInBounds(mediaPanel, mediaPoster)) {
|
||||
return mediaPoster;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Video details query parameters.
|
||||
*/
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.xbmc.kore.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
@ -44,6 +45,7 @@ import org.xbmc.kore.provider.MediaDatabase;
|
|||
import org.xbmc.kore.service.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
||||
/**
|
||||
* Fragment that presents the artists list
|
||||
|
@ -52,7 +54,7 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
private static final String TAG = LogUtils.makeLogTag(MusicVideoListFragment.class);
|
||||
|
||||
public interface OnMusicVideoSelectedListener {
|
||||
public void onMusicVideoSelected(int musicVideoId, String musicVideoTitle);
|
||||
public void onMusicVideoSelected(ViewHolder vh);
|
||||
}
|
||||
|
||||
// Activity listener
|
||||
|
@ -69,7 +71,7 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
// Get the movie id from the tag
|
||||
ViewHolder tag = (ViewHolder)view.getTag();
|
||||
// Notify the activity
|
||||
listenerActivity.onMusicVideoSelected(tag.musicVideoId, tag.musicVideoTitle);
|
||||
listenerActivity.onMusicVideoSelected(tag);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -141,6 +143,8 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
MediaContract.MusicVideos.THUMBNAIL,
|
||||
MediaContract.MusicVideos.RUNTIME,
|
||||
MediaContract.MusicVideos.GENRES,
|
||||
MediaContract.MusicVideos.YEAR,
|
||||
MediaContract.MusicVideos.PLOT,
|
||||
};
|
||||
|
||||
String SORT = MediaDatabase.sortCommonTokens(MediaContract.MusicVideos.TITLE) + " ASC";
|
||||
|
@ -153,6 +157,8 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
final int THUMBNAIL = 5;
|
||||
final int RUNTIME = 6;
|
||||
final int GENRES = 7;
|
||||
final int YEAR = 8;
|
||||
final int PLOT = 9;
|
||||
}
|
||||
|
||||
private static class MusicVideosAdapter extends CursorAdapter {
|
||||
|
@ -166,10 +172,8 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
|
||||
// Get the art dimensions
|
||||
Resources resources = context.getResources();
|
||||
artWidth = (int)(resources.getDimension(R.dimen.musicvideolist_art_width) /
|
||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
artHeight = (int)(resources.getDimension(R.dimen.musicvideolist_art_heigth) /
|
||||
UIUtils.IMAGE_RESIZE_FACTOR);
|
||||
artHeight = resources.getDimensionPixelOffset(R.dimen.musicvideodetail_poster_heigth);
|
||||
artWidth = resources.getDimensionPixelOffset(R.dimen.musicvideodetail_poster_width);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
@ -190,6 +194,7 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@TargetApi(21)
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
|
@ -197,28 +202,37 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
// Save the movie id
|
||||
viewHolder.musicVideoId = cursor.getInt(MusicVideosListQuery.MUSICVIDEOID);
|
||||
viewHolder.musicVideoTitle = cursor.getString(MusicVideosListQuery.TITLE);
|
||||
viewHolder.album = cursor.getString(MusicVideosListQuery.ALBUM);
|
||||
viewHolder.artist = cursor.getString(MusicVideosListQuery.ARTIST);
|
||||
viewHolder.genres = cursor.getString(MusicVideosListQuery.GENRES);
|
||||
viewHolder.plot = cursor.getString(MusicVideosListQuery.PLOT);
|
||||
viewHolder.runtime = cursor.getInt(MusicVideosListQuery.RUNTIME);
|
||||
viewHolder.year = cursor.getInt(MusicVideosListQuery.YEAR);
|
||||
|
||||
viewHolder.titleView.setText(viewHolder.musicVideoTitle);
|
||||
String artistAlbum = cursor.getString(MusicVideosListQuery.ARTIST) + " | " +
|
||||
cursor.getString(MusicVideosListQuery.ALBUM);
|
||||
String artistAlbum = viewHolder.artist + " | " +
|
||||
viewHolder.album;
|
||||
viewHolder.artistAlbumView.setText(artistAlbum);
|
||||
|
||||
int runtime = cursor.getInt(MusicVideosListQuery.RUNTIME);
|
||||
String durationGenres =
|
||||
runtime > 0 ?
|
||||
UIUtils.formatTime(runtime) + " | " + cursor.getString(MusicVideosListQuery.GENRES) :
|
||||
cursor.getString(MusicVideosListQuery.GENRES);
|
||||
viewHolder.runtime > 0 ?
|
||||
UIUtils.formatTime(viewHolder.runtime) + " | " + viewHolder.genres :
|
||||
viewHolder.genres;
|
||||
viewHolder.durationGenresView.setText(durationGenres);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
cursor.getString(MusicVideosListQuery.THUMBNAIL), viewHolder.musicVideoTitle,
|
||||
viewHolder.artView, artWidth, artHeight);
|
||||
|
||||
if(Utils.isLollipopOrLater()) {
|
||||
viewHolder.artView.setTransitionName("a"+viewHolder.musicVideoId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View holder pattern
|
||||
*/
|
||||
private static class ViewHolder {
|
||||
public static class ViewHolder {
|
||||
TextView titleView;
|
||||
TextView artistAlbumView;
|
||||
TextView durationGenresView;
|
||||
|
@ -226,5 +240,11 @@ public class MusicVideoListFragment extends AbstractListFragment {
|
|||
|
||||
int musicVideoId;
|
||||
String musicVideoTitle;
|
||||
String artist;
|
||||
String album;
|
||||
int runtime;
|
||||
String genres;
|
||||
int year;
|
||||
String plot;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,8 +115,7 @@
|
|||
android:layout_height="match_parent"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconDownload"
|
||||
android:contentDescription="@string/download"
|
||||
android:visibility="gone"/>
|
||||
android:contentDescription="@string/download"/>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
|
|
Loading…
Reference in New Issue