我正在为纸牌游戏创建 Android 应用程序。基本上,我有它,所以屏幕上一次有四行三张卡片,每张卡片都由一个可按的 ImageButton 表示。我的问题是我想使用 for 循环,这样我就可以为这十二张卡片创建 OnClickListeners,同时有办法跟踪我们所在的数字卡片,这样我就可以正确跟踪哪张卡片按钮被按下。在下面的代码中,我使用 counter 来跟踪推送了多少张牌,并使用 pressed_index
来跟踪推送的三张牌。如果计数器不等于 3,我会更改 ImageButton
上的颜色滤镜,使其看起来像是被按下的。但是,当我设置匿名类时,我无法使用 x 变量,因为匿名类中不允许使用 x 变量。我需要能够将 pressed_index
设置为当前卡的值,否则我将无法知道 12 张卡中的哪一张被推送。
ImageButton[] hand = new ImageButton[12];
int[] pressed_index = new int[3];
int counter = 0;
for (int x = 0; x < 12; x++) {
hand[x] = (ImageButton)findViewById(R.id.//card_1, card_2, etc.);
hand[x].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pressed_index[counter] = x;
counter++;
if (counter != 3) {
((ImageView) v).setColorFilter(Color.argb(150, 155, 155, 155));
}
}
});
}
另一种选择,这就是我现在的方式,我能想到的唯一方法就是对所有十二个方法进行硬编码,并以物理方式放入每个数字。但这是非常低效的,并且使得更新代码变得非常困难。正确设置ID的问题还不错,我只是从x构造的字符串中获取ID,就像这样......
int ID = getResources().getIdentifier(("card_"+(x+1)),"id","com.example.project");
hand[x] = (ImageButton)findViewById(ID);
...类似于此处找到的解决方案:Android: Using findViewById() with a string / in a loop
然而,即使经过大量研究,到目前为止,使用 x 的问题仍然无法解决。通过像Accessing variables from onclicklistener这样的帖子和 Android: Accessing a global Variable inside an onClickListener ,似乎只能传递 final
变量,一个常见的解决方法是创建一个单独的类而不是使用匿名类。然而,这并没有让我走得太远,因为当我开始为 OnClickListener
编写单独的类时,我遇到了同样的问题,因为我无法传递变量来创建 OnClickListener
将其与正确的卡片相匹配。如果您对如何解决此问题有任何想法,请告诉我。
最佳答案
常规的 Java/Android 习惯用法是
ImageButton[] hand = new ImageButton[12];
int[] pressed_index = new int[3];
int counter = 0;
for (int x = 0; x < 12; x++) {
final int x_ = x;
hand[x] = (ImageButton)findViewById(R.id.//card_1, card_2, etc.);
hand[x].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pressed_index[counter] = x_;
counter++;
if (counter != 3) {
((ImageView) v).setColorFilter(Color.argb(150, 155, 155, 155));
}
}
});
}
也就是说,你引入一个helper Final变量,为其分配迭代器,然后在匿名内部类中引用该final helper;您可能会说您正在以这种方式“捕获”变量。虽然它与 lambda 语法中关闭变量的方式非常相似,但将这种显式代码调味归咎于 Java 设计叹息。
或者,请注意,虽然匿名类中使用的变量的引用必须是finalfinal,但这并不意味着您不能更改引用的对象;例如
final Foo foo = new Foo();
bar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
foo.doBaz();
}
});
是完全有效的代码 - 然后您可以在 doBaz()
方法中自由更改 foo
的状态。天啊,你甚至可以(严重的代码味道 - 不要在家尝试这个!)
ImageButton[] hand = new ImageButton[12];
int[] pressed_index = new int[3];
int counter = 0;
for (int[] x = new int[]{0}; x[0] < 12; x[0]++) {
hand[x[0]] = (ImageButton)findViewById(R.id.//card_1, card_2, etc.);
hand[x[0]].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pressed_index[counter] = x[0];
counter++;
if (counter != 3) {
((ImageView) v).setColorFilter(Color.argb(150, 155, 155, 155));
}
}
});
}
关于java - 在 Android OnClickListener 匿名类中使用循环索引创建 ImageButtons 网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18008868/