【问题标题】:Button requires double click to activate click event按钮需要双击才能激活点击事件
【发布时间】:2020-12-11 00:37:55
【问题描述】:

这个 bug 似乎无法消除,现在它跟着我去了两个不同的项目(我废弃的第一个项目)。下面是代码:


   


    if(testIterator.hasNext()){

        layers.setDrawableByLayerId(R.id.layer1, testIterator.next())
        basePicture.setImageDrawable(layers)
    }
    else{
        hairButton.isFocusable = false

        layers.setDrawableByLayerId(R.id.layer1,test.first())
        basePicture.setImageDrawable(layers)
        testIterator = test.iterator()

    }

}

“layers”是可绘制文件夹中的layer-list.xml。使用这个迭代器,我正在迭代一个名为“test”的drawables(?)数组。 “测试”中的可绘制对象正在替换我的 layer-list.xml 中的单个可绘制对象。

if 语句的功能是(如前所述),遍历可绘制对象列表(?),如果用户再次单击按钮,则将当前替换为下一个。这应该会在单击按钮时更改屏幕上的图形。

else 语句的功能是在按钮被一直点击到最后一个功能(如重新启动)后返回到数组列表“test”的元素 [0]。

问题: 我必须单击按钮两次才能离开元素 [0] 并开始迭代。之后它不需要双击,至少在它回到元素 [0] 之前不需要。我研究过这个问题,有人说它与“焦点”有关,但我已经广泛尝试了可聚焦性,我认为这不是问题。

我不认为它是这样说的: “basePicture.setImageDrawable(层)” 我认为这不是问题,因为我(认为)我需要这样来更新图像在屏幕上的外观,当我注释掉这一行时,它没有任何区别。

附: 当我进行迭代时,它不会立即显示在屏幕上。我必须单击主页按钮(因此应用程序消失)并重新打开它以查看显示的图形的任何变化。这是我发现的一个新错误,所以我还没有开始真正研究它,但任何关于这是什么的想法都会非常有帮助。谢谢!

【问题讨论】:

  • 为什么不使用索引属性而不是迭代器?长期挂在迭代器上并不是很健壮。
  • @Tenfour04 就像一个带有附加到 clicklistener 的中断的“for”循环?
  • 我没有想到任何循环。如果没有一些复杂的协程实现,您将无法做到这一点。只需挂上使用的最后一个索引的引用即可。使用时增加它,当它达到集合的大小时滚动它。

标签: java android android-studio kotlin


【解决方案1】:

这是因为当您循环回到起点时(在您的else 子句中),您将图像设置为显示第一层,然后为下一个循环创建一个新的迭代器。

但是您实际上并没有从迭代器中获取第一个元素,因此在下一次单击时,它会调用 next() - 这会产生下一个项目,即第一个项目,即第一层。你最终会再次显示它。

最简单的解决方法是在重新创建迭代器后调用next(),弹出不需要的第一个元素。更好的方法是将您的显示代码移动到一个通用函数中:

fun showNextLayer() {
    layers.setDrawableByLayerId(R.id.layer1, testIterator.next())
    basePicture.setImageDrawable(layers)
}

...

if (!testIterator.hasNext()) {
    hairButton.isFocusable = false
    testIterator = test.iterator()
}
showNextLayer()

您也可以滚动您自己的无限迭代器,因此您无需检查或重新创建它,您只需在每次点击时调用next()

class LayerIterator : Iterator<Int> {
    private var current = -1

    override fun hasNext() = true

    override fun next(): Int {
        // increment the current index, wrapping back to zero
        current = (current + 1) % layers.size
        return layers[current]
    }
}

但是因为你在 Kotlin 中,所以你可以做一个无限序列!

val iterator = generateSequence(0) { (it + 1) % layers.size }
    .map(layers::get)
    .iterator()

编辑 - 你的问题没有显示出来……我没有亲自使用过,但我认为你需要使用LevelListDrawable,而不是LayerDrawable

后者基本上是一个集合,它将一堆可绘制元素堆叠成一个您可以轻松引用的组合视觉元素,我不认为它是为了切换哪些在顶部。但是LevelListDrawable 用于将值分配给一组可绘制对象,然后您在其上调用setLevel 来控制显示哪个。 (他们给出的例子是电池图标及其不同的状态。)

所以你应该只需要在basePicture上设置一次drawable,然后设置drawable的level来改变显示的内容

【讨论】:

  • 我试用了 Levellist,但遇到了问题。我正在尝试将可绘制图层更改为不同的图像,就像当您自定义角色时可以更改其发型(您也可以更改鼻子形状)。我尝试创建一个可绘制的单层,每个项目都是可绘制的水平列表。当我将可绘制的主要图像设置为 layerlist 时,我看不到任何变化。我也尝试了无限序列,但它不会让我得到我的 levellist size 。你认为我应该尝试使用 Canvas 而不是图层列表的想法。 @cactustictacs
  • 哦,所以您实际上是在绘制一堆可绘制对象,而不是一次绘制一个?好的,我想在这种情况下你需要一个LayerDrawable,所以你的原始代码应该没问题,除非你不需要重复设置它在basePicture - 你将图层列表设置为它的drawable一次,然后你可以只是弄乱图层列表本身。它应该可以正常工作(我还没有使用过这些,但仍然)-您可以尝试在ImageView 上调用invalidate(),但它应该是自动的。除非你需要,否则不要打扰Canvases。对于您想要test 的长度/大小的序列,您的来源
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2014-05-08
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多