getView()方法改变listview项目的位置

时间:2014-09-11 23:44:33

标签: android sqlite listview android-listview

我有一个带有已检查textview和两个textview的列表视图,但是,我的getView方法在滚动时不断更改listview项,值和复选框状态都保存到sqlite数据库中。我尝试了所有可能的解决方案,花了4个小时试图修复它。 任何帮助表示赞赏。唯一有效的解决方案是在getView()的开头将convertview设置为null,它落后于listview。

目标:正确制作列表视图显示项目而不随意更改其位置。

有需要的人的最终工作代码:

   @Override
public View getView( final int position, View convertView, ViewGroup parent) {
    viewHolder = null;
    if(convertView == null){

        convertView = inflater.inflate(R.layout.sin_item,null);
        viewHolder = new HolderCo();
        viewHolder.box = (CheckBox)convertView.findViewById(R.id.coco);
        viewHolder.subject = (TextView)convertView.findViewById(R.id.subject_com);
        viewHolder.date = (TextView)convertView.findViewById(R.id.date_co);




        convertView.setTag(viewHolder);
    }
    else{
        viewHolder = (HolderCo)convertView.getTag();
    }

    viewHolder.position = position;


    viewHolder.box.setText(list.get(viewHolder.position).getWhats());
    viewHolder.subject.setText(list.get(viewHolder.position).getSubject());

    if(list.get(viewHolder.position).isSelected()) {
        viewHolder.box.setOnCheckedChangeListener(null);
        viewHolder.box.setChecked(true);
        viewHolder.box.setPaintFlags(viewHolder.box.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
    }else{
        viewHolder.box.setOnCheckedChangeListener(null);
        viewHolder.box.setChecked(false);
        viewHolder.box.setPaintFlags(viewHolder.box.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
    }

    if(dator.equals("d"))
        viewHolder.date.setText(list.get(viewHolder.position).getDay()+"/"+list.get(viewHolder.position).getMonth()+"/"+list.get(viewHolder.position).getYear());

    if(dator.equals("m"))
        viewHolder.date.setText(list.get(viewHolder.position).getMonth()+"/"+list.get(viewHolder.position).getDay()+"/"+list.get(viewHolder.position).getYear());



    if(dator.equals("y"))
        viewHolder.date.setText(list.get(viewHolder.position).getYear()+"/"+list.get(viewHolder.position).getMonth()+"/"+list.get(viewHolder.position).getDay());







    viewHolder.box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if(buttonView.isChecked()) {
                list.get(position).setSelected(true);
                db.updateState(list.get(position),true);
                buttonView.setPaintFlags(buttonView.getPaintFlags()| Paint.STRIKE_THRU_TEXT_FLAG);
                if(PreferenceManager.getDefaultSharedPreferences(ctx).getBoolean("add_mark_dialog",true))
                buttonView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dialoging(viewHolder.position);
                    }
                });

            }else{
                buttonView.setOnClickListener(null);
                list.get(position).setSelected(false);
                db.updateState(list.get(position), false);
                buttonView.setPaintFlags(buttonView.getPaintFlags()&(~Paint.STRIKE_THRU_TEXT_FLAG));

            }
        }
    });







    return convertView;
}

2 个答案:

答案 0 :(得分:1)

通过这样做:

viewHolder.box.setTag(position);
viewHolder.date.setTag(position);
viewHolder.subject.setTag(position);

您将标记设置为视图到创建它们的第一个位置 因此,当使用非空getView()(之前已回收)调用convertView时,其viewHolder中的标记仍然指向该位置。

将这些setTag()来电移到if()之外,以便为新回合的视图设置新位置。

BTW我宁愿用

替换所有这些
viewHolder.position = position; // outside if()

并在任何地方使用它(整数)x.getTag()

更新:你还必须这样做:

viewHolder.box.setOnCheckedChangeListener(null);

之前:

viewHolder.box.setChecked(...);

因为否则它可以触发你很可能不想要的前一个听众。

答案 1 :(得分:1)

您可以使用if条件有条件地更新视图。您需要提供相应的else块,将视图重置为默认值。

例如,

if(dator.equals("d"))
    viewHolder.date.setText(...);

if(dator.equals("m"))
    viewHolder.date.setText(...);

if(dator.equals("y"))
    viewHolder.date.setText(...);

需要像

if(dator.equals("d"))
    viewHolder.date.setText(...);

else if(dator.equals("m"))
    viewHolder.date.setText(...);

else if(dator.equals("y"))
    viewHolder.date.setText(...);

else
    viewHolder.date.setText("some default value");

同样重置viewHolder.box.setPaintFlags()中的默认值。

原因是ListView次观看次数被回收。回收的观点并不像通货膨胀之后那样处于原始状态。相反,它们将处于它们被回收之前的状态,可能包含先前使用该视图的列表行中的数据。