0

カードゲーム用の Android アプリケーションを作成しています。基本的に、私はそれを持っているので、一度に画面に 3 枚のカードが 4 列あり、各カードは押せる で表されますImageButton。私の問題は、これらの 12 枚のカードを作成できるように for ループを使用したいOnClickListeners一方で、現在のカードの番号を追跡して、どのボタンが押されたかを適切に追跡できるようにすることです。以下のコードでは、counter を使用して、プッシュされたカードの数pressed_indexと、プッシュされた 3 枚のカードを追跡しています。カウンターが 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));
                }
            }
    });
}

別の方法は、私が今それを持っている方法であり、それ以外の方法でそれを行うことができる唯一の方法は、12のメソッドすべてをハードコードし、物理的に各番号を入れることです. ただし、これは非常に非効率的であり、コードの更新が非常に困難になります。ID を正しく設定する問題は悪くありません。x から構築された文字列から ID を取得するだけです。

int ID = getResources().getIdentifier(("card_"+(x+1)),"id","com.example.project");
hand[x] = (ImageButton)findViewById(ID);

...ここにある解決策に似ています: Android: 文字列 / ループで findViewById() を使用し ます。Accessing variables from onclicklistenerAndroid: Accessing a global Variable inside an onClickListener のような投稿を通じて、変数のみfinalを渡すことができるようです。一般的な修正の 1 つは、匿名クラスを使用する代わりに別のクラスを作成することです。の別のクラスを書き始めたとき、変数を渡して を作成し、それを正しいカードに一致させるOnClickListenerことができなかったため、同じ問題に遭遇しました。OnClickListenerこれを修正する方法について何かアイデアがあれば教えてください。

4

1 に答える 1

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

つまり、ヘルパーの最終変数を導入し、反復子をそれに割り当ててから、匿名内部クラスで最終ヘルパーを参照します。この方法で変数を「キャプチャ」していると言うかもしれません。ラムダ構文で変数を閉じる方法と非常に似ていますが、そのような明示的なコード フレーバーについては Java 設計を非難してください

または、匿名クラスで使用される変数の参照は final final でなければなりませんが、それは参照されるobjectを変更できないという意味ではないことに注意してください。例えば

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));
                }
        }
    });
}
于 2014-01-18T09:11:21.587 に答える