2012-05-12 230 views
1

我在我的活動和每行Im有一個ListView使用我的自定義佈局與TextView和兩個按鈕。當我點擊這兩個按鈕中的任何一個時,我想要執行某個動作。在我的ArrayAdapter中,在getView方法中,我將onClickListeners設置爲這兩個按鈕。Android ListView自定義佈局

public View getView(int position, View convertView, ViewGroup parent) { 

    View v = convertView; 
    if (v == null) { 
     v = li.inflate(R.layout.process_row, null); 
    } 


    final Button processCheck = (Button) v.findViewById(R.id.processCheck); 
    processCheck.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (process.isChecked() == false) { 
       process.setChecked(true); 
       processCheck.setBackgroundColor(Color.BLUE); 
      } 
      else { 
       process.setChecked(false); 
       processCheck.setBackgroundColor(Color.RED); 
      } 

     } 
    }); 

    return v; 
} 

ArrayList保存mz自定義類的對象進程和進程在代碼中是這個類的一個實例。所以,現在當我在其中一個ListView行中單擊這個按鈕時,我希望改變給定Process實例中的布爾變量並更改按鈕的顏色。發生這種情況,但不僅僅是這一行,還有3-4次。所以點擊後,我有5個改變的按鈕,而不是一個。你知道我在這裏做錯了什麼嗎?請注意,我不太瞭解ListActivity編碼,大部分代碼實際上是從示例文件中複製和編輯的。謝謝!

編輯:

該問題可能只與佈局的地方。當我點擊按鈕時,它們中的更多顏色會改變,但只有我單擊的過程的布爾值發生了變化。

+0

http:// w ww.android-ios-tutorials.com/770/create-custom-listview-in-android/ – Houcine

回答

0

編輯:找一個 「開箱即用」 的帖子的末尾例子!

因爲你看到多行受到影響我猜它有些事情要做系統如何回收資源,也許對Button的引用是不明確的。

我不確定我在哪裏選擇了這種做法(Android教程或我們以前的開發人員通過這些教程學習了Android)。然而,建議是使用一個嵌套類ViewHolder

private static class ViewHolder { 

    public Button processCheck; 
} 

將此放在適配器或任何類的getView()在聲明並修改它是這樣:

public View getView(int position, View convertView, ViewGroup parent) { 

    View v = convertView; 
    $ViewHolder viewHolder; //wait for the magic! 
    if (v == null) { 
     v = li.inflate(R.layout.process_row, null); 
     $viewHolder = new ViewHolder(); 
     $viewHolder.processCheck = (Button) v.findViewById(R.id.processCheck); 
     $v.setTag(viewHolder); 
     //ok we somewhat stuffed an object with the Button into our View... so what? 
    } 

    $viewHolder = (ViewHolder) v.getTag(); 
    //see explanation below 

    $viewHolder.processCheck.setOnClickListener(new View.OnClickListener() { 
    //set the onClickListener for this and only this button. 
     @Override 
     public void onClick(View v) { 
      if (process.isChecked() == false) { 
       process.setChecked(true); 
       processCheck.setBackgroundColor(Color.BLUE); 
      } 
      else { 
       process.setChecked(false); 
       processCheck.setBackgroundColor(Color.RED); 
      } 

     } 
    }); 

    return v; 
} 

(我打上$變化。我認爲這樣他們應該很容易發現,如果我使用eclipse。否則查找+替換^^)

因此​​將返回一個與調用的視圖關聯的對象。對象是如此令人難以置信的泛型,您可以將其稱爲您創建的ViewHolder對象。因此,您可以引用按鈕並將其存儲在對象中。
現在,無論何時獲得ListView,都可以檢索對象並設置新鮮和新鮮的OnclickListener。這樣你只有一個Listener被調用。

請注意,您不必再次致電v.setTag();來「保存」您的更改。

一個陷阱可能是如果你瘋狂的東西,像在同一個列表中膨脹不同的佈局,有什麼理由。你也許會不同ViewHandlers分配給他們,如:

if (v == null) { 
    if(someCriteria) { 
     v = li.inflate(R.layout.process_row, null); 
     viewHolder = new ViewHolder(); 
    } 
     v = li.inflate(R.layout.process_another_row, null); 
     viewHolder = new AnotherViewHolder(); 
} 

隨後的getView()一個ViewHolder或其他未經檢查的通話可能會在運行時拋出一個錯誤!

+0

我急於嘗試這個,但在onClickListener我得到「無法解決」爲processCheck。我想可能應該有viewHolder。過程檢查,而是當我這樣做時,我得到「不能引用非最終變量viewHolder」。所以我改變了實例wHolder是最終的,但我在v.getTag()行得到「可能已被分配」。它可能只是一個愚蠢的問題,但我不能看到它... –

