Zoomlayout: ZoomLayout 的宽度/高度的变化不会更新子转换以保持中心裁剪工作

创建于 2020-10-16  ·  5评论  ·  资料来源: natario1/ZoomLayout

描述错误

  • 库版本:1.8.0
  • 可在官方演示应用程序中重现:是
  • 设备/安卓版本: Pixel 3,API 29

我正在使用 ZoomLayout 来显示纵向/横向图像。 我已禁用 Zoom 和 OverScroll。 我仅将水平和垂直平移与 CenterCrop 一起使用。 正如预期的那样,一次只能执行一个方向平移(因为禁用了缩放)。 这允许我显示图像的一部分,而另一部分可以使用 Pan 查看。

据我所知, centercrop 的工作原理是将containerHeight对齐childHeightcontainerWidth对齐childWidth 。 对? 想象一下将风景/肖像图像加载到方形 ImageView 中。 对于横向图像, childHeight将与containerHeight对齐以执行 centercrop,现在可以水平执行 pan。 同样,对于纵向图像,可以垂直执行平移。

这工作正常。

但是,如果我像这样更改 ZoomLayout 的宽度/高度,则转换不会应用于子视图。

val layoutParams = zoomLayout.layoutParams
layoutParams.width = layoutParams.width + changedWidth
layoutParams.height = layoutParams.height + changedHeight
zoomLayout.layoutParams = layoutParams

再现

重现行为的步骤,可能在演示应用程序中:

  1. 禁用缩放和过度滚动。
  2. 启用水平和垂直平移。
  3. 在 XML 中的 ZoomLayout 中放置一个子视图。 保持宽度/高度来包装内容。
  4. 添加一个长的风景可绘制对象。 用 780 x 180 测试。
  5. 将此 drawable 设置为 XML 中 ZoomLayout 中子视图的背景。
  6. 运行,水平执行平移。
  7. 使用按钮增加 ZoomLayout 的高度。 不执行对 child 的转换。

预期行为

当容器高度发生变化时,会应用子变换来保持 CenterCrop。

XML 布局(扩展 ZoomLayout)

init {
    setHorizontalPanEnabled(true)
    setVerticalPanEnabled(true)

    setOverScrollHorizontal(false)
    setOverScrollVertical(false)

    setAlignment(Alignment.TOP or Alignment.LEFT)
    setHasClickableChildren(true)
    setTransformation(
        ZoomApi.TRANSFORMATION_CENTER_CROP,
        ZoomApi.TRANSFORMATION_GRAVITY_AUTO
    )

    setZoomEnabled(false)
}

截图

Screenshot
Screenshot

日志

推出

I/ZoomLayout: setHasClickableChildren: old: false new: false
I/ZoomLayout: setHasClickableChildren: old: false new: true

加载可在孩子上绘制的水平背景。

W/ZoomEngine: onMatrixSizeChanged: firstTime: true oldZoom: NaN transformation: 1 transformationZoom: 0.0
I/ZoomEngine: computeTransformationZoom centerCrop scaleX: 1.0042135 scaleY: 5.860656
I/ZoomEngine: onMatrixSizeChanged: newTransformationZoom: 5.860656 newRealZoom: 5.8606563 newZoom: 1.0000001

使用上面的代码增加 ZoomLayout 高度。

W/ZoomEngine: onMatrixSizeChanged: firstTime: false oldZoom: 5.8606563 transformation: 1 transformationZoom: 5.860656
I/ZoomEngine: computeTransformationZoom centerCrop scaleX: 1.0042135 scaleY: 6.2704916
I/ZoomEngine: onMatrixSizeChanged: newTransformationZoom: 6.2704916 newRealZoom: 5.8606563 newZoom: 0.93464065

Child 不会被转换以保持 centercrop 功能。

APK

如果需要,将提供,但非常易于使用的复制步骤。

enhancement discussion

最有用的评论

我喜欢它现在的工作方式,容器大小可能因多种原因而改变,如果内容已经缩放/平移,我认为我们不应该重新应用转换。 你应该能够像这样实现你想要的:

