2012-07-05 66 views
25


我有:自定義列表視圖與Textviews和複選框。 當滾動自定義列表視圖,複選框值的變化


問題:假設我的屏幕在時間上只能顯示6個項目,而其他項目是不可見的。 所以我檢查了列表中的第一個元素(位置爲0的項目)。向下滾動查看我的所有列表,當我在第一個元素(位置0處的項目)上滾動時,複選框被正確檢查。大!但是現在有些新項目也會被檢查,例如位置8的項目(因爲當我滾動列表時(對於Rycicling)它成爲位置0處的新項目。請記住我的屏幕在時間上只顯示7個元素)。它會被檢查,但我從來沒有檢查過它!

問題:我該如何避免這個問題?我不希望我不點擊的複選框改變它們的狀態。
下面我適配器的ListView與getView功能,我已經實現了setOnCheckedChangeListener:

public class NewQAAdapterSelectFriends extends BaseAdapter { 
private LayoutInflater mInflater; 
private Person[] data; 


public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context); 
} 

public void setData(Person[] data) { 
    this.data = data; 
} 

@Override 
public int getCount() { 
    return data.length; 
} 

@Override 
public Object getItem(int item) { 
    return data[item]; 
} 

@Override 
public long getItemId(int position) { 
    return position; 
} 



@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item_select_friends, null); 
     final ViewHolder viewHolder = new ViewHolder(); 
     viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); 
     viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); 
     viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); 
     viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); 
     convertView.setTag(viewHolder); 
     viewHolder.nameText.setTag(viewHolder.nameText); 
     viewHolder.nameText.setTag(viewHolder.surnameText); 
     viewHolder.contactImage.setTag(data[position]); 
     viewHolder.checkBox.setOnCheckedChangeListener(
       new CompoundButton.OnCheckedChangeListener() { 
        @Override 
        public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 
         Person element = (Person) viewHolder.checkBox.getTag(); 

         if(isChecked){ 
          element.setCheck(buttonView.isChecked()); 
          //data[position].setCheck(true); //this is equivalent to previous line 

         } 
         else{ 
          //to-do 

         } 

        } 
       }); 
     viewHolder.checkBox.setTag(data[position]); 

    } else { 


    } 

    ViewHolder holder = (ViewHolder) convertView.getTag(); 
    holder.nameText.setText(data[position].getName()); 
    holder.surnameText.setText(data[position].getSurname()); 
    holder.contactImage.setImageResource(data[position].getPhotoRes()); 
    holder.contactImage.setScaleType(ScaleType.FIT_XY); 
    holder.checkBox.setChecked(data[position].isCheck()); 
    return convertView; 
} 

static class ViewHolder { 
    TextView nameText; 
    TextView surnameText; 
    ImageView contactImage; 
    CheckBox checkBox; 
} 
} 

感謝您的答案:)

編輯:隨着建議我改變了我的getView像如下:

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    final ViewHolder viewHolder; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item_select_friends, null); 
     viewHolder=new ViewHolder(); 
     viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); 
     viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); 
     viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); 
     viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); 

     convertView.setTag(viewHolder); 

     viewHolder.nameText.setTag(viewHolder.nameText); 
     viewHolder.nameText.setTag(viewHolder.surnameText); 
     viewHolder.contactImage.setTag(data[position]); 
     viewHolder.checkBox.setChecked(data[position].isCheck()); 
     viewHolder.checkBox.setOnClickListener(new OnClickListener() { 

      public void onClick(View arg0) { 

       if(viewHolder.checkBox.isChecked()==true) 
        data[position].setCheck(true); 
       else 
        data[position].setCheck(false); 
      } 
     }); 

    } 
    else{ 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    viewHolder.nameText.setText(data[position].getName()); 
    viewHolder.surnameText.setText(data[position].getSurname()); 
    viewHolder.contactImage.setImageResource(data[position].getPhotoRes()); 
    viewHolder.contactImage.setScaleType(ScaleType.FIT_XY); 
    viewHolder.checkBox.setChecked(data[position].isCheck()); 
    return convertView; 
} 

編輯後的狀態:現在,如果我檢查屏幕上顯示的初始項目,然後查看列表,它們的值將被正確保存。但是,當我滾動列表,例如我想檢查我的列表中的最後一棵樹複選框,然後我滾動後,他們變得uncheked ....但爲什麼??????

解決:我解決我getView的問題,此代碼:

public class NewQAAdapterSelectFriends extends BaseAdapter { 
private LayoutInflater mInflater; 
private Person[] data; 
boolean[] checkBoxState; 
ViewHolder viewHolder; 

public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context); 
} 


public void setData(Person[] data) { 
    this.data = data; 
    checkBoxState=new boolean[data.length]; 
} 

@Override 
public int getCount() { 
    return data.length; 
} 

@Override 
public Object getItem(int item) { 
    return data[item]; 
} 

