27

我正在开发的应用程序显示图像网格。当您点击图像时,它会进入详细信息视图。详细信息视图包含一个 ViewPager,它允许您在网格中的每个图像之间滑动。这是通过传递路径列表(包含网格中的每个图像)以及被点击的图像的偏移量来完成的,因此可以将 ViewPager 设置为最初显示该页面。

在 ViewPager 中的当前偏移页面的 Fragment 内进行共享元素转换的最佳方式是什么?网格 (RecyclerView) 图像应在当前页面中展开为全屏图像。我看到了推迟和恢复活动转换的能力,因此应用程序将等待显示共享元素转换,直到从磁盘加载图像。但我希望能够使其动画到视图寻呼机中的正确页面,并在用户返回时退出到当前页面(因为您可以在页面之间滑动)。如果您现在滑动到不同的页面,初始页面就是动画回到网格中的内容。

目前,我为视图寻呼机的 Fragments 中的每个图像分配了一个“image_[index]”格式的转换名称。当我开始详细信息活动时,我使用相同的 transitionName ,索引是偏移量。

与此相关,我还想知道如何使涟漪与长按一起工作。当您更改视图的激活状态时,它似乎取消了涟漪。我想要一个类似于 Gmail 的效果,在长按完成并触发激活状态后,涟漪会重新开始并迅速结束。

4

2 回答 2

35

据我所知(如果我错了,请纠正我),你想要实现的基本上是这样的:假设你有 a MainActivity、 aDetailsActivity和任意一组图像。以MainActivity网格形式DetailsActivity显示一组图像,而以水平方向显示同一组图像ViewPager。当用户在 中选择图像时MainActivity,该图像应从其在网格中的位置过渡到第二个活动中的正确页面ViewPager

我们要解决的问题是“如果用户在里面切换页面DetailsActivity怎么办”?如果发生这种情况,我们希望更改将在返回转换期间使用的共享图像。默认情况下,活动转换框架将使用在进入转换期间使用的共享元素......但是视图寻呼机的页面已经改变,所以显然我们希望以某种方式覆盖这个行为。为此,我们需要SharedElementCallback在您的andMainActivity方法中设置 a并覆盖该方法,如下所示:DetailsActivityonCreate()onMapSharedElements()

private final SharedElementCallback mCallback = new SharedElementCallback() {
    @Override
    public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
        if (mCurrentImagePosition != mOriginalImagePosition) {
            View sharedView = getImageAtPosition(mCurrentImagePosition);
            names.clear();
            sharedElements.clear();
            names.add(sharedView.getTransitionName());
            sharedElements.put(sharedView.getTransitionName(), sharedView);
        }
    }

    /**
     * Returns the image of interest to be used as the entering/returning
     * shared element during the activity transition.
     */
    private View getImageAtPosition(int position) {
        // ...
    }
};

对于更完整的解决方案,我在 GitHub 上创建了一个示例项目,可以实现此效果(在单个 StackOverflow 答案中发布的代码太多)。

于 2014-12-05T17:04:56.090 回答
4

我假设您正在使用片段转换并且您没有在活动之间制作动画。在Activity Transitions和Fragment Transitions中都可以,但是具体代码有点不同。不过,Fragment Transitions 不提供延期。

addSharedElement 采用第二个参数。如果你在调用的时候知道目标fragment中的具体名字,你可以直接选择detailsfragment中的名字来使用。如果您不这样做,您可以选择任何您想要的名称并使用 Fragment 上设置的 SharedElementCallback 重新映射它。

fragment.setEnterSharedElementCallback(new SharedElementCallback() {
    @Override
    public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
        sharedElements.put("detailView", mTargetDetailView);
    }
});

如果它在返回的路上不匹配,则会进行相同的调用以重新映射它。这很可能同时出现在调用片段和被调用片段中——在调用片段上,您使用 setExitSharedElementCallback。我希望您的应用程序会出现这种情况。

同样,在 Activity Transitions 中,您设置相同的 SharedElementCallback 并使用相同的映射,但您在 Activity 上执行此操作。

于 2014-12-05T01:11:07.887 回答