Android 确定动画后ImageView共享元素的最终大小

Android 确定动画后ImageView共享元素的最终大小,android,animation,android-animation,android-transitions,shared-element-transition,Android,Animation,Android Animation,Android Transitions,Shared Element Transition,我有许多共享元素,通过ActivityOptions.makeSceneTransitionAnimation在两个活动之间转换。当我进入第二个活动时,我想确定ImageView的最终目标大小,以便设置ImageView的适当宽度。我相信这样做将允许它右边的对象(也是一个共享元素)平稳过渡 ImageView是一个具有固定高度和wrap\u内容宽度的fitStart缩放类型。图像将动态加载,并从第一个活动缩小到第二个活动,因此我不知道最终宽度。在转换开始之前,我想设置ImageView的Layo

我有许多共享元素,通过
ActivityOptions.makeSceneTransitionAnimation
在两个活动之间转换。当我进入第二个活动时,我想确定
ImageView
的最终目标大小,以便设置
ImageView
的适当宽度。我相信这样做将允许它右边的对象(也是一个共享元素)平稳过渡

ImageView
是一个具有固定高度和
wrap\u内容
宽度的
fitStart
缩放类型。图像将动态加载,并从第一个活动缩小到第二个活动,因此我不知道最终宽度。在转换开始之前,我想设置
ImageView
LayoutParams
宽度,以匹配转换结束后的最终宽度

当前,此
ImageView
wrap\u content
属性会导致其右侧的元素不知道其最终静止位置,因此在返回并降落到正确位置之前,它会向右离开屏幕

这是动画的gif。第一个元素是正确设置动画的
ImageView
,第二个元素是
ImageView
右侧的按钮:

请注意,当第二个活动返回到第一个活动时,第二个元素平稳地过渡回屏幕左侧,因为结束位置已知

当我给
ImageView
一个特定的宽度,比如
100dp
,而不是
wrap\u content
(然后在转换完成后将其更改回
wrap\u content
),第二个元素会更平滑地移动到其最终的静止位置,但由于
ImageView
将被动态加载和缩放,我事先不知道XML中图像的真实宽度,因此在转换后,当我将第二个元素更改为
wrap\u content
时,它总是会突然移动

因此,我想确定
ImageView
的目标宽度,并在第二个活动中开始转换之前以编程方式设置它,以便第二个元素知道它需要向左走多远。我尝试过使用
ViewTreeObserver
TransitionValues
但是我不知道如何获得ImageView转换到的最终宽度

在第二个活动的
onCreate
中,我是否可以调用一些东西来确定转换后ImageView的最终宽度?


编辑

我在中尝试了该解决方案,但它报告了ImageView的开始宽度,而不是它转换到的最终宽度。以下是我正在切换的两项活动的布局,仅供参考:

请注意,我正在移动和缩小ImageView

我调整了答案的代码,因为我没有使用支持库,必须在
onPreDraw()调用中转到
imageView.getViewTreeObserver()
,以避免出现
IllegalStateException

postponeEnterTransition();

final ImageView imageView = (ImageView) findViewById(R.id.image_view);
final ViewGroup.LayoutParams imageViewLayoutParams = imageView.getLayoutParams();
final ViewTreeObserver viewTreeObserver = imageView.getViewTreeObserver();

viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
  @Override public boolean onPreDraw() {
    imageView.getViewTreeObserver().removeOnPreDrawListener(this);

    // You can acquire the width here
    logoLayoutParams.width = imageView.getWidth();
    Log.i(TAG, "width is " + imageViewLayoutParams.width);
    imageView.setLayoutParams(imageViewLayoutParams);
    // `imageView` has been laid out, but not yet been drawn
    startPostponedEnterTransition();
    return true;
  }
});
日志报告宽度为998,这是活动1中imageView的较大尺寸(转换前的起始尺寸)。所以第二个元素仍然在屏幕上飞走

现在我有了这个代码,我可以使用较大图像的纵横比信息来计算较小图像的最终宽度,因为我知道最终高度,但是
fitStart
scaleType可以保证吗


如果安卓能告诉我共享元素目标的最终大小,那就太好了。

情况是这样的:如果你在第二个活动中将资源从
@drawable/first\u element
更改为
@drawable/first\u element\u thumb
,你将不会再经历这种行为。缺点是,每次转换开始时,您都会看到一个小故障,这是因为在转换开始之前,可绘制图像正从高分辨率更改为低分辨率

以下是300毫秒动画时间:

以下是5000毫秒动画时间:


如果您希望转换不会出现该问题,那么解决方案是在转换视图时开始从高分辨率可绘制转换,并将该可绘制转换为低分辨率。你可以在他的文章中看到对这一特征的描述。您将编写自定义转换类,如。

此图像来自何处?如果它是您的后端,您可以控制它,那么我建议您将图像的大小与图像url一起传递。在此信息中,您可以定义
ImageView
所需的纵横比,因此它具有固定的宽度和高度。谢谢。不过我还是有个问题。编辑我的问题。如果你在github发布了一个简单的项目,我会看一看。下面是一个简单的例子:我意识到在创建这个项目时,我也会在转换结束后将大图像替换为缩略图,以便显示更好的图像版本。如果我不这样做,并将图像设置回wrap_内容,它实际上保持为较大图像的全宽,即使在过渡之后也是如此。所以也许我不应该把它设置回包装内容。但问题仍然是,我正在经历一点痛苦重新构建最终宽度(包括较小图像的右边缘)。非常感谢您查看代码并帮助解释。我甚至没有想到在过渡后将其更改为缩略图会产生如此大的影响。