带有复选框的ListView

时间:2015-07-23 12:32:58

标签: java android android-listview

我想用复选框制作一个简单的列表视图。问题是,每当我点击一个复选框时,我的应用程序会因NullPointerException而崩溃,我真的无法弄清楚问题是什么。

这是我的java代码:

public class ShowTypes extends Activity {

    MyCustomAdapter dataAdapter = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_types);

        //Generate list View from ArrayList
        displayListView();

        Button btn1 = (Button)findViewById(R.id.nextmap);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                startActivity(new Intent(ShowTypes.this, map.class));
            }
        });

    }

    private void displayListView() {

        //Array list of countries
        ArrayList<TypePoi> typeList = new ArrayList<TypePoi>();
        TypePoi country = new TypePoi("All of them",false);
        typeList.add(country);
        country = new TypePoi("tourist attractions",false);
        typeList.add(country);
        country = new TypePoi("parks",false);
        typeList.add(country);
        country = new TypePoi("restaurants",false);
        typeList.add(country);
        country = new TypePoi("hotels",false);
        typeList.add(country);
        country = new TypePoi("tube stations",false);
        typeList.add(country);

        //create an ArrayAdaptar from the String Array
        dataAdapter = new MyCustomAdapter(this,
                R.layout.typepoi_info, typeList);
        ListView listView = (ListView) findViewById(R.id.list_types);
        // Assign adapter to ListView
        listView.setAdapter(dataAdapter);


        listView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                // When clicked, show a toast with the TextView text
                TypePoi country = (TypePoi) parent.getItemAtPosition(position);
                //  Toast.makeText(getApplicationContext(),
                //          "Clicked on Row: " + country.getName(),
                //           Toast.LENGTH_LONG).show();
            }
        });

    }

    private class MyCustomAdapter extends ArrayAdapter<TypePoi> {

        private ArrayList<TypePoi> typeList;

        public MyCustomAdapter(Context context, int textViewResourceId,
                               ArrayList<TypePoi> typeList) {
            super(context, textViewResourceId, typeList);
            this.typeList = new ArrayList<TypePoi>();
            this.typeList.addAll(typeList);
        }

        private class ViewHolder {
            CheckBox name;
        }

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

            ViewHolder holder = null;
            Log.v("ConvertView", String.valueOf(position));

            if (convertView == null) {
                LayoutInflater vi = (LayoutInflater)getSystemService(
                        Context.LAYOUT_INFLATER_SERVICE);
                convertView = vi.inflate(R.layout.typepoi_info, null);

                holder = new ViewHolder();
                holder.name = (CheckBox) convertView.findViewById(R.id.checkBox2);
                convertView.setTag(holder);

                holder.name.setOnClickListener( new View.OnClickListener() {
                    public void onClick(View v) {
                        CheckBox cb = (CheckBox) v ;
                        TypePoi country = (TypePoi) cb.getTag();
                        Toast.makeText(getApplicationContext(),
                                "Clicked on : " + cb.getText(),
                                Toast.LENGTH_LONG).show();
                        country.setSelected(cb.isChecked());
                    }
                });
            }
            else {
                holder = (ViewHolder) convertView.getTag();
            }

            TypePoi country = typeList.get(position);
            holder.name.setText(country.getName());
            holder.name.setChecked(country.isSelected());

            return convertView;

        }

    }
}

activity_show_types.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#FFE5B4">

    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:padding="10dp"
        android:layout_gravity="center"
        android:text="Pick type:" android:textSize="20sp" />


    <Button
        android:id="@+id/nextmap"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#EBD1A0"
        android:text="Show map" />

    <ListView android:id="@+id/list_types" android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

typepoi_info.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="6dip" >

    <CheckBox
        android:id="@+id/checkBox2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:text="CheckBox" />


</RelativeLayout>

和我的logcat

 FATAL EXCEPTION: main
    java.lang.NullPointerException
            at com.example.diana.track.ShowTypes$MyCustomAdapter$1.onClick(ShowTypes.java:120)
            at android.view.View.performClick(View.java:4421)
            at android.widget.CompoundButton.performClick(CompoundButton.java:100)
            at android.view.View$PerformClick.run(View.java:17903)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5214)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
            at dalvik.system.NativeStart.main(Native Method)

知道可能是什么问题吗?

3 个答案:

答案 0 :(得分:3)

您可以通过使用简单代码实现此目的,Listview已经具有属性ChoiceMode。您可以将其设置为CHOICE_MODE_MULTIPLE。

以下是来自android示例项目的代码示例 -

https://android.googlesource.com/platform/development/+/master/samples/ApiDemos/src/com/example/android/apis/view/List11.java?autodive=0%2F%2F

完整代码为 -

public class List11 extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_multiple_choice, GENRES));

        final ListView listView = getListView();
        listView.setItemsCanFocus(false);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }
    private static final String[] GENRES = new String[] {
        "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",
        "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
    };
}

答案 1 :(得分:2)

您忘记了代码中的一个重要行,

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

    TypePoi country = typeList.get(position);
    holder.name.setText(country.getName());
    holder.name.setChecked(country.isSelected());

    // Try inserting this line
    holder.name.setTag(country);

    return convertView;
}

说明

它会引发NullPointerException,因为在onClick中,

holder.name.setOnClickListener( new View.OnClickListener() {
    public void onClick(View v) {
        CheckBox cb = (CheckBox) v ;
        TypePoi country = (TypePoi) cb.getTag();
        Toast.makeText(getApplicationContext(),
                "Clicked on : " + cb.getText(),
                Toast.LENGTH_LONG).show();
        country.setSelected(cb.isChecked()); // throws NullPointerException!
    }
});

此处的cb.getTag()将导致始终返回null

因此,countrynullcountry.setSelected(cb.isChecked())抛出异常。

答案 2 :(得分:1)

onClick()中进行更改,它会正常工作。

CheckBox cb = (CheckBox) v.findById(R.id.checkBox2);