Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 共享元素转换未正确退出_Java_Android_Android Animation_Android Transitions_Shared Element Transition - Fatal编程技术网

Java 共享元素转换未正确退出

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

我有一个片段,我正在从中启动带有共享元素转换的活动,其中包含viewpager,enter转换工作正常,但当我在view pager中滚动并完成转换时,共享图像来自左侧,这是不需要的,它应该将自身重新定位到启动位置,下面是我的代码:

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是的,试着多了解一点,