【问题标题】:Fixed Background Image in android without scroll listener修复了没有滚动监听器的android中的背景图像
【发布时间】:2019-09-22 03:47:26
【问题描述】:

我正在开发一个 android 库,以将图像显示为固定的背景图像。为此,我每 10 毫秒根据 locationOnScreen 动态调整图像的位置。我知道这是一个很棒的解决方案,但我来这里是为了改进它:)

这个问题是当父可滚动视图滚动太快并且图像在其他视图移动时发生跳动时,会出现故障。 (点击 gif 可查看完整演示)

由于它是一个库,我不想在集成库时增加复杂性,这意味着没有滚动侦听器、主题或没有窗口覆盖等。

已尝试的解决方案:
- 改变循环延迟
- 库不能使用窗口背景
- 无法访问活动主题或类似内容

处理程序

    override fun run() {
        fixedBackgroundImageLayout.getLocationOnScreen(locationOnScreen)
        fixedBackgroundImagePlugin.update(locationOnScreen)

        handler.postDelayed(this, 10)
    }

FixedBackgroundImagePlugin#update

    override fun update(locationOnScreen: IntArray) {
        if (backgroundImageFrameLayout == null) {
            return
        }
        yPosition = parentLocationOnScreen[1] - locationOnScreen[1]
        backgroundImageFrameLayout.top = 2 * yPosition - lastYPosition - 10
        lastYPosition = yPosition
    }

backgroundImageFrameLayout 将图像作为背景图像。

我还设置了一个sample repository 来帮助您在需要时进行挖掘。

我愿意接受任何建议/领导

【问题讨论】:

  • 你能在 ImageView 上放一个 ScrollView 吗?
  • 我无法理解您到底想要达到什么目的。您能否添加一个示例来说明您要实现的目标?
  • 对于一个完整的演示(有问题),检查raw.githubusercontent.com/HugoGresse/FixedBacgroundImageAndroid/…@AjahnCharles 但是滚动视图将如何对未定向到此的父滚动作出反应?我的意思是用户使用文本和图像在整个 ScrollView 上滚动。我只对图片本身负责。
  • 我正在开发一个 android 库以将图像显示为固定的背景图像。您只想滚动文本而不是图像?正确的?图像应保持在其固定位置?
  • 明白,问题是它确实是一个功能更多的库,管理图像只是一个特定的部分。所以它不能改变 ti 设计的容器之外的布局。

标签: android


【解决方案1】:

更新:我之前发布的代码有一些交互问题,令人惊讶的是,这些问题使代码工作但与 CPU 挂钩。下面的代码与前面的代码基本相似,但行为不同。虽然新代码包含一个滚动监听器,它会导致视图重绘自身,但它是自包含的。需要滚动侦听器来检测视图何时在屏幕上重新定位。调用时,滚动侦听器只会使视图无效。


您可以在自定义视图 BackgroundImageFrameLayout 中做所有您需要的事情。这是一个 draw() 覆盖,它将负责绘制包含图像的 FrameLayout 的背景。

将以下内容添加到 init 块中:

viewTreeObserver.addOnScrollChangedListener {
    invalidate()
}

将以下覆盖方法添加到BackgroundImageFrameLayout

override fun onDraw(canvas: Canvas) { // draw(canvas) may be better choice.
    if (background == null) {
        return
    }

    // Get the location of this view on the screen to compute its top and bottom coordinates.
    val location = IntArray(2)
    getLocationOnScreen(location)
    val imageTop = location[1]
    val imageBottom = imageTop + height

    // Draw the slice of the image that should be viewable.
    canvas.save()
    canvas.translate(0f, -imageTop.toFloat())
    background?.setBounds(0, imageTop, width, imageBottom)
    background?.draw(canvas)
    canvas.restore()
}

删除所有试图操纵背景的其他内容 - 你不需要它。

这是带有新 onDraw() 的应用程序演示:

我认为屏幕尺寸与图像尺寸之间可能存在其他一些问题,但这是你应该去的方向(恕我直言)

【讨论】:

  • 干得好,使用 onDraw 确实解决了问题,同时仍然使用 runnable。在 viewTreeObserver 上使用 scrollListener 可以删除 postDelayed。 ? 旁注,你能解释一下为什么在画布上使用 .save() 和 .restore() 吗?
  • 请参阅here,了解有关保存/恢复的详细说明。视图比图像小,但从图像中选择的切片不在视图内,而是在视图之外的某个位置。为了纠正这个问题,画布向下滑动,使视图和图像切片重叠。保存和恢复只是保存和恢复画布位置,不影响绘图。 (基本上撤消了翻译。)
  • 附带说明,考虑调整onSizeChanged() 中的图像大小。 onMeasure() 可以在每个布局中多次调用。您只需要在视图大小发生变化时调整位图大小。
  • 完美,感谢 Cheticamp,您已经赢得了赏金!再次感谢。
猜你喜欢
  • 1970-01-01
  • 2018-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多