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?
Related
I am quite new to Android development. I managed to get data saved to SQLite database. Now, what I want is to view these data when I call viewData(). I have viewData() which shows data as a Toast as I made it as a sample. Now I need these data to show on a new activity using a ListView, but the number of data to show is depending on how many data is in the database at the moment, If user saved 10 items then I want all the 10 items to shown up. How can I do it?
I hope my question is clear.
Thanks in advance.
you could use ListView
declare it in your layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#+id/list"
android:layout_height="wrap_content"
android:layout_width="match_parent">
</ListView>
</LinearLayout>
in yor activity declare a globar var:
ListView listView;
and onCreate
listView = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, values);
// Assign adapter to ListView
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id){
// ListView Clicked item index
int itemPosition = position;
// ListView Clicked item value
String itemValue = (String) listView.getItemAtPosition(position);
}
});
datos can be an array that you can populate with data that you extract from your data base and that's the most simple way to show it. if you want to customizise your listView you can create a custom adapter, or in other way the newest element that replace listView is ReciclerView. I hope tihs help you
You can use a SimpleCursorAdapter:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView answerList=(ListView)findViewById(R.id.answerList);
Cursor mCursor = getData();
startManagingCursor(mCursor);
// now create a new list adapter bound to the cursor.
// SimpleListAdapter is designed for binding to a Cursor.
ListAdapter adapter = new SimpleCursorAdapter(this, // Context.
android.R.layout.two_line_list_item,
mCursor, // Pass in the cursor to bind to.
// Array of cursor columns to bind to.
new String[] {"_id", "answer"};
// Parallel array of which template objects to bind to those
// columns.
new int[] { android.R.id.text1,android.R.id.text2 });
// Bind to our new adapter.
answerList.setAdapter(adapter);
}
private Cursor getData() {
String sq = "Select _id, answer from foo";
Cursor c = db.rawQuery(sql);
return c;
}
I will try to give an in-depth answer to this.
Whenever you want to fetch and display a list of data from the database, you can use a ListView, GridView, Spinner, etc for it.
You can use a CursorAdapter which can make the job of querying and displaying data much more simple and easy.
Here is a basic visual representation of it,
Step 1
Firstly, you need to create a database. As mentioned in your question, it is clear that you know how to create a database and put some data into it. So I am not going into the depths of it.
Step 2
We need to define the layout to be used for the individual items in the ListView and save it as res/layout/item_todo.xml This is just a sample layout, you can design any kind of layout you want to.
<?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="horizontal" >
<TextView
android:id="#+id/tvBody"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Study cursors"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/tvPriority"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="3"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
Step 3
Now we need to define an adapter. Here we are using a CursorAdapter which converts a Cursor (that you provide) into Views (defined by your layout).
There are two methods, newView and bindView which we need to override. The newView is responsible for inflating newViews for the first time and the bindView is responsible for binding the data to the Views.
public class TodoCursorAdapter extends CursorAdapter {
public TodoCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
}
// The newView method is used to inflate a new view and return it,
// you don't bind any data to the view at this point.
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_todo, parent, false);
}
// The bindView method is used to bind all data to a given view
// such as setting the text on a TextView.
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView tvBody = (TextView) view.findViewById(R.id.tvBody);
TextView tvPriority = (TextView) view.findViewById(R.id.tvPriority);
// Extract properties from cursor
String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
int priority = cursor.getInt(cursor.getColumnIndexOrThrow("priority"));
// Populate fields with extracted properties
tvBody.setText(body);
tvPriority.setText(String.valueOf(priority));
}
}
Step 4
Now as you can clearly see, that the constructor needs a Context and a Cursor. Now we need to query the database and retrieve the data into a Cursor and pass it to the adapter.
// TodoDatabaseHandler is a SQLiteOpenHelper class connecting to SQLite
TodoDatabaseHandler handler = new TodoDatabaseHandler(this);
// Get access to the underlying writeable database
SQLiteDatabase db = handler.getWritableDatabase();
// Query for items from the database and get a cursor back
Cursor todoCursor = db.rawQuery("SELECT * FROM todo_items", null);
Step 5
This is the last step where we need to instantiate the adapter and attach the ListView with the adapter to populate the data.
// Find ListView to populate
ListView lvItems = (ListView) findViewById(R.id.lvItems);
// Setup cursor adapter using cursor from last step
TodoCursorAdapter todoAdapter = new TodoCursorAdapter(this, todoCursor);
// Attach cursor adapter to the ListView
lvItems.setAdapter(todoAdapter);
I am populating a list from an SQLite database which works fine but the first text view is always empty and I cannot figure out why. This is causing me issues because I use the populated text views to display information when clicked but as the first one is empty and can be clicked it is causes the program to fail. Here is my code:
public class ShowPhrases extends Activity implements OnInitListener {
SQLiteDatabase database;
NotesDbAdapter md;
CursorAdapter dataSource;
TextToSpeech tts;
private static final String fields[] = { "phrase", "folang",BaseColumns._ID };
NotesDbAdapter.DatabaseHelper helper = new NotesDbAdapter.DatabaseHelper(
this);
#Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.hs);
//Set volume buttons to music volume instead of ringer
setVolumeControlStream(AudioManager.STREAM_MUSIC);
tts = new TextToSpeech(this, this);
database = helper.getWritableDatabase();
Cursor data = database.query("notes", fields, null, null, null, null,null);
dataSource = new SimpleCursorAdapter(this, R.layout.highscores, data, fields, new int[] { R.id.first });
final ListView lv = (ListView) findViewById(R.id.list_view);
lv.setHeaderDividersEnabled(true);
lv.addHeaderView(getLayoutInflater().inflate(R.layout.highscores, null));
lv.setAdapter(dataSource);
The highscores xml layout:
android:orientation="vertical" >
<TextView
android:id="#+id/first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="20dp"
android:focusable="false"
android:textColor="#357ae8"
android:textSize="20dp" />
</RelativeLayout>
The hs xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/gerback"
android:orientation="vertical" >
<ListView
android:id="#+id/list_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
Can anyone see why this is happening?
Try this:
Cursor data = database.query("notes", fields, null, null, null, null,null);
data.moveToNext();
dataSource = new SimpleCursorAdapter(this, R.layout.highscores, data, fields, new int[] { R.id.first }, 0);
Does it works?
Remember to add 0 as last parameter to use the non deprecated method.
When you say that the first Textview is empty, are you talking about the headerview or the first item in the list?
If you mean the headerview, and the first piece of xml (in your question) is the one being inflated into it (R.layout.highscores), then the problem is simply that you haven't assigned it any text to display. The headerview isn't populated by the adapter, and it scrolls with the list, so it will be blank in your case.
Android 2.3.3
I have a table in database with two columns. I wish to retrieve this data and show them in a ListView having two textviews(first column in first textview and second column in second textview) and repeat this till for all the rows in the database. I have read a few examples on(custom adapter and listview) how to do, but the more I read, the more I get confused.
Can someone give me a head start on how to do this? I can use a dynamic listview, but I wish to do it using the static one.
Here is the Layout of the row in the listview:
<?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="horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingBottom="5dp"
android:paddingTop="5dp" >
<TextView
android:id="#+id/txtView_History_Expression"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.50"
android:text="Expression"
android:textColor="#FFFFFF"
/>
<TextView
android:id="#+id/txtView_History_Result"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.50"
android:text="Result"
android:textColor="#316DA2" />
</LinearLayout>
Here is the XML with ListView:
<?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" >
<TextView
android:id="#+id/txtView_History_Header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="HISTORY"
android:gravity="center"
android:textSize="24dp"
android:textColor="#316DA2"
android:paddingTop="10dp"
/>
<ListView
android:id="#+id/lvHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
I am retrieving the data from database and storing it in a Cursor. I want to read data from Cursor and give those values to the textviews in the listview.
I have a table in database with two columns. I wish to retrieve this
data and show them in a ListView having two textviews(first column in
first textview and second column in second textview) and repeat this
till for all the rows in the database. I have read a few examples
on(custom adapter and listview) how to do, but the more I read, the
more I get confused.
Hello. This algorithm is not too tricky. You need to these steps:
Create some method for getting rows from db. You can return either
List<TableDataType> or directly Cursor.
Create subclass of some ListAdapter to get better control over it.
Set ListAdapter to ListView.
Example:
Method for getting data from db:
public List<DataType> getAll() {
List<DataType> objects = new ArrayList<DataType>();
DataType child = null;
Cursor c = null;
try {
String query = "select * from TableName";
c = db.rawQuery(query, null);
if (c.moveToFirst()) {
child = new DataType();
child.setId(c.getInt(c.getColumnIndex("id")));
child.setName(c.getString(c.getColumnIndex("name")));
objects.add(child);
}
return objects;
}
finally {
if (c != null) {
c.close();
}
if (db != null) {
db.close();
}
}
}
Then you can create own Adapter extending from BaseAdapter and set data to TextViews in getView() method and create RowHolder that will be arbitrary Object that holds childs(widgets) of each row
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// inflate convertView and add row to RowHolder
// set RowHolder as tag of row .. convertView.setTag(rowHolder);
}
else {
// just recycle views so get existing RowHolder
rowHolder = (RowHolder) convertView.getTag();
}
// set data to widget(s)
rowHolder.getFirstTextView().setText(dataSource.get(position).getId());
...
}
RowHolder can looks like
public class RowHolder {
private View row;
private TextView idColumn;
public RowHolder(View v) {
this.row = v;
}
public TextView getIdColumn() {
if (idColumn == null) {
idColumn = (TextView) row.findViewById(R.id.idColumnId);
}
return idColumn;
}
}
And finally set Adapter to ListView and work is done.
Note:
DataType is own defined Object. It presents Table in your db where properties of Object are identical with columns in Table.
There is other approach and return from db Cursor and a usage of SimpleCursorAdapter or CursorAdapter. Here are nice examples:
Android Listview Example using CursorAdapter and SQLite
database
SimpleCursorAdapters and
ListViews
you should follow this flow
step 1 -> get data from data base and Fill the List with getter Setter
Step 2 -> Create BaseAdapter Class and give that list in this class[Here you need to see BaseAdpter bind methods]
Stap 3 -> Bind BaseAdapter object with Your ListView
All you can do is take a look at Bind the List view from Database with Cursor Adapter.
Also check the ListView Example using Cursor Adapter with SQLiteDatabase.
I hope this will guide you.
Thanks.
I am new to android. I want to show inserted data from database to a table. I have used List to get the data.
public List<user> getAllUsers() {
List<user> users = new ArrayList<user>();
Cursor cursor = database.query(SqlLiteHelper.TABLE_USER, allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
user varUser = cursorToUser(cursor);
//Log.v("user name",varUser.getName().toString());
users.add(varUser);
cursor.moveToNext();
}
//Log.v("user name",users.get(0).getName().toString());
cursor.close();
return users;
}
private user cursorToUser(Cursor cursor) {
user varUser = new user();
//Log.v("user id", cursor.getString(1).toString());
varUser.setID(cursor.getLong(0));
varUser.setName(cursor.getString(1));
varUser.setPhone(cursor.getString(2));
varUser.setEmail(cursor.getString(3));
return varUser;
}
I wrote this code on UserDataSource.java
Then where i need to show those data i use the following codes
databaseSource = new UserDataSource(this);
databaseSource.open();
List<user> values = databaseSource.getAllUsers();
Log.v("information", values.get(0).getName().toString());
ArrayAdapter<user> adapter = new ArrayAdapter<user>(this, android.R.layout.simple_list_item_1, values);
setListAdapter(adapter);
This is not adding the values in the list. I use the log.v to check whether the data is coming back or not. And i found that the data is coming perfectly from the database. Only when i try to print the List or insert it to the simple_list_item_1 then it is doing the problem.
It is printing
com.example.given_n_take.user#41221338
Buts its suppose to print the name from the database.
Database table name is user.
Please let me know what am i missing.
here is my xml file of layout where i am trying to add those list
<?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" >
<Button
android:id="#+id/all_user_back"
style="?android:attr/buttonStyleSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="Back" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="384dp" >
</ListView>
</LinearLayout>
If your list shows com.example.given_n_take.user#41221338 this means that you are missing a toString method in your user class. Implement a toString that returns the name of the user.
It's because your ArrayAdapter calls the toString() method of your user object. You either have to implement to toString() method or if you want to show more than a string in your list, you have to write your own Adapter.
you are getting wrong result because
Log.v("information", values.get(0).getName().toString());
values.get(0) will return class User consist of values like name ,id, phone no etc and to acces name you are calling getName method which is perfect. But for adapter you are passing List<user> values directly. So when adapter extract data out of it it will extract class User out of it not the different values. SO to access values you have to get the positioned value of list, extract values name, id etc and then pass it to adapter
I have a Listview that will list the alarms which are in the database.I need to add a Toggle Button beside each list item to set the alarm on/off.
How can I add the Toggle Button in the ListView?
R.layout.alarm_list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView android:id="#+id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_reminders"
android:textColor="#FFF"/>
</LinearLayout>
Java Code:
private void fillData() {
Cursor remindersCursor = aDbHelper.fetchAllAlarms();
startManagingCursor(remindersCursor);
// Create an array to specify the fields we want to display in the list
// (only TITLE)
String[] from = new String[] { AlarmDbAdapter.KEY_TITLE };
// and an array of the fields we want to bind those fields to (in this
// case just text1)
int[] to = new int[] { R.id.text1};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter reminders = new SimpleCursorAdapter(this,
R.layout.alarm_row, remindersCursor, from, to);
setListAdapter(reminders);
}
R.layout.alarm_row:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:padding="10dip" android:layout_width="242dp"
android:layout_height="wrap_content"/>
My project is getting delayed.
Help
There is no small snippet ans. to your problem. I assume you need to have multi-selection. Now here are the things you need.
Since you are using SimpleCursorAdapter, you should replace that with CursorAdapter. To do so you have to extend it as it is a abstract adapter. Once you done that you will be overriding two functions.
newView Where you will create your list item views by inflating R.layout.alarm_row (it should contain your toggle button too). You have make toggle button non-clickable.
bindView where you will set state of toggle button and text for your text view
That said this what you need on the Activity side.
You have make your ListView to multi-selection mode by android:choiceMode in xml or using setChoiceMode.
Now bindView will look like:
ListView lv = ((ListActivity)context).getListView();
// Containing all check states
SparseBooleanArray sba = lv.getCheckedItemPositions();
// I am using check box
cb.setChecked(false);
// Cursor is passed as an argument.
if(sba != null)
if(sba.get(cursor.getPosition()))
cb.setChecked(true);
Ref to docs:
CursorAdapter docs
http://developer.android.com/reference/android/widget/ListView.html
Try creating a custom adapter like:
public class YourAdapter extends BaseAdapter
and a custom layout for the rows with a toggle button (you will have to inflate the layout in the method geView).
Here you can find an example: http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/
Hope this helps..