My app shows a ListView
with a TextView
and checkbox for each row. The TextView
contains different types of food.
Each row has one checkbox. I want to change that. Each type of food has an attribute called numberOfPortions
. This number should determine the number of checkboxes in the row.
For example:
ListItem Beans numberOfPortions = 3
This means that the row in my ListView
with beans should have 3 checkboxes instead of previously 1 checkbox.
How can I achieve that? If I add three checkboxes to my row layout, three checkboxes will be shown in each row, but there are also rows were numberOfPortions
is 1 or 2 so that only one or two checkboxes should be shown.
This image shows how my list should look like:
EDIT:
I added this piece of code to my Adapter. It should add new CheckBoxes to each row dependent on the Integer numCheckBox:
int numCheckBox = item.numCheckBox;
CheckBox[] cb = new CheckBox[numCheckBox];
for(int i = 0; i < numCheckBox; i++){
cb[i] = new CheckBox(parent.getContext());
holder.rl.addView(cb[i]);
}
I am getting a NullPointerException
. But, I don't understand why it keeps occurring?
Process: com.example.xx.myapplication, PID: 23887
java.lang.NullPointerException
at com.example.timofocken.myapplication.ItemListAdapter.getView(ItemListAdapter.java:103)
at android.widget.AbsListView.obtainView(AbsListView.java:2458)
at android.widget.ListView.makeAndAddView(ListView.java:1891)
at android.widget.ListView.fillDown(ListView.java:792)
Here is my Adapter:
public class ItemListAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ArrayList<Object> itemArray;
int resIdImage;
private static final int TYPE_ListElement = 0;
private static final int TYPE_DIVIDER = 1;
public ItemListAdapter(Context context, ArrayList<Object> itemArray, int resource) {
this.itemArray = itemArray;
this.resIdImage = resource;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return itemArray.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public Object getItem(int position) {
return itemArray.get(position);
}
@Override
public int getViewTypeCount() {
// TYPE_PERSON and TYPE_DIVIDER
return 2;
}
@Override
public int getItemViewType(int position) {
if (getItem(position) instanceof ItemList) {
return TYPE_ListElement;
}
return TYPE_DIVIDER;
}
@Override
public boolean isEnabled(int position) {
return (getItemViewType(position) == TYPE_ListElement);
}
public class DataHolder{
ImageView imageView;
TextView textView;
CheckBox cb;
RelativeLayout rl;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
DataHolder holder = null;
int type = getItemViewType(position);
if (convertView == null) {
switch (type) {
case TYPE_ListElement:
convertView = inflater.inflate(resIdImage, parent, false);
holder = new DataHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.image);
holder.textView = (TextView) convertView.findViewById(R.id.nameLabel);
holder.cb = (CheckBox) convertView.findViewById(R.id.checkbox);
holder.rl = (RelativeLayout) convertView.findViewById(R.id.row_layout);
convertView.setTag(holder);
break;
case TYPE_DIVIDER:
convertView = inflater.inflate(R.layout.row_header, parent, false);
break;
}
} else {
holder = (DataHolder)convertView.getTag();
}
switch (type) {
case TYPE_ListElement:
ItemList item = (ItemList) getItem(position);
holder.textView.setText(item.getTitle());
holder.imageView.setImageResource(item.resIdImage);
holder.cb.setChecked(item.checked);
int numCheckBox = item.numCheckBox;
CheckBox[] cb = new CheckBox[numCheckBox];
for(int i = 0; i < numCheckBox; i++){
cb[i] = new CheckBox(parent.getContext());
holder.rl.addView(cb[i]);
}
break;
case TYPE_DIVIDER:
TextView title = (TextView)convertView.findViewById(R.id.headerTitle);
String titleString = (String)getItem(position);
title.setText(titleString);
break;
}
return convertView;
}
}
My row layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher"
android:layout_gravity="center"
android:layout_margin="20dp"/>
<TextView
android:id="@+id/nameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_margin="20dp"
android:text="Name"
android:layout_weight="1" />
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_gravity="right|center"
android:gravity="right|center" />
</LinearLayout>
I am not quite sure if this is the graceful solution to the problem specified in your question. However, after checking the desired UI and your comment later above, I think there is a workaround which involves less trouble.
I would like to suggest keeping three checkboxes (as three is the max limit of checkboxes a row can have) in your row layout. So the final layout of each row should look like the following.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@mipmap/ic_launcher"
android:layout_gravity="center"
android:layout_margin="20dp"/>
<TextView
android:id="@+id/nameLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_margin="20dp"
android:text="Name"
android:layout_weight="1" />
<CheckBox
android:id="@+id/checkbox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_gravity="right|center"
android:gravity="right|center" />
<CheckBox
android:id="@+id/checkbox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_gravity="right|center"
android:gravity="right|center" />
<CheckBox
android:id="@+id/checkbox3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_gravity="right|center"
android:gravity="right|center" />
</LinearLayout>
The DataHolder
class inside your Adapter should look like this.
public class DataHolder{
ImageView imageView;
TextView textView;
CheckBox cb1;
CheckBox cb2;
CheckBox cb3;
RelativeLayout rl;
}
Then in your getView
function take three different references.
holder.cb1 = (CheckBox) convertView.findViewById(R.id.checkbox1);
holder.cb2 = (CheckBox) convertView.findViewById(R.id.checkbox2);
holder.cb3 = (CheckBox) convertView.findViewById(R.id.checkbox3);
Then modify the switch case like the following.
int numCheckBox = item.numCheckBox;
if(numCheckBox == 1) {
cb1.setVisibility(View.VISIBLE);
cb2.setVisibility(View.GONE);
cb3.setVisibility(View.GONE);
} else if(numCheckBox == 2) {
cb1.setVisibility(View.VISIBLE);
cb2.setVisibility(View.VISIBLE);
cb3.setVisibility(View.GONE);
} else if(numCheckBox == 3) {
cb1.setVisibility(View.VISIBLE);
cb2.setVisibility(View.VISIBLE);
cb3.setVisibility(View.VISIBLE);
}
Once the items are populated correctly, you can receive the actions on those checkbox items accordingly.
I hope you get the idea. Please let me know if there is anything else I can help you with.
Edit:
You do not have to loop through the checkboxes as you can explicitly set the onCheckedChangeListener
to each of your checkbox which will save your desired values in SQLite. The invisible checkbox will not have any effect on their listener. Hope that helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.