java - 在 Android OnClickListener 匿名类中使用循环索引创建 ImageButtons 网格

标签 java android imagebutton onclicklistener

我正在为纸牌游戏创建 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/

相关文章:

java - 如何从现有的 gridview 图像实现 coverflow 布局

html - 如何在 ASP.Net 中更改禁用的 ImageButton 的光标

java - 如何在布局中滚动时查看所有图像

java - 云数据流:Reading entire json array file from Cloud Storage and create a PCollection of json object

java - 将复选框动态添加到 fragment - 复选框不可见

java - 在验证 JTextFields 的数值是否大于 0 后,在 java 中启用 JButtons 吗?

java - Android Set 上的 ConcurrentModificationException

java - 传递一个类并调用它的方法

android - 如何使 ImageButtons 边界环绕图像?

android - 带有图像但没有常规按钮形状的按钮 : Android