如何在列表视图中使用复选框?

时间:2017-09-13 23:22:55

标签: android listview checkbox custom-adapter

我一直在尝试关注如何让checkboxlistview工作的S.O上的教程/帖子。我想用它做很多事情,但首先我想简单地检查项目的位置,但应用程序崩溃,我收到NullPointerException错误。

错误是(在此部分下面有更多内容):

    java.lang.NullPointerException at com.example.chris.tutorialspoint.SelectPhoneContactAdapter.getView(SelectPhoneContactAdapter.java:104)

第104行是:

convertView.setTag(v);

但对我而言,我似乎已经正确地遵循了这些教程,而且我不知道如何根据我的问题调整这些帖子:Getting NullPointerException in custom ListViewCrash in ListView at AbsListView.obtainView for ListActivity。你能告诉我出了什么问题吗?一切顺利,直到我开始尝试这些复选框。

以下是我的customadapter代码,SelectPhoneContactAdapter

public class SelectPhoneContactAdapter extends BaseAdapter {

    //define a list made out of SelectPhoneContacts and call it theContactsList
    public List<SelectPhoneContact> theContactsList;
    //define an array list made out of SelectContacts and call it arraylist
    private ArrayList<SelectPhoneContact> arraylist;
    boolean itemChecked[];
    Context _c;

    //define a ViewHolder to hold our name and number info, instead of constantly querying
    // findviewbyid. Makes the ListView run smoother
    ViewHolder v;

    public SelectPhoneContactAdapter(final List<SelectPhoneContact> selectPhoneContacts, Context context) {
        theContactsList = selectPhoneContacts;
        _c = context;
        this.arraylist = new ArrayList<SelectPhoneContact>();
        this.arraylist.addAll(theContactsList);
        itemChecked = new boolean[theContactsList.size()];

    }


    @Override
    public int getCount() {
        System.out.println("the amount in arraylist :" + arraylist.size());
        return arraylist.size();
    }

    @Override
    public Object getItem(int i) {
        return theContactsList.get(i);
    }

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

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)

    static class ViewHolder {
        //        In each cell in the listview show the items you want to have
//        Having a ViewHolder caches our ids, instead of having to call and load each one again and again
        TextView title, phone;
        CheckBox check;
    }

    @Override
    public View getView(final int i, View convertView, ViewGroup viewGroup) {

        //we're naming our convertView as view
        View view = convertView;


        if (view == null) {

            v = new ViewHolder();
            System.out.println("getview position :" + i);

            //if there is nothing there (if it's null) inflate the view with the layout
            LayoutInflater li = (LayoutInflater) _c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = li.inflate(R.layout.phone_inflate_listview, null);


            //      So, for example, title is cast to the name id, in phone_inflate_listview,
//        phone is cast to the id called no etc
            v.title = (TextView) view.findViewById(R.id.name);
            v.phone = (TextView) view.findViewById(R.id.no);
            v.check = (CheckBox) view.findViewById(R.id.checkBoxContact);

            convertView.setTag(v);

            //or else use the view (what we can see in each row) that is already there
        } else {
            view = convertView;

        }


//        store the holder with the view
        final SelectPhoneContact data = (SelectPhoneContact) theContactsList.get(i);

        //in the listview for contacts, set the name
        v.title.setText(data.getName());
        //in the listview for contacts, set the number
        v.phone.setText(data.getPhone());
        v.check.setChecked(false);

        v.check.setChecked(itemChecked[i]);

        v.check
                .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                                                 boolean isChecked) {
                        itemChecked[i] = isChecked;
                    }
                });

        // Return the completed view to render on screen
        return view;


    }
}

我的吸气者和二传手,SelectPhoneContact

public class SelectPhoneContact {

    String phone;

    public String getPhone() {return phone;}

    public void setPhone(String phone) {
        this.phone = phone;
    }

    String name;

    public String getName() {
        return name;
    }

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

    Boolean selected;

    public boolean isSelected() {
        return selected;
    }

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

如有必要,我可以发布更多代码。

1 个答案:

答案 0 :(得分:1)

考虑以下代码:

library(data.table) 
res <- setDT(df1)[, lapply(.SD, function(x) sum(x != shift(x, fill = x[1]))), 
                by = .(A_ID, Queues)][order(A_ID)]

setnames(res, 3:ncol(res), paste0(names(res)[3:ncol(res)], "ChangedVal"))[]
#   A_ID Queues COL1ChangedVal COL2ChangedVal
#1:    1  First              2              2
#2:    1 Second              0              0
#3:    2 Second              3              3
#4:    3  First              2              2
#5:    4  First              1              0

首先,您将@Override public View getView(final int i, View convertView, ViewGroup viewGroup) { ... View view = convertView; if (view == null) { ... view = li.inflate(R.layout.phone_inflate_listview, null); ... convertView.setTag(v); } ... } 的值分配给convertView变量。如果为null,则转到view语句,您可以通过ifview分配新值。

但是,您稍后会在li.inflate()语句中引用convertView。尽管您在上面写了if,但此时view = convertView仍为convertView

有两种方法可以解决这个问题。第一个选项是将null更改为convertView.setTag(v)。另一种是删除这一行:

view.setTag(v)

只需更改您引用View view = convertView; 的任何地点即可使用view。没有必要引入新的convertView变量;您可以直接使用View view