Implemented fix for movie and album shared element transitions

When shared element view is not visible on returning, the return shared
element transition starts off screen. This looks odd and we now simply
do not perform the shared element transition when the shared element is
not visible.
This commit is contained in:
Martijn Brekhof 2015-12-10 16:44:42 +01:00
parent fce521a9bb
commit f84ccaf02a
5 changed files with 113 additions and 17 deletions

View File

@ -669,6 +669,18 @@ public class AlbumDetailsFragment extends Fragment
}
}
/**
* Returns the shared element if visible
* @return View if visible, null otherwise
*/
public View getSharedElement() {
if (UIUtils.isViewInBounds(mediaPanel, mediaPoster)) {
return mediaPoster;
}
return null;
}
/**
* Album details query parameters.
*/

View File

@ -201,7 +201,7 @@ public class MovieDetailsFragment extends AbstractDetailsFragment
// Pad main content view to overlap with bottom system bar
// UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true);
// mediaPanel.setClipToPadding(false);
return root;
}
@ -628,6 +628,18 @@ public class MovieDetailsFragment extends AbstractDetailsFragment
}
}
/**
* Returns the shared element if visible
* @return View if visible, null otherwise
*/
public View getSharedElement() {
if (UIUtils.isViewInBounds(mediaPanel, mediaPoster)) {
return mediaPoster;
}
return null;
}
/**
* Movie details query parameters.
*/

View File

@ -26,12 +26,16 @@ import android.transition.Transition;
import android.transition.TransitionInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import org.xbmc.kore.R;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.Utils;
import java.util.List;
import java.util.Map;
/**
* Controls the presentation of Movies information (list, details)
* All the information is presented by specific fragments
@ -48,6 +52,8 @@ public class MoviesActivity extends BaseActivity
private NavigationDrawerFragment navigationDrawerFragment;
private boolean clearSharedElements;
@TargetApi(21)
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -76,6 +82,18 @@ public class MoviesActivity extends BaseActivity
movieListFragment.setReenterTransition(fade);
movieListFragment.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;
}
}
};
movieListFragment.setExitSharedElementCallback(seCallback);
}
getSupportFragmentManager()
.beginTransaction()
@ -189,9 +207,27 @@ public class MoviesActivity extends BaseActivity
// Set up transitions
if (Utils.isLollipopOrLater()) {
MovieDetailsFragment movieDetailsFragment = MovieDetailsFragment.newInstance(vh);
final MovieDetailsFragment movieDetailsFragment = MovieDetailsFragment.newInstance(vh);
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
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 (movieDetailsFragment.isVisible()) {
View sharedView = movieDetailsFragment.getSharedElement();
if (sharedView == null) { // shared element not visible
clearSharedElements = true;
}
}
}
};
movieDetailsFragment.setEnterSharedElementCallback(seCallback);
movieDetailsFragment.setEnterTransition(TransitionInflater
.from(this)
.inflateTransition(R.transition.media_details));

View File

@ -26,11 +26,15 @@ import android.transition.Transition;
import android.transition.TransitionInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import org.xbmc.kore.R;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.Utils;
import java.util.List;
import java.util.Map;
/**
* Controls the presentation of Music information (list, details)
* All the information is presented by specific fragments
@ -62,6 +66,8 @@ public class MusicActivity extends BaseActivity
private NavigationDrawerFragment navigationDrawerFragment;
private boolean clearSharedElements;
@TargetApi(21)
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -255,6 +261,18 @@ public class MusicActivity extends BaseActivity
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
// Setup animations
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) {
if (clearSharedElements) {
names.clear();
sharedElements.clear();
clearSharedElements = false;
}
}
};
albumListFragment.setExitSharedElementCallback(seCallback);
//Fade added to prevent shared element from disappearing very shortly at the start of the transition.
Transition fade = TransitionInflater
.from(this)
@ -281,11 +299,29 @@ public class MusicActivity extends BaseActivity
selectedAlbumTitle = vh.albumTitle;
// Replace list fragment
AlbumDetailsFragment albumDetailsFragment = AlbumDetailsFragment.newInstance(vh);
final AlbumDetailsFragment albumDetailsFragment = AlbumDetailsFragment.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 (albumDetailsFragment.isVisible()) {
View sharedView = albumDetailsFragment.getSharedElement();
if (sharedView == null) { // shared element not visible
clearSharedElements = true;
}
}
}
};
albumDetailsFragment.setEnterSharedElementCallback(seCallback);
albumDetailsFragment.setEnterTransition(TransitionInflater
.from(this)
.inflateTransition(R.transition.media_details));

View File

@ -122,16 +122,16 @@ public class UIUtils {
if ((imageWidth) > 0 && (imageHeight > 0)) {
hostManager.getPicasso()
.load(hostManager.getHostInfo().getImageUrl(imageUrl))
.resize(imageWidth, imageHeight)
.centerCrop()
.into(imageView);
.load(hostManager.getHostInfo().getImageUrl(imageUrl))
.resize(imageWidth, imageHeight)
.centerCrop()
.into(imageView);
} else {
hostManager.getPicasso()
.load(hostManager.getHostInfo().getImageUrl(imageUrl))
.fit()
.centerCrop()
.into(imageView);
.load(hostManager.getHostInfo().getImageUrl(imageUrl))
.fit()
.centerCrop()
.into(imageView);
}
}
@ -191,11 +191,11 @@ public class UIUtils {
}
char charAvatar = TextUtils.isEmpty(str) ?
' ' : str.charAt(0);
' ' : str.charAt(0);
avatarColorsIdx = TextUtils.isEmpty(str) ? 0 :
Math.max(Character.getNumericValue(str.charAt(0)) +
Character.getNumericValue(str.charAt(str.length() - 1)) +
str.length(), 0) % characterAvatarColors.length();
Math.max(Character.getNumericValue(str.charAt(0)) +
Character.getNumericValue(str.charAt(str.length() - 1)) +
str.length(), 0) % characterAvatarColors.length();
int color = characterAvatarColors.getColor(avatarColorsIdx, 0xff000000);
// avatarColorsIdx = randomGenerator.nextInt(characterAvatarColors.length());
return new CharacterDrawable(charAvatar, color);
@ -318,7 +318,7 @@ public class UIUtils {
@Override
public void run() {
NetUtils.sendWolMagicPacket(hostInfo.getMacAddress(),
hostInfo.getAddress(), hostInfo.getWolPort());
hostInfo.getAddress(), hostInfo.getWolPort());
}
}).start();
Toast.makeText(context, R.string.wol_sent, Toast.LENGTH_SHORT).show();
@ -423,7 +423,7 @@ public class UIUtils {
// Show the animation
int endRadius = Math.max(exitTransitionView.getHeight(), exitTransitionView.getWidth());
Animator exitAnim = ViewAnimationUtils.createCircularReveal(exitTransitionView,
centerX, centerY, 0, endRadius);
centerX, centerY, 0, endRadius);
exitAnim.setDuration(200);
exitAnim.addListener(new Animator.AnimatorListener() {