Reputation: 489
I'm trying to make a simple tasklist in Android using Eclipse. The layout i'm trying to build is this:
I want the tasks to be the groups, and under each task, 2 childs with task description and task's limit date.
At the right side of the task/group, I wanted a checkbox for marking tasks as done, but I don't really know how to do that. I even have problems using adapters for my ExpandableListView (all questions I manage to find talk about creating ExpandableListView from scrap using ListViews & Maps of Strings, but I want to use an already created ExpandableListView in my XML layout, if that's possible) or thinking how I'm going to add tasks from the input (the input is an AlertDialog appearing when you press the button).
Any ideas will be appreciated, and sorry for my English (not my mother language).
Upvotes: 1
Views: 5449
Reputation: 5636
The way i'd do something like this is to make your expandable listview utilizing a custom adapter (these extend the baseexpandableadapter class). Then you have the ability to inflate or create different views for your group and child views. This is an example of how you might set it up if you're using an expandable listactivity (vs regular activity with expandable listview):
public class ExpandableList1 extends ExpandableListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set up our adapter
ExpandableListAdapter mAdapter = new MyExpandableListAdapter(this);
setListAdapter(mAdapter);
}
// The custom adapter part
public class MyExpandableListAdapter extends BaseExpandableListAdapter {
// Sample data set. children[i] contains the children (String[]) for groups[i].
private String[] groups = { "Task1", "Task2", "Task3", "Task4"};
private String[][] children = {
{ "Task Description", "Task time limit date" },
{ "Task Description", "Task time limit date" },
{ "Task Description", "Task time limit date" },
{ "Task Description", "Task time limit date" }
};
public MyExpandableListAdapter(Context context) {
super();
this.context = context;
}
private Context context;
static class ViewHolder {
TextView text;
CheckBox checkbox;
}
public Object getChild(int groupPosition, int childPosition) {
return children[groupPosition][childPosition];
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public int getChildrenCount(int groupPosition) {
return children[groupPosition].length;
}
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
return convertView;
}
public Object getGroup(int groupPosition) {
return groups[groupPosition];
}
public int getGroupCount() {
return groups.length;
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
LayoutInflater viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = viewInflater.inflate(R.layout.mtopics_groupview, parent, false);
holder = new ViewHolder();
holder.text = (TextView)convertView.findViewById(R.id.mtopicsgrouptv);
holder.checkbox = (CheckBox)convertView.findViewById(R.id.cb_group);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(getGroup(groupPosition).toString());
return convertView;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public boolean hasStableIds() {
return true;
}
}
You have the ability to create your group views and child views programatically or to you can inflate these from xml. In my example, i've inflated from xml for just the group view as it is far easier for more complex views. I know that pattern seems like a round-about method for the use of the two line inflate code, but it will help the performance of your view tremendously. You can learn more about it here: http://www.youtube.com/watch?v=wDBM6wVEO70. As for now, the xml is pretty simple, it's just a textview and a checkbox. (small hint: checkboxes in groupviews must have "focusable" set to false AND can't be directly adjacent the group view indicator, or the group view won't be able to expand)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<CheckBox
android:id="@+id/cb_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:checked="true"
android:focusable="false" />
<TextView
android:id="@+id/mtopicsgrouptv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="40dp"
android:focusable="false"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
I didn't do the childview, but depending on what you want to do with it, you can model it after the group view. you can just put a textview in there and set the text based of the child position. BUT i gotta warn you, as of now you'll quickly find that your checkbox states are gonna be wacky whenever you click them. sometimes the check will move or dissapear or not work at all. If you wanna know why i could tell you, but i'll just post the solution for now. You have to set up an arraylist or map or anything really to hold the checkbox states and then load them (since their positions will correspond). Here is how i'd do it in my getGroupView portion.
// make the list
ArrayList<Boolean> group_check_states = new ArrayList<Boolean> (groups.length);
for(int i = 0; i < groups.length; i++) {
group_check_states.add(true);
}
// load the checkstates
if ((group_check_states.get(groupPosition)) == true) {
holder.checkbox.setChecked(true);
} else {
holder.checkbox.setChecked(false);
}
// save the checkstates
holder.checkbox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (holder.checkbox.isChecked()) {
group_check_states.set(groupPosition, true);
} else {
group_check_states.set(groupPosition, false);
}
}
});
You can also put your checkbox action code in there, too. Now the adapter looks the part, but it might be too simple for what you intend. you want to be able to set the tasks dynamically based on what was inputted your alert dialog. In that case, you wouldn't want to be using that simply array I that used (groups and children), you might want to load from an arraylist, or other type of list that you can dynamically add and remove things dynamically, which would be modified by your alert dialog.
i hope it helped, but i'm sure there'll be some more issues along the way. just holla if somethings comes up.
Upvotes: 8