2

「学生」の出席・欠席のチェックリストを作成しています。私は listView を作成し、その詳細と右側を正常に作成しています。ImageView「X」。行をタップすると、「X」がチェックマークに変わります! そして、このプログラムが機能するために必要な他のものをうまく変更します。

私の問題は「でした」、「チェックされた」行の1つをスクロールして表示から外すと、「X」に戻ります。ビューホルダーを使用してこれを解決しました。

私の現在の問題は、たとえば、6人の学生のリストにあります。学生 1 を「ティック」すると、学生 5 もティックに変更されます (見えないにもかかわらず)。そして、生徒 2 にチェックを入れると、生徒 6 にチェックが入ります。これは逆にも機能します。「ランダムに変更された行」に対して onClick コードが実行されていないことはわかっています。それは私にとって非常に奇妙です、ここに私のコードがあります:

ListView listView = (ListView) findViewById(R.id.student_listview);
    listView.setBackgroundColor(Color.TRANSPARENT); 
    listView.setCacheColorHint(Color.TRANSPARENT);
    listView.setAdapter(new MySimpleArrayAdapter(this, studentIDarr)); 
    listView.setOnItemClickListener(new OnItemClickListener() {
          public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {

            ImageView img = (ImageView) view.findViewById(R.id.icon);

            if(img.getTag().toString().equals("checked")) {
                checkListArr.set(position, "Absent");
                img.setImageResource(R.drawable.remove);
                img.setTag("unchecked");
            } else {
                checkListArr.set(position, "Present");
                img.setImageResource(R.drawable.checked);
                img.setTag("checked");
            }  
          }
        }); 

そして、ViewHolder を備えたアダプター...

static class ViewHolder {
      TextView fname;
      TextView sname;
      TextView ID;
      TextView email;
      ImageView status;
    }

public class MySimpleArrayAdapter extends ArrayAdapter<String> {
      private final Context context;
      private final ArrayList<String> values;

      public MySimpleArrayAdapter(Context context, ArrayList<String> values) {
        super(context, R.layout.list_class_item, values);
        this.context = context;
        this.values = values;
      }

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

          LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

          View vi = convertView;
          ViewHolder holder;
          if (convertView == null) {
                vi = inflater.inflate(R.layout.list_student_item, null);
                holder = new ViewHolder();
                holder.fname = (TextView) vi.findViewById(R.id.tvFname);
                holder.sname = (TextView) vi.findViewById(R.id.tvSname);
                holder.ID = (TextView) vi.findViewById(R.id.tvStudentID);
                holder.email = (TextView) vi.findViewById(R.id.tvEmail);
                holder.status= (ImageView) vi.findViewById(R.id.icon);

                if(checkListArr.get(position).toString().equals("Absent")) {
                    holder.status.setTag("unchecked");
                } else if (checkListArr.get(position).toString().equals("Present")) {
                    holder.status.setTag("checked");
                }       

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

        if(checkListArr.get(position).toString().equals("Absent")) {
            holder.status.setTag("unchecked");
        } else if (checkListArr.get(position).toString().equals("Present")) {
            holder.status.setTag("checked");
        }           

        holder.ID.setText(values.get(position));
        holder.fname.setText(fNameArray.get(position));
        holder.sname.setText(sNameArray.get(position));
        holder.email.setText(emailArray.get(position));
        return vi;
      }
    } 

誰か私のコードの明らかな欠陥を指摘してください! 読んでくれてありがとう!

4

2 に答える 2

1

ListView が以前のビューをリサイクルする方法を誤解しています。これらの変更は、基になるデータ モデル内に保存する必要があります。

public class Model {

  private String fname;
  private String sname;
  private String email;
  private boolean selected;

  public Model(String fname, String sname, String email) {
    this.fname = fname;
    selected = false;
    //etc
  }

  public String getName() {
    return fname;
  }

  public void setName(String fname) {
    this.fname = fname;
  }

  public boolean isSelected() {
    return selected;
  }

  public void setSelected(boolean selected) {
    this.selected = selected;
  }
  //etc
} 

アダプタ:

private final List<Model> list;
    private final Activity context;

    public InteractiveArrayAdapter(Activity context, List<Model> list) {
        super(context, R.layout.yourlayout, list);
        this.context = context;
        this.list = list;
    }

    static class ViewHolder {
        protected TextView text;
        protected CheckBox checkbox;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;
        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.rowbuttonlayout, null);
            final ViewHolder viewHolder = new ViewHolder();
            viewHolder.text = (TextView) view.findViewById(R.id.label);
            viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
            viewHolder.checkbox
                    .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

                        @Override
                        public void onCheckedChanged(CompoundButton buttonView,
                                boolean isChecked) {
                            Model element = (Model) viewHolder.checkbox
                                    .getTag();
                            element.setSelected(buttonView.isChecked());

                        }
                    });
            view.setTag(viewHolder);
            viewHolder.checkbox.setTag(list.get(position));
        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
        }
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.text.setText(list.get(position).getName());
        holder.checkbox.setChecked(list.get(position).isSelected());
        return view;
    }
于 2013-03-28T11:15:43.820 に答える
0

の必要はありませんViewHolder

convertViewすでに膨らんだビューです。値が null の場合はインフレートします。次に、ビューを見つけて、new または convertView の位置に応じて適切な値を設定します。

SparseBooleanArray値を切り替えるメソッドを使用してアダプタに実装し<int Position, boolean Absence> ます。そのような値を保持および挿入するための最適化された HashMap のようなクラスです。AdapterView<?>それと対話するためのアダプターを提供します。

ListView は、処理と保存のために選択されたすべてのビューを含む同様の配列へのアクセスも提供します。

于 2013-03-28T11:20:02.410 に答える