@Override 
public long getItemId(int position) { 
    return position; 
} 



@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item_select_friends, null); 
     viewHolder=new ViewHolder(); 

     viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); 
     viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); 
     viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); 
     viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); 

     convertView.setTag(viewHolder); 

    } 
    else{ 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    viewHolder.nameText.setText(data[position].getName()); 
    viewHolder.surnameText.setText(data[position].getSurname()); 
    viewHolder.contactImage.setImageResource(data[position].getPhotoRes()); 
    viewHolder.contactImage.setScaleType(ScaleType.FIT_XY); 
    viewHolder.checkBox.setChecked(checkBoxState[position]); 
    viewHolder.checkBox.setOnClickListener(new View.OnClickListener() { 

      public void onClick(View v) { 
       if(((CheckBox)v).isChecked()){ 
        checkBoxState[position]=true; 
        data[position].setCheck(true); 
       }else{ 
        checkBoxState[position]=false; 
        data[position].setCheck(false); 
       } 
      } 
     }); 
    return convertView; 
} 


static class ViewHolder { 
    TextView nameText; 
    TextView surnameText; 
    ImageView contactImage; 
    CheckBox checkBox; 
} 

}

我已經看到了這個教程做我getView:http://androidcocktail.blogspot.it/2012/04/adding-checkboxes-to-custom-listview-in.html

+0

大解決這個崗位,其工作對我來說 – Ravikumar11 2013-03-12 12:44:02

+0

只有一個問題?什麼是Person []數據?我的意思是它看起來如何? – Josef 2013-09-29 09:18:42

+0

唯一的解決方案,爲我工作。 – 2015-02-11 14:16:27

回答

1

你沒有覆蓋案例convertView!= null,這是上下滾動時發生的情況。你應該實現一種方法來回收convertView(更好),或者只是忽略它,並在這種情況下給出一個新的視圖(更糟糕)。

+0

謝謝,但我怎麼能做到這一點? – 2012-07-05 13:22:26

2

只有在convertview爲null時,纔會設置複選框的標記。這隻發生在記錄的第一個屏幕上。當用戶向下滾動時,先前的convertviews將被回收。因此,您的複選框將舊數據項作爲其標籤。

您的託運變化監聽器應該是這樣的:

new CompoundButton.OnCheckedChangeListener() 
{ 
    @Override 
    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) 
    { 
     Person element = (Person) viewHolder.checkBox.getTag(); 

     data[position].setCheck(isChecked); 

     if(isChecked) 
     { 
      // do your stuff 
     } 
     else 
     { 
      //to-do 
     } 

    } 
} 
+0

謝謝你的回答,但我不工作。現在,如果我檢查了一些chekbox,當我滾動列表我失去了長度和每個複選框未經檢查!我會嘗試添加:if(isChecked)data [position] .setChecked(true)else data [position] .setChecked(false)...我怎麼辦? – 2012-07-05 13:21:34

+0

DON「T使用onCheckedChanged,使用onClick代替,這對我很有用 – RRTW 2013-02-05 02:27:59

0

檢查這個代碼

public class NewQAAdapterSelectFriends extends BaseAdapter { 
private LayoutInflater mInflater; 
private Person[] data; 
ArrayList<String> checkedItem=new ArrayList<String>(); 

public NewQAAdapterSelectFriends(Context context) { 
    mInflater = LayoutInflater.from(context); 
} 

public void setData(Person[] data) { 
    this.data = data; 
} 

@Override 
public int getCount() { 
    return data.length; 
} 

@Override 
public Object getItem(int item) { 
    return data[item]; 
} 

@Override 
public long getItemId(int position) { 
    return position; 
} 



@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item_select_friends, null); 
     final ViewHolder viewHolder = new ViewHolder(); 
     viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName); 
     viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname); 
     viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage); 
     viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox); 
     convertView.setTag(viewHolder); 
     viewHolder.nameText.setTag(viewHolder.nameText); 
     viewHolder.nameText.setTag(viewHolder.surnameText); 
     viewHolder.contactImage.setTag(data[position]); 
     viewHolder.checkBox.setOnCheckedChangeListener(
       new CompoundButton.OnCheckedChangeListener() { 
        @Override 
        public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 
         Person element = (Person) viewHolder.checkBox.getTag(); 

         if(isChecked){ 
          getCheckList(data[position],isChecked); 
         } 
         else{ 
          getCheckList(data[position],isChecked);  
         } 

        } 
       }); 
     viewHolder.checkBox.setTag(data[position]); 
    } 
    ViewHolder holder = (ViewHolder) convertView.getTag(); 
    holder.nameText.setText(data[position].getName()); 
    holder.surnameText.setText(data[position].getSurname()); 
    holder.contactImage.setImageResource(data[position].getPhotoRes()); 
    holder.contactImage.setScaleType(ScaleType.FIT_XY); 
    if(checkedItem != null && checkedItem.contains(data[position])){ 
     viewHolder.checkBox.setChecked(true); 
    }else 
    { 
     viewHolder.checkBox.setChecked(false); 
    } 
    return convertView; 
} 

static class ViewHolder { 
    TextView nameText; 
    TextView surnameText; 
    ImageView contactImage; 
    CheckBox checkBox; 
} 
public void getCheckList(String value,boolean status){ 
     if(!checkedItem.contains(value) && status) 
     { 
      checkedItem.add(value); 
     } 
     if(checkedItem.contains(value) && !status) 
     { 
      checkedItem.remove(value); 
     } 
    } 
} 
+0

我嘗試了你的解決方案,但當我點擊checkBoxs然後滾動chekboxs變成所有uncheched ....爲什麼??? – 2012-07-05 14:19:54

+0

邏輯工作適合我。請檢查checkedItem的值或發佈已更改的代碼邏輯應用 – 2012-07-06 04:19:03

+0

嗨,我更改我的代碼作爲您的答案我使用相同的代碼,但複選框丟失了他們的價值:(.. – 2012-07-06 08:18:35

4

檢查下面的代碼 -

public View getView(int position, View convertView, ViewGroup parent){ 
      View view = convertView; 
      ViewHolder holder = new ViewHolder(); 

      if(view == null){ 

       view = inflater.inflate(R.layout.list_callcycle_blue, null);     
       holder.llContainer = (LinearLayout) view.findViewById(R.id.ll_container); 
       holder.lblLabel = (TextView) view.findViewById(R.id.txt_desc); 
       holder.cb = (CheckBox) view.findViewById(R.id.cb_store); 

       view.setTag(holder); 
      } else { 
       holder = (ViewHolder) view.getTag(); 
      } 

      final Object data = getItem(position); 
      holder.lblLabel.setText(data.getDescription()); 

      holder.cb.setTag(position); 
      holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { 

       @Override 
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 

        int position = (Integer) buttonView.getTag(); 
        objects.get(position).setChecked(buttonView.isChecked()); 
       } 
      }); 
      holder.cb.setChecked(isChecked(position)); 

      return view; 
     } 

始終牢記,利用變化holder.cb.setOnCheckedChangeListener()任意監聽它的設置數據之前,在我們的情況下,它是holder.cb.setChecked()

原因:當我們滾動,列表視圖將回收的意見,所以如果setchecked聽衆之前使用,那麼它就會挑老聽衆的基礎上,值。如果我們監聽後設置它,然後它會採取最新值

+1

主要幫助你如何解釋設置聽衆後設置值的原因 – 2016-01-27 20:30:25

5

我解決我的問題只是改變了「setOnCheckedChangeListener」到「setOnClickListener」

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

    ViewHolder holder; 

    if (convertView == null) { 

     CheckBox cbItemChecklist = new CheckBox(context); 

     holder = new ViewHolder(); 
     holder.cbItemChecklist = cbItemChecklist; 

     convertView = cbItemChecklist; 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    final ItemChecklist itemChecklist = itensChecklist.get(position); 

    holder.cbItemChecklist.setText(itemChecklist 
      .getDescricaoItemChecklist()); 
    holder.cbItemChecklist.setChecked(itemChecklist.isChecked()); 
    holder.cbItemChecklist 
      .setOnClickListener(new OnClickListener() { 

       @Override 
       public void onClick(View v) { 
        if(itemChecklist.isChecked()){ 
         itemChecklist.setChecked(false); 
        } else { 
         itemChecklist.setChecked(true);       
        } 


       } 
      }); 
    return convertView; 
} 
+0

完美.....謝謝.... :) – 2017-05-02 10:23:37

0

我有一個複選框一個很好的選擇。您可以使用android:state_activated="true"作爲ListView行。它不會失去它的狀態,也不需要很多代碼。

這裏是如何工作的

  • 在繪製文件夾中創建active_row.xml


<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_activated="true"   
      android:drawable="@android:color/darker_gray"/> 
</selector> 
  • 設置你的行佈局背景
  • 最後添加到您的ListView android:choiceMode="multipleChoice"

您可以檢查每一行的國家這樣

View v; 

LinearLayout yourRowLayout; 
for (int i = 0; i < yourListView.getChildCount(); i++) { 
v = yourListView.getChildAt(i); 
yourRowLayout = (LinearLayout) v.findViewById(R.id. yourRowLayout); 
if(yourRowLayout.isActivated()){.... } } 
0

您需要更新適配器保留複選框

holder.chk.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       CheckBox c = (CheckBox)v.findViewById(R.id.chkID); 
       Boolean chk = c.isChecked(); 
       Integer pos = (Integer)v.getTag(); 
       itemList.get(pos).setChk(chk); 

      } 
     }); 

的價值如需更多幫助,您可以參考在Retain Checkbox value

相關問題