zoomLayout.layoutParams = layoutParams
zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)

或者像这样

zoomLayout.layoutParams = layoutParams
zoomLayout.post {
    zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)
}

我们可以使用 syncTransformation() 函数或类似的东西使这更容易

所有5条评论

我使用下面的代码来解决这个问题。

val layoutParams = zoomLayout.layoutParams
layoutParams.width = layoutParams.width + changedWidth
layoutParams.height = layoutParams.height + changedHeight
zoomLayout.layoutParams = layoutParams

zoomLayout.engine.setContainerSize(
    layoutParams.width.toFloat(),
    layoutParams.height.toFloat(),
    applyTransformation = false // not applying transformation
)

而且,ZoomLayout 的onGlobalLayout()另一个变化

engine.setContentSize(
    child.width.toFloat(), 
    child.height.toFloat(),
    applyTransformation = true // <-- this change
)

这样做对我有帮助。 子项与父项正确对齐以保持中心裁剪功能。 但是,这个代码产生了#185 问题。 显然,现在我知道 Pan 重置的原因(提示#global-layout)。

因此,我仍在寻找一种方法来告诉 ZoomLayout 在容器宽度/高度更改时对子项应用转换。 如果我继续尝试使用 hacks,我只会有更多的错误。 你在这方面工作过,你比我更清楚。 请指导我。

谢谢你的详细报告。
我认为这是 ZoomLayout 的一个普遍问题,在更改容器的尺寸时还没有真正定义行为,因为我们希望容器保持其尺寸,如果我错了,请纠正我@natario1。 所以据我所知,这更像是一个功能请求而不是一个错误。

如果我们想支持这一点,我认为我们需要讨论预期的行为应该是什么样子,以及开发人员应该如何偏离它。

我喜欢它现在的工作方式,容器大小可能因多种原因而改变,如果内容已经缩放/平移,我认为我们不应该重新应用转换。 你应该能够像这样实现你想要的:

zoomLayout.layoutParams = layoutParams
zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)

或者像这样

zoomLayout.layoutParams = layoutParams
zoomLayout.post {
    zoomLayout.engine.setContainerSize(layoutParams.width, layoutParams.height, true)
}

我们可以使用 syncTransformation() 函数或类似的东西使这更容易

@markusressel好的,我明白了。 另外,我觉得我想做的只是使用这个库的 25% 的潜力。 禁用库的用途实际上是在违背它并期望它能够工作。 我所需要的只是带有平移和抛掷的中心裁剪。 如果您有任何建议,请提出。 谢谢。

容器大小可能因多种原因而改变,如果内容已经缩放/平移,我认为我们不应该重新应用转换

@natario1如果这是预期的/需要的,则此行为应该有一个选择加入标志。 对我来说,这感觉就像是对默认期望的反感。 当应用 center-crop 并更改容器大小时,应保持 center-crop。 尽管如果我们不支持 ZoomLayout 中的大小更改,那么这甚至无关紧要。

另外,我从星期二开始研究图书馆的代码。 我对矩阵、向量或着色器的工作原理知之甚少。 我尝试阅读和修改来学习。 但是,在报告问题之前,我已经尝试了您的建议。 因此,水平和垂直方向都启用了平移。 并且,由于内容/子项似乎被缩放,因此中心裁剪不再可用。

感谢您的帮助。 很抱歉我花了更长的时间来回复。

@rupinderjeet我试图重现您的示例,但是当将修改后的LayoutParams应用于ZoomLayout实例时,我收到了我们自己的错误消息:

java.lang.RuntimeException: ZoomLayout must be used with fixed dimensions (e.g. match_parent)

我错过了什么吗?

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

lucasrsv picture lucasrsv  ·  3评论

kuoliangkwong picture kuoliangkwong  ·  4评论

aouledissa picture aouledissa  ·  10评论

natario1 picture natario1  ·  13评论

wakaztahir picture wakaztahir  ·  5评论