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

时间:2013-08-02 04:36:44

标签: java android imagebutton onclicklistener

我正在为纸牌游戏创建一个Android应用程序。基本上,我有它,所以屏幕上一次有四行三张卡,每张卡由一个可按下的ImageButton表示。我的问题是我想使用for循环,所以我可以为这12张卡创建OnClickListeners,同时有办法跟踪我们所在的卡号,这样我就可以正确地跟踪哪个按钮被按下了。在下面的代码中,我使用计数器来跟踪推送的卡数,并使用pressed_index来跟踪推送的三张卡。如果计数器不等于3,我更改ImageButton上的滤色器使其显示为按下。但是,当我设置匿名类时,我不能使用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 onclicklistenerAndroid: Accessing a global Variable inside an onClickListener等帖子,似乎只能传递final个变量,一个常见的解决方法是创建一个单独的类而不是使用匿名类。然而,这并没有让我走得太远,因为当我开始为OnClickListener编写单独的类时,我遇到了同样的问题,因为我无法传递变量来创建{{1}将它与正确的卡匹配。如果您对如何解决这个问题有任何想法,请告诉我。

1 个答案:

答案 0 :(得分:3)

常规的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变量,给它赋予迭代器,然后引用匿名内部类中的最终帮助器;你可能会说你以这种方式“捕获”变量。虽然它与你在lambda语法中关闭变量的方式非常相似,但是将Java设计归咎于这样的显式代码调整叹息

或者,请注意,虽然匿名类中使用的变量的引用必须是最终的,但这并不意味着您无法更改引用的对象; e.g。

final Foo foo = new Foo();
bar.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            foo.doBaz();
        }
});

是完全有效的代码 - 然后您可以自由地更改foo方法中doBaz()的状态。地狱,你甚至可以(严重的代码味道 - 不要在家里试试!)

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));
                }
        }
    });
}