+0

我會深入研究它:)給我一些分鐘雖然=) – yoshi

+0

還有一件事,我不得不聲明ViewHandler只是作爲一個類,而不是私有的靜態的。它只會允許公共抽象和最終:) –

0

問題是在這裏

View v = convertView; 
    if (v == null) { 
     v = li.inflate(R.layout.process_row, null); 
    } 

這是因爲只有創造了可見的項目視圖V,然後它再利用。所以只要刪除IFV == NULL),所以你的代碼會

public View getView(int position, View convertView, ViewGroup parent) { 

    View v = convertView; 

     v = li.inflate(R.layout.process_row, null); 



    final Button processCheck = (Button) v.findViewById(R.id.processCheck); 
    processCheck.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (process.isChecked() == false) { 
       process.setChecked(true); 
       processCheck.setBackgroundColor(Color.BLUE); 
      } 
      else { 
       process.setChecked(false); 
       processCheck.setBackgroundColor(Color.RED); 
      } 

     } 
    }); 

    return v; 
} 
+0

這樣做:)只有一個按鈕改變它的顏色,但現在當我點擊它,看到它改變,比向下滾動向上再次,它的顏色和之前的點擊一樣:) –

+0

每當列表呈現時,都會調用getView。所以你應該加入你的gerview – vandzi

+0

我想知道當你通過一個列表快速滾動時這將如何執行。充氣所有這些佈局會讓機器人哭泣,而不是?:C – yoshi

0

getView被稱爲每當列表呈現時間。所以,你應該加入到設置顏色的gerview條件:公共查看getView(INT位置,查看convertView,ViewGroup以及母公司){

View v = convertView; 

    v = li.inflate(R.layout.process_row, null); 

//添加這些行婁

如果(process.isChecked() == FALSE){

 processCheck.setBackgroundColor(Color.BLUE); 
    } 
    else { 

     processCheck.setBackgroundColor(Color.RED); 
    } 

final Button processCheck = (Button) v.findViewById(R.id.processCheck); 
processCheck.setOnClickListener(new View.OnClickListener() { 

    @Override 
    public void onClick(View v) { 
     if (process.isChecked() == false) { 
      process.setChecked(true); 
      processCheck.setBackgroundColor(Color.BLUE); 
     } 
     else { 
      process.setChecked(false); 
      processCheck.setBackgroundColor(Color.RED); 
     } 

    } 
}); 

return v; 

}

+0

我編輯了代碼。所有的按鈕現在都是藍色的,應該是bu,當我按下按鈕時,它會變紅,但是在向下滾動之後,我不能再看到它,並且再次返回,它又變爲藍色: –

+0

我寫錯了。像這樣:final Button processCheck =(Button)v.findViewById(R.id.processCheck); if(process.isChecked()== false)processCheck.setBackgroundColor(Color.BLUE); } } else { processCheck.setBackgroundColor(Color.RED); } – vandzi

+0

我想過程是你的適配器 – vandzi

0

這是我如何解決它:

在我的適配器,我創建的類:

private static class ViewHolder { 
    public Button  processCheck; 
    public Process  process; 
    public TextView  name; 
} 

比我創建了一個自定義的監聽我的按鈕:

private class CustomListener implements View.OnClickListener { 

    public ViewHolder viewHolder; 

    public CustomListener(ViewHolder holder) { 
     this.viewHolder = holder; 
    } 

    @Override 
    public void onClick(View v) { 
     if (viewHolder.process.isChecked()) { 
      viewHolder.name.setText("not checked"); 
      viewHolder.process.setChecked(false);    
     } 
     else { 
      viewHolder.name.setText("checked"); 
      viewHolder.process.setChecked(true);     
     }   
    } 
} 

而且我getView功能:

public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder viewHolder; 

    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.process_row, null); 

     viewHolder = new ViewHolder(); 
     viewHolder.processCheck = (Button) convertView.findViewById(R.id.processCheck); 
     viewHolder.name = (TextView) convertView.findViewById(R.id.processName);    
     convertView.setTag(viewHolder); 
    } 


    viewHolder = (ViewHolder) convertView.getTag(); 
    viewHolder.process = list.get(position); 

    if (viewHolder.process.isChecked()) { 
     viewHolder.name.setText("checked");   
    } 
    else { 
     viewHolder.name.setText("not checked");   
    }  

    CustomListener listener = new CustomListener(viewHolder); 
    viewHolder.processCheck.setOnClickListener(listener); 

    return convertView; 
} 
+0

問題是在getView中的if-else條件。添加它們並正確執行後,代碼工作。再次感謝,傢伙:) –