I was looking for an alternative to a spinner, since the first item is always selected (which causes me issues), and I found some examples for using an AlertDialog with a list instead.
I am having two problems:
The list is displaying and is formatted ok, but there are no values in it. I know the query is returning, and the cursor/adapter has the data in it.
This may be a symptom of #1 - but when I select a blank row, the Cursor cursor2 = (Cursor) ((AdapterView) dialog).getItemAtPosition(which); statement causes a crash (it's a ClassCastException).
I had similar code previously which set the adapter to a spinner object, and the data was displaying fine.
I don't think the adapter is getting set correctly, and I have been unable to come up with a solution thus far.
Any thoughts?
Thanks!
btnDenomination.setOnClickListener(new View.OnClickListener()
{
public void onClick(View w)
{
Cursor cursor = coinDB.myDataBase.rawQuery("select _id, denomination_desc from denomination", null); // must select the _id field, but no need to use it
startManagingCursor(cursor); // required in order to use the cursor in
String[] from = new String[] {"denomination_desc" }; // This is the database column name I want to display in the spinner
int[] to = new int[] { R.id.tvDBViewRow }; // This is the TextView object in the spinner
cursor.moveToFirst();
SimpleCursorAdapter adapterDenomination = new SimpleCursorAdapter(CoinsScreen.this,
android.R.layout.simple_spinner_item, cursor, from, to );
adapterDenomination.setDropDownViewResource(R.layout.db_view_row);
new AlertDialog.Builder(CoinsScreen.this)
.setTitle("Select Denomination")
.setAdapter(adapterDenomination, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Cursor cursor2 = (Cursor) ((AdapterView<?>) dialog).getItemAtPosition(which);
strDenomination_id = cursor2.getString(0); // Gets column 1 in a zero based index, the first column is the PKID. this could
// be avoided by using a select AS statement.
Log.d("Item Selected", strDenomination_id );
TextView txtDenomination = (TextView) findViewById(R.id.textDenomination);
txtDenomination.setText(cursor2.getString(1));
dialog.dismiss();
}
}).create().show();
}
});
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:text=""
android:id="#+id/tvDBViewRow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF0000" />
</LinearLayout>
Are you sure R.id.tvDBViewRow is the id of the TextView in the layout android.R.layout.simple_spinner_item ? From this, the TextView's id should be android.R.id.text1.
So new answer for the second issue :)
I think you should reuse the initial cursor instead of trying to get a new one... Can you try to do :
adapterDenomination.moveToPosition(which);
strDenomination_id = adapterDenomination.getString(0);
in the onClick() ?
Related
I'm trying to get my contacts on a list view. Now I know that using simple_list_item_multiple_choice enables me to select multiple contacts, but it views names only without numbers.
On the other side, simple_list_item_2 can be used to show both name and number, but supports selection of only one contact.
Is there any template that combine them both? If not, how could I build my customized list with both features?
EDIT: This is the code I'm using
CursorLoader cl = new CursorLoader(this,ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC");
Cursor c = cl.loadInBackground();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_multiple_choice, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME},
new int[] { android.R.id.text1},0);
setListAdapter(adapter);
Here, the second parameter of SimpleCursorAdapter is simple_list_item_multiple_choice but it supports only dealing with android.R.id.text1. So I can use items only, not subitems.
But in the following code
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ,ContactsContract.CommonDataKinds.Phone.NUMBER},
new int[] { android.R.id.text1,android.R.id.text2},0);
I can give it both ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME and NUMBER to be written in android.R.id.text1 and android.R.id.text2, but can't use multiple choice feature.
As Dipu said, you should make your own customized layout.
To show name and contact, you need two text views, and one check box for checking.
You can start coding from this tutorial:
http://www.mysamplecode.com/2012/07/android-listview-checkbox-example.html
Add one more text view to country_info.xml will solve your problem.
ADDED
To use a custom list view layout, you have to implement your own adapter.
This tutorial (2. Custom ArrayAdapter example) will help you figure out how to do that.
http://www.mkyong.com/android/android-listview-example/
The answer provided by Heejin is excellent, but it's not important to implement a custom ArrayAdaptor. What only I needed to do is to write a custom layout and send it to the SimpleCursorAdaptor constructor.
The custom layout represent the layout of each item in the list view. I need each row to contain a CheckedTextView and another small TextView as a subitem. So I've made a layout called row_view.xml with the following content
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<CheckedTextView
android:id="#+id/checkedTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:text="CheckedTextView" />
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Small Text"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
Then I've just used it in the constructor
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.row_view, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER},
new int[] { R.id.checkedTextView, R.id.textView},0);
setListAdapter(adapter);
This is the full code
public class MultipleContacts extends ListActivity implements OnItemClickListener {
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone._ID
,ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
,ContactsContract.CommonDataKinds.Phone.NUMBER
};
SimpleCursorAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multiple_contacts);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
getListView().setOnItemClickListener(this);
// Get a cursor with all people
CursorLoader cl = new CursorLoader(this,ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
PROJECTION, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC");
Cursor c = cl.loadInBackground();
adapter = new SimpleCursorAdapter(this,
R.layout.row_view, // Use a template
// that displays a
// text view
c, // Give the cursor to the list adapter
new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER},
new int[] { R.id.checkedTextView, R.id.textView},0);
setListAdapter(adapter);
}
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
//what to do when an item is clicked
CheckedTextView checkedTextView = (CheckedTextView) v.findViewById(R.id.checkedTextView);
Toast.makeText(this, checkedTextView.getText(), Toast.LENGTH_SHORT).show();
}
}
Please note that I've two layouts, one for the list view itself(called multiple_contacts) and the provided layout here (called row_view) is the layout for each item in the list view. All what I need from multiple_contacts is to write setContentView(R.layout.multiple_contacts);
I'm try to write a little application and the releated unit tests.
I have a ListView binded to a SimpleCursorAdapter reading data from an SQL table.
The Activity#onCreate() method is:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DatabaseHelper(this);
SQLiteDatabase dbRead = dbHelper.getReadableDatabase();
String[] columns={BaseColumns._ID, ENTRY_VALUE};
cursor = dbRead.query(ENTRIES_TABLENAME, columns, null, null, null, null, null);
String[] from = {"value"};
int[] to = {R.id.value};
adapter = new SimpleCursorAdapter(this, R.layout.list_entry, cursor, from, to);
setListAdapter(adapter);
}
My test inside the unit-test is:
#UiThreadTest
public void testTheElementInsideTheDBisDisplayedInTheList() {
String entryValue = "clipboard entry 1";
DatabaseHelper dbHelper = new DatabaseHelper(cmActivity);
Cursor beforeCursor = selectAllEntries(dbHelper);
// The table, at the begining of the test, is empty, I control that
assertEquals(0, beforeCursor.getCount());
// I insert the new value in the table
insertEntry(dbHelper, entryValue);
// and I control that is really inside the table now
Cursor afterCursor = selectAllEntries(dbHelper);
assertEquals(1, afterCursor.getCount());
// This method calls the method "requery()" on the cursor associate
// to the listView's adapter to update the list view
cmActivity.updateList();
// I control that the listView is updated
assertEquals(1, entryList.getCount());
// Now I try to retrive the only child inside the list view
// to extract the text inside it and to compare this text with
// the value inserted into the DB table.
TextView entryView = (TextView) entryList.getChildAt(0);
String viewText = entryView.getText().toString();
assertEquals(entryValue, viewText);
}
My problem is in the third-last row:
TextView entryView = (TextView) entryList.getChildAt(0);
I sude getChildAt() to get the first TextView child of the ListView. But this method returns null, so the test gets a NullPointerException.
Maybe getChildAt() is not the right method to get the View child from a ListView, so which is the correct one?
I see from the documenation that the method works with GroupView, I didn't use them, do I need to configure a default GroupView and put all the entry inside it? In this way, will getChildAt(0) work? Is this the correct way to setup a ListView?
thank you, bye
Andrea
As asked by Vivek, I post here the main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Empty set"
/>
</LinearLayout>
As you can see is very very basic. Also le list entry is very simple:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/value"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
I doubt if the list is populated when you call getChildAt() method. So call getChildCount() method and see if the list is populated. And post back the output here.
Edit:
Now I understand the problem. ListView.getCount() method returns the number of items populated in the list. And ListView.getChildCount() Method or ListView.getChildAt() Method will return 0 here because these methods will return a value only when the view is visible to the user. You can use getChildAt() method only after the textviews are generated. i.e If you use the method in OnItemClick method of the listview, or any listview listener implementation, you will get the desired output. What is the need to get the reference to the textviews here in this method anyways?
I have an activity where I want it to display results from a database using ListView. The table has three columns: word, description, and category. On the activity page, I have a list of categories being read from an array. I want to set it up so that if you click on an item on the list (for example Cat1), the results returned from the cursor will be all words/descriptions with the category Cat1 in the DB. Currently I simply have a Toast with that category's name appear when clicked.
As it is right now, the activity does not run properly. I have read around on the web, and am not sure how to proceed. Here is the code I have so far. If anyone can help me, I would really appreciate it.
public class Categories extends ListActivity {
DataBaseHelper db = new DataBaseHelper(this);
private SQLiteDatabase data;
int position;
private ListView list;
private String[] categories = {
"C1", "C2", "C3", "C4",
"C5", "C6", "C7", "C8",
"C9", "C10", "C11", "C12"
};
#Override
public void onCreate(Bundle icicle){
super.onCreate(icicle);
setContentView(R.layout.cat_list);
list = (ListView)findViewById(R.id.cat_listing);
list.setAdapter(new ArrayAdapter<String>(this,
R.layout.categories, categories));
list.setTextFilterEnabled(true);
Cursor cursor = data.rawQuery("SELECT term, desc FROM words WHERE cat = '" + categories[position] + "'", null);
startManagingCursor(cursor);
String columns[] = new String[] { "term", "desc" };
int[] to = new int[] { R.id.cat_term, R.id.cat_desc };
SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(this, R.layout.cat_result, cursor, columns, to);
this.setListAdapter(myAdapter);
list.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view,
int position, long id){
CharSequence text = categories[position];
Toast toast = Toast.makeText(getApplicationContext(),
text, Toast.LENGTH_SHORT);
toast.show();
}
});
}
}
I have a similar function in my app. You will need to create a XML file to define the layout for the list and call them in your java code.
Here is the example XML:
LIST:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
</ListView>
<TextView
android:id="#+id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="#string/no_projects"
android:padding="10dp"
android:textSize="16sp"
android:textStyle="bold" >
</TextView>
</LinearLayout>
This is the custom layout XML. I call it list_rows:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" >
<TextView
android:id="#+id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TextView>
<TextView
android:id="#+id/text2"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TextView>
<TextView
android:id="#+id/text3"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
And this is the JAVA code:
String[] fields = new String[] { db.TABLE_PRJ_NAME, db.TABLE_PRJ_TYPE, db.TABLE_PRJ_DESC };
int[] views = new int[] { /*android.R.id.text1*/ R.id.text1, R.id.text2, R.id.text3 };
c = db.getAllProjects();
startManagingCursor(c);
// Set the ListView
SimpleCursorAdapter prjName = new SimpleCursorAdapter(
this,
R.layout.project_list_rows,
//android.R.layout.simple_list_item_1,
c, fields, views);
setListAdapter(prjName);
The onListItemClickListener
// This section of code is for handling the Click Event of the Projects List
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Cursor o = (Cursor) this.getListAdapter().getItem(position);
String projectName = o.getString(1);
Intent showProjectDetails = new Intent(this, ProjectDetails.class);
Bundle bundle = new Bundle();
bundle.putString("sendProjectName", projectName);
showProjectDetails.putExtras(bundle);
startActivity(showProjectDetails);
}
What the new part of the code is doing is just sending the selected item to another activity through an intent. Then in the new activity, I am querying the DB using the selected item name from the bundle and displaying the result.
Do ask if you need further explanation.
I am making a very similar program. I'm having trouble with it as its my first program for android/java. What help I have got is from web and my step father who use to teach java.
When helping me setup a database he explained to setup my tables so categories is paired with items under it. So you would have a table for your categories including the title you will display for that category as well as your primary key. Then you need a table for the next level down from category, say title. This would include a text for title and primary key. Next you need to make another table to pair them up. A title key, category key, and primary key.
From there you will need to tell java to pair them up based off that last table.
I'm a noob so sorry I couldn't give more/better info. But anything I find on this issue I'll post here and good luck.
I'm working on my first Android app and can't figure out how to get my SimpleCursorAdpater to populate the view. The cursor that I'm passing in has results in it, so the problem must be somewhere in instantiating the adapter or in binding it to the view. I'm sort of at my wits end since no exceptions are thrown and I can't really step
into setListAdapter.
Here is how i get my cursor in the first place:
Searches searches = new Searches(this);
SQLiteDatabase db = searches.getReadableDatabase();
//select _id, Name, Search FROM Searches;
Cursor c = db.query(
SearchConstants.TABLE_NAME,
FROM, null, null, null,
null, null);
startManagingCursor(c);
And this is the schema do my db:
CREATE TABLE Searches (_id INTEGER PRIMARY KEY, Name Text, Search TEXT)
Here are the two lines where things start to fall apart:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.search, cursor, FROM, TO);
setListAdapter(adapter);
My main layout looks like this:
<ListView
android:id="#android:id/android:list"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#android:id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/empty" />
Here is the view to fill with each result:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10sp">
<TextView
android:id="#+id/_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/colon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
android:layout_toRightOf="#id/name" />
<TextView
android:id="#+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textStyle="italic"
android:layout_toRightOf="#id/colon" />
</RelativeLayout>
Finally here are the static variables I used:
//search query stuff
private static String[] FROM = {SearchConstants._ID, SearchConstants.NAME_COLUMN, SearchConstants.SEARCH_COLUMN};
//where to paste search results
private static int[] TO = {R.id._id, R.id.name, R.id.search};
/**
* Table name
*/
public static final String TABLE_NAME = "Searches";
/**
* Name Column
*/
public static final String NAME_COLUMN = "Name";
/**
* Search Column
*/
public static final String SEARCH_COLUMN = "Search";
I think this is all of the relevant code. I have no idea how to proceed at this point, so any suggestions at all would be helpful.
Thanks,
brian
PS: Looks like theres a lot of great suggestions here - i'm not ignoring them i just havent had the chance yet. Thanks for the advice! At some point i'll go thru them all and try to give some feedback as to which things worked well for me.
You can step into the code if you have the source code. Luckily, Android is open source. To easily attach source code in Eclipse, see:
http://android.opensourceror.org/2010/01/18/android-source/
As for the problem itself, you said in a comment above that you iterate all of the items before creating the adapter. If you are not creating a new cursor after iteration, you probably need to rewind it or the adapter might think it's empty.
cursor.moveToFirst()
Please don't worry about any internal binding aspects. I'm sure there is an easy way out. Try the following:
First, just to ensure your cursor really has got data where it's needed, put the line
System.out.println("cursor.getCount()="+cursor.getCount());
right before the call of setAdapter(). But surely, you already tested to get a row count ;-) So the following might be more interesting.
To check if your binding fails, please test with:
android:id="#+id/android:list"
instead of :
android:id="#android:id/android:list"
in your main.xml. Same thing with: android:id="#+id/android:empty".
And if you still don't get results, you can also try using a list default xml-layout (like simple_list_item_1) for displaying, which would look like this:
ListAdapter adapter = new SimpleCursorAdapter(this,
// Use a template that displays a text view
android.R.layout.simple_list_item_1,
// Give the cursor to the list adapter
cursor,
// Map the NAME column in your database to...
new String[] {SearchConstants.NAME_COLUMN} ,
// ...the "text1" view defined in the R.layout.simple_list_item_1
new int[] {android.R.id.text1}
);
Just copy paste it into your activity and see what happens.
Hope you're done with that!
Just got the same problem and found how to allow the Simplecursoradapter creation to not fail.
In your cursor, the query of the database MUST contain the table primary key even if you don't need it ! If not it will fail and crash...
Hope it will help others with the same problem !
Alright, I noticed you used a column name with a capital letter. Make sure you use the exact identifier in the DB scheme (the sqlite column names are case sensitive). But in the code you provided the column identifiers match.
So, if the cursor you use really has got the data, try out the above code at first (instead of some custom layout) for creating a SimpleCursorAdapter and it should work. Here's another little example for the activity code (as I don't know yours):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.dbManager = new DatabaseManager(this);
setContentView(R.layout.main);
registerForContextMenu(getListView()); // catch clicks
if (!showList()) {
TextView tv = new TextView(this);
tv.setText(getString(R.string.txt_list_empty));
setContentView(tv);
}
}
private boolean showList() {
final Cursor c = dbManager.fetchListData();
startManagingCursor(c); // when the Activity finishes, the cursor is closed
if (!c.moveToFirst())
return false;
final SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(
this, android.R.layout.simple_list_item_2, c,
new String[]{"name"} , new int[]{android.R.id.text1} );
setListAdapter(myAdapter);
return true;
}
Before spending a lot of time where you encounter problems, rather start where things are still working and take small steps for extensions. If you keep them simple, there's no great magic in using adapters.
You might try inserting a ViewBinder for debugging. You can use it to inspect which values are being passed for which views in the SimpleCursorAdaptor. Or just use it to manually do the binding yourself.
Something like this should work:
adapter.setViewBinder(new SimpleCursorBinder());
and then
public class SimpleCursorBinder implements SimpleCursorAdpater.ViewBinder {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
/* set breakpoints and examine incoming data. */
// returning false, causes SimpleCursorAdapter to handing the binding
boolean bound = false;
String columnName = cursor.getColumnName(columnIndex);
TextView bindingView = null;
int viewId = view.getId();
// could just use this opportunity to manually bind
if (columnName.equals(SearchConstants._ID)) {
bindingView = (TextView)(viewId == R.id._id ? view : null);
} else if (columnName.equals(SearchConstants.NAME_COLUMN)) {
bindingView = (TextView)(viewId == R.id.name ? view : null);
} else if (columnName.equals(SearchConstants.SEARCH_COLUMN)) {
bindingView = (TextView)(viewId == R.id.search ? view : null);
}
if (bindingView != null) {
bindingView.setText(cursor.getString(columnIndex));
bound = true;
}
return bound;
}
}
It doesn't look like you've done anything wrong, You haven't shown all your code though so it might be difficult to spot any errors.
Not sure if the line startManagingCursor(c) does this for you but in my examples i have the following lines after my query has completed. Given your example looks absolutely fine it could be your cursor needs resetting to the first item.
(Ah, just noticed kichik pointed this out , but i'll leave my example.)
if (c != null) {
c.moveToFirst();
}
My queries often look like:
public Cursor getQueryCursor()
{
Cursor c;
c = null;
try{
c = myDataBase.query(TABLE_MYTABLE, new String[] {
COLUMN_ID,COLUMN_LABEL, COLUMN_TEXT},
null,
null,
null,
null,
null);
if (c != null) {
c.moveToFirst();
}
}catch(Exception ec)
{
Log.w("MY_APP", ec.getMessage());
}
return c;
}
Then when applying your query result i also often put try/catch statements around it and add break points at these points (sometimes the getMessage() returns null but other properties of the exception will highlight the issue. I also check the out put from LogCat. I've often been able to work out the root of my problems with the following.
try{
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.search, cursor, FROM, TO);
setListAdapter(adapter);
}catch(IllegalStateException e)
{
Log.w("MyApp", e.getMessage());
}catch(Exception es)
{
Log.w("MyApp", es.getMessage());
}
Please check your SQLite database, it must have a column '_id' as a primary key.
I had same kind of problem, and finally figure it out with this...
I'm quite new to Android development (started 2 days ago) and have been through a number of tutorials already. I'm building a test app from the NotePad exercise (Link to tutorial) in the Android SDK and as part of the list of notes I want to display a different image depending on the contents of a database field i've called "notetype". I'd like this image to appear in the List view before each notepad entry.
The code in my .java file is:
private void fillData() {
Cursor notesCursor = mDbHelper.fetchAllNotes();
notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
String[] from = new String[]{NotesDbAdapter.KEY_NOTENAME, NotesDbAdapter.KEY_NOTETYPE};
int[] to = new int[]{R.id.note_name, R.id.note_type};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.notes_row, notesCursor, from, to);
setListAdapter(notes);
}
And my layout xml file (notes_row.xml) looks like this:
<ImageView android:id="#+id/note_type"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="#drawable/default_note"/>
<TextView android:id="#+id/note_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
I just really have no clue how I'd go about fetching the right drawable depending on the type of note that has been selected. At the moment I have the ability to select the type from a Spinner, so what gets stored in the database is an integer. I've created some images that correspond to these integers but it doesn't seem to pick things up.
Any help would be appreciated. If you need more info then please let me know.
You might want to try using a ViewBinder. http://d.android.com/reference/android/widget/SimpleCursorAdapter.ViewBinder.html
This example should help:
private class MyViewBinder implements SimpleCursorAdapter.ViewBinder {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
int viewId = view.getId();
switch(viewId) {
case R.id.note_name:
TextView noteName = (TextView) view;
noteName.setText(Cursor.getString(columnIndex));
break;
case R.id.note_type:
ImageView noteTypeIcon = (ImageView) view;
int noteType = cursor.getInteger(columnIndex);
switch(noteType) {
case 1:
noteTypeIcon.setImageResource(R.drawable.yourimage);
break;
case 2:
noteTypeIcon.setImageResource(R.drawable.yourimage);
break;
etc…
}
break;
}
}
}
Then add it to your adapter with
note.setViewBinder(new MyViewBinder());