Java 共享元素转换未正确退出
我有一个片段,我正在从中启动带有共享元素转换的活动,其中包含viewpager,enter转换工作正常,但当我在view pager中滚动并完成转换时,共享图像来自左侧,这是不需要的,它应该将自身重新定位到启动位置,下面是我的代码:Java 共享元素转换未正确退出,java,android,android-animation,android-transitions,shared-element-transition,Java,Android,Android Animation,Android Transitions,Shared Element Transition,我有一个片段,我正在从中启动带有共享元素转换的活动,其中包含viewpager,enter转换工作正常,但当我在view pager中滚动并完成转换时,共享图像来自左侧,这是不需要的,它应该将自身重新定位到启动位置,下面是我的代码: Intent myIntent = new Intent(getActivity(), EnlargeActivity.class); ActivityOptionsCompat options = ActivityOptionsCompa
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();
这实际上是一种默认行为,我在SharedElementTransitions中苦苦挣扎,但我有嵌套的片段。我从最近的一篇文章中得到了我的解决方案,它显示了一个带有RecyclerView的实现,我想您已经有了。简言之,解决方案是覆盖onLayoutChange:
这是,您也可以在上找到该项目。这实际上是一种默认行为,我一直在努力实现SharedElementTransitions,但我有嵌套的片段。我从最近的一篇文章中得到了我的解决方案,它显示了一个带有RecyclerView的实现,我想您已经有了。简言之,解决方案是覆盖onLayoutChange:
这是,您也可以在上找到项目。基本上,Android使用预定义的视图和transitionName启动转换,并自动为返回转换使用相同的属性。当您在ViewPager中更改聚焦视图时,Android不知道这一点,并在返回的过程中保持前一个视图的转换。因此,您需要将这些更改告知Android: 重新映射转换属性:在从Activity2返回之前,使用setEnterSharedElementCallback将转换名称和视图更改为新的。 等待Activity1完成呈现addOnPreDrawListener。 最后的实现有点复杂。但您可以查看我的示例代码。我尝试实现从许多简单部分到复杂部分的共享元素转换。 你的问题出现在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();
}
重写Activity1中的ActivityReeenter,从结果意图中获取所选索引。设置setExitSharedElementCallback,以便在转换开始时重新映射新的选定视图。调用SupportPostpuneEntertTransition可稍微延迟一点,因为此时可能无法呈现新视图。使用getViewTreeObserver.addOnPreDrawListener来侦听布局更改,通过所选索引找到正确的视图,然后继续转换supportStartPostponedEnterTransition
更新2:getSelectedItem
若要从ViewPager获取所选视图,请不要使用getChildAt,否则会得到错误的视图,请改用findViewWithTag
在PagerAdapter.InstanceItem中,将位置用作每个视图的标记:
@Override
public View instantiateItem(ViewGroup container, int position) {
// Create the View
view.setTag(position)
// ...
}
收听onPageSelected事件以获取所选索引:
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) {
}
});
调用getSelectedView以按所选索引获取当前视图
private View getSelectedView() {
try {
return mPhotoViewPager.findViewWithTag(mSelectedIndex);
} catch (IndexOutOfBoundsException | NullPointerException ex) {
return null;
}
}
基本上,Android使用预定义的视图和transitionName启动转换,并自动为返回转换使用相同的属性。当您在ViewPager中更改聚焦视图时,Android不知道这一点,并在返回的过程中保持前一个视图的转换。因此,您需要将这些更改告知Android: 重新映射转换属性:在从Activity2返回之前,使用setEnterSharedElementCallback将转换名称和视图更改为新的。 等待Activity1完成呈现addOnPreDrawListener。 最后的实现有点复杂。但您可以查看我的示例代码。我尝试实现从许多简单部分到复杂部分的共享元素转换。 你的问题出现在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();
}
重写Activity1中的ActivityReeenter,从结果意图中获取所选索引。设置setExitSharedElementCallback,以便在转换开始时重新映射新的选定视图。调用SupportPostpuneEntertTransition可稍微延迟一点,因为此时可能无法呈现新视图。使用getViewTreeObserver.addOnPreDrawListener来侦听布局更改,通过所选索引找到正确的视图,然后继续转换supportStartPostponedEnterTransition
更新2:getSelectedIt
em
若要从ViewPager获取所选视图,请不要使用getChildAt,否则会得到错误的视图,请改用findViewWithTag
在PagerAdapter.InstanceItem中,将位置用作每个视图的标记:
@Override
public View instantiateItem(ViewGroup container, int position) {
// Create the View
view.setTag(position)
// ...
}
收听onPageSelected事件以获取所选索引:
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) {
}
});
调用getSelectedView以按所选索引获取当前视图
private View getSelectedView() {
try {
return mPhotoViewPager.findViewWithTag(mSelectedIndex);
} catch (IndexOutOfBoundsException | NullPointerException ex) {
return null;
}
}
我使用了同一篇文章,从中我学到了很多,但情况不同,我使用片段中的共享元素打开活动,当我完成该活动时,效果很好,但当我在活动中添加viewpager,然后完成活动时,其行为类似于转换名称的设置不正确,它来自右手边,当没有viewpager时,图像像放大一样笔直出现,像缩小一样返回,这是需要的。你能知道当我在活动和结束中添加viewpager时发生了什么吗activity@blackHawk因此,如果您有viewpager,请打开活动,在不滑动viewpager的情况下关闭它,它仍会执行相同的操作?在“活动”中添加viewpager会导致差异,无论我是否交换not@blackHawk正如您所说,这可能是由于转换名称,您的viewpager包含哪些内容?您确定这些名称是唯一的吗?我遇到了一个问题,我使用了一个带有显示类似数据的片段的表格布局,所以我不得不在我的转换名称中添加片段编号来区分它们。我使用了同一篇文章,从中我学到了很多,但这里的情况不同,我使用片段中的共享元素开始活动,当我完成该活动时,它工作正常,但当我在活动中添加viewpager,然后完成活动时,其行为类似于转换名称的设置不正确,它来自右手边,当没有viewpager时,图像像放大一样笔直出现,像缩小一样返回,这是需要的。你能知道当我在活动和结束中添加viewpager时发生了什么吗activity@blackHawk因此,如果您有viewpager,请打开活动,在不滑动viewpager的情况下关闭它,它仍会执行相同的操作?在“活动”中添加viewpager会导致差异,无论我是否交换not@blackHawk正如您所说,这可能是由于转换名称,您的viewpager包含哪些内容?您确定这些名称是唯一的吗?我遇到了一个问题,我使用了一个带有显示类似数据的片段的表格布局,所以我必须在我的转换名称中添加片段编号来区分它们。你是对的,转换名称设置不正确,这就是问题发生的原因,我把你的方法系在应该适用的地方setEnterSharedElementCallback@blackHawk报纸上说你read@blackHawk我在上面的回答中添加了一个更新,以进一步解释我的问题code@LieForBananas是的,试着多了解一点,你是对的,转换名称设置不正确,这就是问题发生的原因,我把你的方法系在应该适用的地方setEnterSharedElementCallback@blackHawk报纸上说你read@blackHawk我在上面的回答中添加了一个更新,以进一步解释我的问题code@LieForBananas是的,试着多了解一点,