Coding Android Dynamic Expanding Lists--glad that's over (AGAIN)

Published May 01, 2012
Advertisement
One of the GUI elements I wanted for Titan Trivia was an expandable list for the Trivia question categories and subcategories. Easy enough to do, or so I thought. All the example code that I found online and in my texts were filled with pre-defined data. In other words, you had to know beforehand what your parent and child elements were going to be and hard code them in. I needed something a little more flexible, because my parent and child elements were changing regularly. After more consternation over the code than I'd care to admit, I finally got my expandable lists reading and displaying the trivia question categories and subcategories without me having to hard code ahead of time.

Figuring out how to do that was frustrating at times, but of course satisfying when I finished. I decided to put together a quick 'how to' in case there are others who find they may want to do the same thing. I have no doubt there are more elegant ways of implementing what I have here, but at the very least I know this code works. Instead of pulling out the code I've implemented in Titan Trivia, yesterday I sat down and put together a quick app that demonstrates the functionality.

The app is called "TopicNotes", and it does what it sounds like. It lets you write a note with a topic. If you write another note with the same Topic, it will file that note under the same Parent list header, as in this screenshot:


expandableLists1.png


The interface is simple. Just a single button and an expandable list below it. When you click the button, you get a dialog box:


expandableLists2.png


When you click OK, the topic you just entered a note for goes to the top of your list on the main screen:


expandableLists3.png


Yes, I know this isn't pretty, and there are some glaring omissions in the app (for example, there's no delete function). I may add to it over time, but for now, I just want to demo the dynamic expandable list code.

First, you'll need to override the BaseExpandableListAdapter. Depending on your skill level, this may sound intimidating (I admit I was a bit put off when someone casually suggested it), but it's not that hard for what we're doing here (there are several variations of this to be found online, but if you want to see the code I used for this example, you can find it here: http://numberedmount...overriding.html). I may write a comprehensive tutorial to cover this part as well if there's interest, but for now I'll stay focused.

So, into the main Activity file (TopicNotesActivity.java) I write a function to return an instance of the modified adapter. Note that it calls two additional methods: getAllTopics() and getAllTopicNotes() that return a String array and a 2-dimensional String array respectively. These arrays are required by the ModifiedExpandableListAdapter instance. The Topics and Notes are saved away in a SQLite3 database table.

[source lang="java"]
[size=2] private ModifiedExpandableListAdapter getAllTopicNotes(){
String[] topics=getAllTopics();
String[][] contents = getAllNotes(topics);
ModifiedExpandableListAdapter adapter=new ModifiedExpandableListAdapter(this,topics,contents);

return adapter;

}

private String[] getAllTopics(){
String[] topics=null;
int index=0;
int size=0;

SQLiteDatabase db = topic_notes_data.getReadableDatabase();
Cursor cursor = db.query(TOPICNOTES_TABLE, FROM, null, null, TOPIC, null, ORDER_BY);
size = cursor.getCount();
topics = new String[size];

while(cursor.moveToNext()){
if(cursor.getString(1).length()>0){
topics[index]=cursor.getString(1);
index++;
}

}
cursor.close();


return topics;

}
private String[][] getAllNotes(String[] topics){
String[] temp={};
String[][] notes=null;
int index=0;
//int size=topics.length;
notes = new String[topics.length][];

SQLiteDatabase db = topic_notes_data.getReadableDatabase();

for(int i=0;i int topicsize=0;
index=0;
Cursor cursor = db.query(TOPICNOTES_TABLE, FROM, "TOPIC=?", new String[]{topics}, null, null, null);
topicsize=cursor.getCount();
temp = new String[topicsize];
while(cursor.moveToNext()){
temp[index] = cursor.getString(2);
index++;
}
cursor.close();
notes=temp;
}


return notes;
}


[/source]

Now that these methods are written, I can implement them in the activity onCreate:
[source lang="java"]
[size=2]@Override public void onCreate(Bundle savedInstanceState) {
[size=2]super.onCreate(savedInstanceState);
[size=2]setContentView(R.layout.main);
[size=2]topic_notes_data = new TopicNotesData(this);
[size=2]final Button btnAddTopicNote = (Button) findViewById(R.id.Button_AddTopicNote);

[size=2]btnAddTopicNote.setOnClickListener(new View.OnClickListener() {
[size=2]@Override public void onClick(View v) {
[size=2]showDialog(ADD_TOPIC_NOTE_DLG_ID);
[size=2]}
[size=2]});
[size=2]//Here we assign the ExpandableListView we defined in our xml file to the code
[size=2]ExpandableListView list = (ExpandableListView)findViewById(R.id.ExpList_Topics);
[size=2]list.setGroupIndicator(null);
[size=2]list.setChildIndicator(null);
[size=2]// Now we fill the Expandable list with the Topics and Notes, using the Modified adapter
[size=2]list.setAdapter(getAllTopicNotes());
[size=2]}
[/source]
Last thing, here's the code snippet from the onCreateDialog method that saves new Topics and Notes to the SQLite3 database:
[source lang="java"]
[size=2]@Override
public void onClick(DialogInterface dialog, int which) {
EditText topicText = (EditText)layout.findViewById(R.id.EditText_Topic);
String strTopic = topicText.getText().toString();
EditText noteText = (EditText)layout.findViewById(R.id.EditText_Note);
String strNote = noteText.getText().toString();
SQLiteDatabase db = topic_notes_data.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(TOPIC, strTopic);
values.put(NOTE, strNote);
db.insertOrThrow(TOPICNOTES_TABLE, null, values);
db.close();
ExpandableListView list = (ExpandableListView)findViewById(R.id.ExpList_Topics);
list.setGroupIndicator(null);
list.setChildIndicator(null);
list.setAdapter(getAllTopicNotes());
TopicNotesActivity.this.removeDialog(ADD_TOPIC_NOTE_DLG_ID);
}
[/source]
That's about it--hopefully this is useful. I left out all the supporting xml files and database files to focus on implementation. TopicNotes is a simple program, but has been fun to work on so far. As I stated above, I may take some time to improve it if for no other reason than to write some useful tutorials for beginner Android programmers. Any feedback is welcome. Thanks!
https://blogger.goog...in.blogspot.com

Source
0 likes 2 comments

Comments

Gaiiden
You should use source or code tags - that code is microscopic!

Oh duh, this is fed in from an external blog :P
May 05, 2012 01:49 AM
modemancer
Yikes, that WAS painfully small. I've edited the post, and included the sourcecode tags. I'll be more conscious of that in the future. Thanks for pointing it out!
May 05, 2012 02:31 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement