1. 程式人生 > >ListView滾動後內容重複的問題

ListView滾動後內容重複的問題

最可能出現重複的情況就是getView(int position, View convertView, ViewGroup parent)中的convertview利用的情況,由於getview的時候,listview自身會複用已存在的item,即重用最先新建的那幾個item,還有就是注意tag的使用,convertView.getTag()返回的也是重用的view,其狀態是和被重用的一樣,包括圖片的顯示與隱藏的狀態,進度條的重新整理等,都會被重用,這就出現了圖片或者進度條錯亂的情況,這時就需要在getview的時候,先把狀態復原(即隱藏進度條,去掉沒有下載的item的監聽,圖片設為預設等等),然後再根據判斷條件修改各個item的狀態。

ListView只會快取第一屏裡面的List Item的檢視佈局,之後滾動ListView後面的Item的佈局就都是用前面所快取的檢視佈局(也就是convertView不為null)。這樣如果當後面的某一條記錄裡面的某些控制元件因上面的原因沒有賦值,就會直接使用前面所快取的視圖裡面的值了(裡面有值的話)。

  這樣的最終效果就是,滾動的時候,會出現前面已經出現過的內容。

解決辦法就是用setTag();

public class NursingProjectAdapter extends BaseAdapter {

private static final String TAG = NursingProjectAdapter.class.getSimpleName();

private Context mContext;
private LayoutInflater mLayoutInflater;
private List<NursingProject> mNps;
private ListView mListView;

/**
 * 儲存CheckBox選中記錄
 */
public Map<Integer, Boolean> isSelected;  

/**
 * 儲存掃描患者腕帶標籤執行所勾選的護理專案成功的資料
 * key 代表掃描患者腕帶標籤
 * value 代表掃描患者腕帶標籤時所勾選的護理專案,這些勾選的護理專案是已經執行成功的
 */
private Map<String,ArrayList<String>> cacheSubCodeMap = new HashMap<String, ArrayList<String>>();

/**
 * 勾選的專案
 */
private ArrayList<String> cacheSelectItems;

/**
 * 掃描的患者腕帶標籤
 */
private String selectItem;

public NursingProjectAdapter(Context context,List<NursingProject> nps,String mSelectItem){
    this.mContext = context;
    this.mLayoutInflater = LayoutInflater.from(context);
    this.mNps = nps;
    this.selectItem = mSelectItem;
    initMapAboutCheckBox();
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return mNps.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return mNps.get(position);
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    if(convertView == null){
        convertView = this.mLayoutInflater.inflate(R.layout.listitem_care_to_perfromnew, null);
        holder = new ViewHolder();
        holder.cbPerfroms = (CheckBox) convertView.findViewById(R.id.cbPerfroms);
        holder.tvPerfromsStatus = (TextView) convertView.findViewById(R.id.tvPerfromsStatus);
        convertView.setTag(holder);
    }else{
        holder = (ViewHolder) convertView.getTag();
    }
    holder.tvPerfromsStatus.setText(mNps.get(position).getSubitemName());
    //給tvPerfromsStatus控制元件做一個標記,防止listview向下滾動時,出現各項背景色錯亂
    holder.tvPerfromsStatus.setTag(mNps.get(position).getSubitemCode());
    //給cbPerfroms控制元件做一個標記,防止listview向下滾動時,勾選的checkbox出現錯亂
    holder.cbPerfroms.setTag(position);
    if(!isSelected.isEmpty()){
        holder.cbPerfroms.setChecked(isSelected.get(position));  
    }
    //若包含,根據已經執行過的記錄是否包含,包含則變為綠色,不包含則為預設背景色
    if(cacheSubCodeMap.containsKey(selectItem)){
        if(holder.tvPerfromsStatus.getTag() != null){
            if(cacheSubCodeMap.get(selectItem).contains(holder.tvPerfromsStatus.getTag())){ //包含,根據標記唯一確保滾動時背景色不會錯亂
                convertView.setBackgroundColor(mContext.getResources().getColor(
                        R.color.green));
            }else{ //不包含,預設背景色
                convertView.setBackgroundColor(mContext.getResources().getColor(
                        R.color.day_blue));
            }
        }
    }else{ //首次渲染listview或非首次渲染,不包含沒有掃描過的標籤,各項預設背景色
        if(holder.tvPerfromsStatus.getTag() != null && holder.tvPerfromsStatus.getTag().equals(mNps.get(position).getSubitemCode())){
            convertView.setBackgroundColor(mContext.getResources().getColor(
                    R.color.day_blue));
        }
    }
    return convertView;
}


public class ViewHolder{
    public CheckBox cbPerfroms;
    public TextView tvPerfromsStatus;
}


public List<NursingProject> getmNps() {
    return mNps;
}

public void setmNps(List<NursingProject> mNps) {
    this.mNps = mNps;
}

public Map<Integer, Boolean> getIsSelected() {
    return isSelected;
}

public void setIsSelected(Map<Integer, Boolean> isSelected) {
    this.isSelected = isSelected;
}

public Map<String, ArrayList<String>> getCacheSubCodeMap() {
    return cacheSubCodeMap;
}

/**
 * 初始化checkbox選中狀態
 * @param mNps
 */
public void initMapAboutCheckBox(){
    isSelected = new HashMap<Integer, Boolean>();  
    if(mNps != null && mNps.size() > 0){
        for (int i = 0; i < mNps.size(); i++) {  
            isSelected.put(i, false);  
        }  
    }        
}

/**
 * 掃描患者腕帶標籤,執行勾選的專案記錄成功時儲存資料
 * @param selectItem 掃描的患者腕帶標籤
 * @param subCode 勾選的專案ID
 */
public void setSelectItem(String selectItem,String subCode) {
    this.selectItem = selectItem;
    if(cacheSubCodeMap.containsKey(selectItem)){
        cacheSubCodeMap.get(selectItem).add(subCode);
    }else{
        cacheSelectItems = new ArrayList<String>();
        cacheSelectItems.add(subCode);
        cacheSubCodeMap.put(selectItem, cacheSelectItems);
    }
}

/**
 * 獲取已經選中的項資料
 * @author chixianpeng
 * @date 2015-8-6 15:09
 * @return
 */
public List<NursingProject> getSelectedItem(){
    List<NursingProject> selectedItemList = new ArrayList<NursingProject>();
    for (int i = 0; i < mNps.size(); i++) {
        if(isSelected.containsKey(i)){
            boolean isSelect = isSelected.get(i);
            if(isSelect){ //已經選中的
                NursingProject np = mNps.get(i);
                selectedItemList.add(np);
            }
        }
    }
    return selectedItemList;
}

}

//執行成功通知adapter更新勾選的項改變背景色為綠色
mNursingProjectAdapter.setSelectItem(mPrintCode, np.getSubitemCode());
mNursingProjectAdapter.notifyDataSetChanged();