Reputation: 1548
I am trying to create a "simple" image shared element transition between a recycler view item (Activity A) & a view pager (Activity B). I have managed to smoothen everything but it seems that no matter how I set my exit/reenter/enter/return transitions the transition back from B to A, when the shared element is settled back, is flickering. And by flickering I mean the entire screen.
I am using AppCompat themes & ActivityCompat methods with combinations of PreDrawListeners in both A (reenter) and B (when image is set using Glide).
Heres Activity A related code:
private Bundle mReenterState;
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override protected void initActivityTransitions() {
super.initActivityTransitions();
getWindow().setSharedElementsUseOverlay(false);
setExitSharedElementCallback(mCallback);
}
private final SharedElementCallback mCallback = new SharedElementCallback() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (mReenterState != null) {
int startingSelection = mReenterState.getInt(DefinesGlobal.KEY_STARTING_INDEX);
int currentSelection = mReenterState.getInt(DefinesGlobal.KEY_CURRENT_INDEX);
if (startingSelection != currentSelection) {
String newTransitionName = mHotel.getDetail().getHotelImagesGallery().get(currentSelection);
View newSharedElement = mContentView.getGalleryView().getRecyclerViewPager()
.getLayoutManager().findViewByPosition(currentSelection);
if (newSharedElement != null) {
names.clear();
names.add(newTransitionName);
sharedElements.clear();
sharedElements.put(newTransitionName, newSharedElement);
}
}
mReenterState = null;
} else {
// If mReenterState is null, then the activity is exiting.
View navigationBar = findViewById(android.R.id.navigationBarBackground);
View statusBar = findViewById(android.R.id.statusBarBackground);
if (navigationBar != null) {
names.add(navigationBar.getTransitionName());
sharedElements.put(navigationBar.getTransitionName(), navigationBar);
}
if (statusBar != null) {
names.add(statusBar.getTransitionName());
sharedElements.put(statusBar.getTransitionName(), statusBar);
}
}
}
};
@Override public void onActivityReenter(int resultCode, Intent data) {
super.onActivityReenter(resultCode, data);
mReenterState = new Bundle(data.getExtras());
int startingSelection = mReenterState.getInt(DefinesGlobal.KEY_STARTING_INDEX);
int currentSelection = mReenterState.getInt(DefinesGlobal.KEY_CURRENT_INDEX);
if (startingSelection != currentSelection) {
mContentView.getGalleryView().getRecyclerViewPager().scrollToPosition(currentSelection);
}
ActivityCompat.postponeEnterTransition(this);
mContentView.getGalleryView().getRecyclerViewPager().getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mContentView.getGalleryView().getRecyclerViewPager().getViewTreeObserver().removeOnPreDrawListener(this);
mContentView.getGalleryView().getRecyclerViewPager().requestLayout();
ActivityCompat.startPostponedEnterTransition(ViewModelHotelDetailsActivity.this);
return true;
}
});
}
Heres Activity B related code.
private boolean mIsReturning;
@Override public void finishAfterTransition() {
mIsReturning = true;
Intent data = new Intent();
data.putExtra(DefinesGlobal.KEY_CURRENT_INDEX, mCurrentSelection);
data.putExtra(DefinesGlobal.KEY_STARTING_INDEX, mStartingSelection);
setResult(RESULT_OK, data);
super.finishAfterTransition();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override protected void initActivityTransitions() {
super.initActivityTransitions();
ActivityCompat.postponeEnterTransition(this);
setEnterSharedElementCallback(mCallback);
}
private final SharedElementCallback mCallback = new SharedElementCallback() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
if (mIsReturning) {
ViewModelFullSizeGalleryFragment fragment =
((FullSizeGalleryPagerAdapter) mPager.getAdapter()).getCurrent();
ImageView sharedElement = fragment.getImageView();
if (sharedElement == null) {
names.clear();
sharedElements.clear();
} else if (mStartingSelection != mCurrentSelection) {
names.clear();
names.add(sharedElement.getTransitionName());
sharedElements.clear();
sharedElements.put(sharedElement.getTransitionName(), sharedElement);
}
}
}
};
Activity B view pager fragment:
ublic class ViewModelFullSizeGalleryFragment extends ViewModelBaseFragment {
@Override protected int getLayoutId() {
return R.layout.view_model_fragment_full_size_gallery;
}
@Bind(R.id.full_size_image_view) ImageView mImageView;
public static ViewModelFullSizeGalleryFragment newInstance(String url, int position, int
target) {
ViewModelFullSizeGalleryFragment fragment = new ViewModelFullSizeGalleryFragment();
fragment.setUrl(url);
fragment.setIndexAndTarget(position, target);
return fragment;
}
private String mUrl;
private int mPosition;
private int mTarget;
public void setUrl(String url) {
mUrl = url;
}
public void setIndexAndTarget(int position, int target) {
mPosition = position;
mTarget = target;
}
@Override protected void initViewModel(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mImageView.setTransitionName(mUrl);
}
Glide.with(getContext())
.load(mUrl)
.transform(new HotelDetailsImageTransformation(getContext(),
LMTApplication.mWidth))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.skipMemoryCache(true)
.error(R.drawable.ic_nopic)
.into(new SimpleTarget<GlideDrawable>() {
@Override public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
if (mImageView != null && resource != null) {
mImageView.setImageDrawable(resource);
mImageView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override public boolean onPreDraw() {
mImageView.getViewTreeObserver().removeOnPreDrawListener(this);
if (mTarget == mPosition)
((ISharedElementCallback) getContext()).onViewReadyForTransition();
return true;
}
});
}
}
});
}
@Override public void onBackPressed() {
//!! Not used.
}
public interface ISharedElementCallback {
void onViewReadyForTransition();
}
public ImageView getImageView() {
return mImageView;
}
Havent figured out what actually does the flickering... Any help will be grand. Thanks.
Also. If its any help theres a map fragment behind the Activity A recycler view if its any help.
Upvotes: 0
Views: 1759
Reputation: 404
Does setting android:windowSharedElementsUseOverlay
(inside your Activity's XML theme file) to false solve your problem?
Upvotes: 4