2015-02-10 59 views
0

ListView适配器确实奇怪的事情。方法getChecked()(下面显示的适配器代码)不会返回我期望的值。仿佛他迟到了一步。ListView适配器行为奇怪

为了解,我将解释:我使用的是自定义ListView,每个项目包含一个CheckBox(和其他Views)。我想按下按钮显示选中元素的位置。这使得方法getChecked()。 但是会发生以下情况:我检查第二和第四列表项并单击按钮,结果 - [],然后检查第五项,结果 - [2,4],然后清除所有CheckBoxes,结果[2,4,5]当我再次点击按钮时,我收到 - []。结果晚了一步。

public class ContactAdapter extends BaseAdapter { 

private LayoutInflater inflater; 
private ArrayList<Contact> contacts; 

private boolean isCheckBoxVisible; 
private View view; 

private int[] colors = {Color.BLACK, Color.BLUE, Color.RED, Color.GRAY, Color.GREEN}; 
private int currentMaleColor; 
private int currentFemaleColor; 

public ContactAdapter(Context context, ArrayList<Contact> contacts) { 
    this.contacts = contacts; 
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    isCheckBoxVisible = false; 
    setColors(); 
} 

@Override 
public int getCount() { 
    return contacts.size(); 
} 

@Override 
public Object getItem(int position) { 
    return contacts.get(position); 
} 

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

private Contact getContact(int position) { 
    return (Contact) getItem(position); 
} 

public void setCheckBoxVisibility(boolean isVisible) { 
    isCheckBoxVisible = isVisible; 
    notifyDataSetChanged(); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    view = convertView; 
    if (view == null) { 
     view = inflater.inflate(R.layout.contact_item, parent, false); 
    } 

    CheckBox cb = (CheckBox) view.findViewById(R.id.lv_box); 
    if (isCheckBoxVisible) { 
     cb.setVisibility(View.VISIBLE); 
    } else { 
     cb.setVisibility(View.INVISIBLE); 
    } 

    Contact c = getContact(position); 
    ((TextView) view.findViewById(R.id.lv_name)).setText(c.getName() + " " + c.getSurname()); 
    ((ImageView) view.findViewById(R.id.lv_img)).setImageBitmap(c.getPhoto()); 

    if (c.getSex().equals("Man")) { 
     view.setBackgroundColor(currentMaleColor); 
    } else { 
     view.setBackgroundColor(currentFemaleColor); 
    } 

    boolean isCheck = ((CheckBox) view.findViewById(R.id.lv_box)).isChecked(); 
    contacts.get(position).setChecked(isCheck); 
    return view; 
} 

public ArrayList<Integer> getChecked() { 
    notifyDataSetChanged(); 
    ArrayList<Integer> IDs = new ArrayList<Integer>(); 
    for (Contact c : contacts) { 
     if (c.isChecked()) IDs.add(c.getID()); 
    } 
    return IDs; 
} 

private void setColors() { 
    int colorM = Integer.parseInt(MainActivity.sp.getString("lp_colorM", "0")); 
    int colorW = Integer.parseInt(MainActivity.sp.getString("lp_colorW", "0")); 

    currentMaleColor = colors[colorM]; 
    currentFemaleColor = colors[colorW]; 
} 

} 

在我的活动我用我的转接器,像这样:

@Override 
protected void onResume() { 
    super.onResume(); 
    adapter = new ContactAdapter(getApplicationContext(), contacts); 
    list.setAdapter(adapter); 
} 

我的按钮的代码:

ArrayList<Integer> al = adapter.getChecked(); 
Toast.makeText(this, al.toString(), Toast.LENGTH_LONG).show(); 

你觉得这个怎么样?我会很乐意提供任何帮助。

+0

'contacts.get(位置).setChecked(isCheck);如果联系人仅在刷新视图时才更新状态,而不是在单击视图时更新状态。使用CB上的checkedchangedlistener立即检测变化。 – njzk2 2015-02-10 14:32:40

+0

好主意,** njzk2 **。我会尽力去做。但后来我有一个问题 - 为什么现在的方法getChecked()会给出迟到的结果?我认为如果适配器没有更新,这种方法现在不应该工作。 – Fredisson 2015-02-10 16:23:05

+0

,因为getChecked会将调用的结果返回给'setChecked',由于它只根据convertView的状态进行更新而被延迟。 (如果你有足够的项目滚动,它会给出更奇怪的结果。) – njzk2 2015-02-10 16:25:24

回答

0

在njzk2的建议,我改变了它:

boolean isCheck = ((CheckBox) view.findViewById(R.id.lv_box)).isChecked(); 
contacts.get(position).setChecked(isCheck); 

在此:

CheckBox checkBox = (CheckBox) view.findViewById(R.id.lv_box); 
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
     contacts.get(position).setChecked(isChecked); 
    } 
}); 

现在工程:)

0

试图得到的观点,如果convertView ==空状态

if (convertView == null) { 
      holder = new Holder(); 
      convertView = mInflator.inflate(R.layout.row_viewproduct, null); 
      convertView.setTag(holder); 
     } else { 
      holder = (Holder) convertView.getTag(); 
     } 

//将数据从持有人查看

+0

谢谢您的回答,但班级是什么 - 持有人?你什么意思? – Fredisson 2015-02-10 15:39:17

+0

我试图按照你的建议去做,但它不起作用。 – Fredisson 2015-02-10 16:04:34

+0

'view = convertView; (view == null){ view = inflater.inflate(R.layout.contact_item,parent,false); } else { view =(View)convertView.getTag(); }' – Fredisson 2015-02-10 16:06:07

0

这不是答案,但希望说,你可以使用下面

private void setColors() { 
     int colorM = Integer.parseInt(MainActivity.sp.getString("lp_colorM", "0")); 
     int colorW = Integer.parseInt(MainActivity.sp.getString("lp_colorW", "0")); 

     if(colorM < 5){ 
      currentMaleColor = colors[colorM]; 
     } 

     if(colorW < 5){ 
      currentFemaleColor = colors[colorM]; 
     } 
    } 

要回答你的问题看的观点持有者模式 http://ricston.com/blog/optimising-listview-viewholder-pattern/

+0

Kevin Crain,非常感谢您的评论。出于某种原因,我之前没有注意到它,但现在纠正了我的代码。 – Fredisson 2015-02-10 14:06:28

+0

它是一种乐趣,你可以使用colorM 2015-02-10 14:21:08