2013-08-02 45 views
0

我正在爲紙牌遊戲創建Android應用程序。基本上,我擁有它,所以屏幕上一次有四行三張卡片,每張卡片由可壓縮的ImageButton表示。我的問題是我想使用for循環,所以我可以爲這12張卡片創建OnClickListeners,同時有一種方法可以跟蹤我們所在的數字卡片的位置,以便我可以正確跟蹤哪個按鈕被按下。在下面的代碼中,我使用計數器來跟蹤有多少卡被推入,並使用pressed_index來跟蹤被推入的三張卡。如果計數器不等於三,我更改ImageButton上的顏色過濾器使其看起來被推動。但是,當我設置匿名類時,我不能使用x變量,因爲它在匿名類中是不允許的。我需要能夠將pressed_index設置爲當前卡的值,否則我無法知道12張卡中的哪一張被推入。在Android OnClickListener匿名類中使用循環索引創建ImageButton的網格

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編寫單獨的課程時,我遇到了同樣的問題,因爲我無法傳遞變量來創建OnClickListener以將其匹配到正確的卡。請讓我知道,如果你有任何想法可以解決這個問題。

+0

順便說一句,雖然這並不關心的問題本身 - 價值'12'應該出來,形成一個變量/不斷在這裏;否則它只是一個[幻數](https://en.wikipedia.org/wiki/Magic_number_(編程)#Unnamed_numerical_constants) – vaxquis

回答

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

就是你介紹一個幫手最後一個變量,迭代器分配給它,然後引用的匿名內部類的最後幫手;你可能會說你正在以這種方式「捕捉」變量。雖然它非常類似於在lambda語法中關閉變量的方式,但是要指責Java設計的這種顯式代碼風味嘆息

另外,請注意,雖然匿名類中使用的變量的引用必須是final final,但這並不意味着您不能更改引用的對象;例如

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

也請注意,在Java 8中有一個「有效最終」的術語,您也可以使用lambdas /閉包而不需要明確的決賽 - 所以設計現在變得越來越好。 – vaxquis