Intent myIntent = new Intent(getActivity(), EnlargeActivity.class);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(getActivity(),
imageView,
ViewCompat.getTransitionName(imageView));
startActivity(myIntent, options.toBundle());
当完成活动时,我正在更新包含viewpager的活动中的视图及其名称,但它会闪烁:
public void finishAfterTransition() {
setEnterSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
// Clear all current shared views and names
names.clear();
sharedElements.clear();
ViewGroup viewGroup = (ViewGroup) viewPagerDetail.getAdapter()
.instantiateItem(viewPagerDetail, viewPagerDetail.getCurrentItem());
if (viewGroup == null) {
return;
}
// Map the first shared element name to the child ImageView.
sharedElements.put(viewGroup.findViewById(R.id.img).getTransitionName(), viewGroup.findViewById(R.id.img));
// setExitSharedElementCallback((SharedElementCallback) this);
}
});
super.finishAfterTransition();
基本上,Android使用预定义的视图
和transitionname
开始转换,并自动将相同的属性用于返回转换。当你在ViewPager中改变你的聚焦视图时,Android并不知道这一点,而是在返回的路上保持上一个的转换。因此您需要通知Android有关更改:
Activity2
返回之前,使用SetEnterShareDelementCallback
将TransitionName
和视图
更改为新的。Activity1
完成呈现AddonPredrawListener
。在最终实现中有点复杂。但是您可以查看我的示例代码https://github.com/tamhuynhit/photogally。我试图实现从许多简单节到复杂节的共享元素转换。您的问题出现在级别3
中,并在级别4
中解决。
更新1:工作流程
下面是我如何在代码中实现它:
>
在Activity2中重写FinishafterTransition
,并调用SetEnterShareDelementCallback
方法在ViewPager中重新映射当前选定的项。另外,调用setresult
将新选择的索引传递回此处的上一个活动。
@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void finishAfterTransition() {
setEnterSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
View selectedView = getSelectedView();
if (selectedView == null)
return;
// Clear all current shared views and names
names.clear();
sharedElements.clear();
// Store new selected view and name
String transitionName = ViewCompat.getTransitionName(selectedView);
names.add(transitionName);
sharedElements.put(transitionName, selectedView);
setExitSharedElementCallback((SharedElementCallback) null);
}
});
Intent intent = new Intent();
intent.putExtra(PHOTO_FOCUSED_INDEX, mCurrentIndex);
setResult(RESULT_PHOTO_CLOSED, intent);
super.finishAfterTransition();
}
编写一个自定义的ShareElementCallback
,这样我就可以在知道要使用哪个视图
之前设置回调。
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static class CustomSharedElementCallback extends SharedElementCallback {
private View mView;
/**
* Set the transtion View to the callback, this should be called before starting the transition so the View is not null
*/
public void setView(View view) {
mView = view;
}
@Override
public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
// Clear all current shared views and names
names.clear();
sharedElements.clear();
// Store new selected view and name
String transitionName = ViewCompat.getTransitionName(mView);
names.add(transitionName);
sharedElements.put(transitionName, mView);
}
}
在Activity1中重写onActivityReenter
,从结果Intent
中获取选定的索引。设置SetExitShareDelementCallback
以在转换开始时重新映射新的选定视图
。调用SupportPostponeEntertransition
以延迟一点,因为此时可能无法呈现新的视图
。使用GetViewTreeObserver().AddonPredrawListener
侦听布局更改,根据所选索引找到正确的视图
并继续转换SupportStartPostponedEnterTransition
。
@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void onActivityReenter(int resultCode, Intent data) {
if (resultCode != LevelFourFullPhotoActivity.RESULT_PHOTO_CLOSED || data == null)
return;
final int selectedIndex = data.getIntExtra(LevelFourFullPhotoActivity.PHOTO_FOCUSED_INDEX, -1);
if (selectedIndex == -1)
return;
// Scroll to the new selected view in case it's not currently visible on the screen
mPhotoList.scrollToPosition(selectedIndex);
final CustomSharedElementCallback callback = new CustomSharedElementCallback();
getActivity().setExitSharedElementCallback(callback);
// Listen for the transition end and clear all registered callback
getActivity().getWindow().getSharedElementExitTransition().addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {}
@Override
public void onTransitionPause(Transition transition) {}
@Override
public void onTransitionResume(Transition transition) {}
@Override
public void onTransitionEnd(Transition transition) {
removeCallback();
}
@Override
public void onTransitionCancel(Transition transition) {
removeCallback();
}
private void removeCallback() {
if (getActivity() != null) {
getActivity().getWindow().getSharedElementExitTransition().removeListener(this);
getActivity().setExitSharedElementCallback((SharedElementCallback) null);
}
}
});
// Pause transition until the selected view is fully drawn
getActivity().supportPostponeEnterTransition();
// Listen for the RecyclerView pre draw to make sure the selected view is visible,
// and findViewHolderForAdapterPosition will return a non null ViewHolder
mPhotoList.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mPhotoList.getViewTreeObserver().removeOnPreDrawListener(this);
RecyclerView.ViewHolder holder = mPhotoList.findViewHolderForAdapterPosition(selectedIndex);
if (holder instanceof ViewHolder) {
callback.setView(((ViewHolder) holder).mPhotoImg);
}
// Continue the transition
getActivity().supportStartPostponedEnterTransition();
return true;
}
});
}
更新2:getSelectedItem
若要从视图页获取选定视图,请不要使用getchildat
,否则获取的视图是错误的,请使用findviewwithtag
在PagerAdapter.InstantiateItem
中,将position用作每个视图的标记:
@Override
public View instantiateItem(ViewGroup container, int position) {
// Create the View
view.setTag(position)
// ...
}
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
mSelectedIndex = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
private View getSelectedView() {
try {
return mPhotoViewPager.findViewWithTag(mSelectedIndex);
} catch (IndexOutOfBoundsException | NullPointerException ex) {
return null;
}
}
我一直在尝试实现这个共享元素转换,并在单击转换时不断出现“java.lang.IllegalArgumentException:共享元素不能为null”错误。请帮忙。 这是下面给出的MainActive onCreate方法。请检查我的代码。 这是recyclerView的onClickListener。 图像的过渡名称相同。这里的bug修复在使用共享元素的活动转换中出现问题并不是问题所在。 我卡
我正在实现一个gallery应用程序,它有一个片段,其中包含一个带有图像的RecyclerView,单击一个图像,我会转到ViewPager循环浏览图像 目前,我正试图实现像本视频中那样的入门动画。问题是动画不起作用,我显然遗漏了一些东西(只是显示与转换相关的代码): 查看页面: GridAdapter: 在MainActivity中,我在onClick中实例化ViewPagerFragment:
我在Lollipop上的共享元素转换中看到了奇怪的事情。共享元素在开始动画之前闪烁(请看视频https://www.youtube.com/watch?v=DCoyyC_S-9A) 我不知道为什么会这样。但是,当我添加
我希望采用Glide库来代替通用图像加载器,但在共享元素转换方面遇到了问题。 在我的简单沙盒中,我使用UIL创建了以下过渡:https://dl.dropboxusercontent.com/u/97787025/device-2015-06-18-113333.mp4 非常简单,而且效果很好。但当我使用Glide时,它看起来不太好看:https://dl.dropboxusercontent.c
我已经研究这个问题几个星期了,但我仍然无法解决这个问题。 我有一个CardView,它包含一个带有ImageView的线性布局。 没有那个半径共享元素过渡可以无缝工作。但是,当我将半径(app: cardCornerRadius="25dp")添加到CardView时,共享元素过渡看起来很难看,因为它首先删除半径,然后开始动画。 第一种方法:ObjectAnimator 我创建ObjectAnim
我点击了recyclerview的项目,打开了一个共享元素转换的活动,如下所示: 在活动中,它有视图寻呼机: 在扩展FragmentStatePagerAdapter的viewpager适配器中,返回一个片段ProductDetailViewPagerFraack,该片段具有一个Imageview和im加载图像,如:(MainActivity.position是回收器视图的位置)