i have been having this issue for some time now, and have not gotten an answer for it yet. i have this custom Cursor adapter which i use to populate a list view from an sqlite database. Now my issue is that i want to populate the listview based on certain conditions.An example is if the condition is important, the listview should display only data that fits into that criteria and so on. I already have working methods that query the database accordingly.
now my problem is that, i can't seem to populate the listviews based on those methods and conditions without:
1) creating a copy of the exact same custom cursor adapter and just changing the names variables.
2) creating a copy of the exact xml layout and changing the id's.
As i say, its working this way, but i feel am having unnecessary classes and xml layout since its exactly the same thing. I know am doing something wrong, i just don't know what. Please any help and explanation would be appreciated. here is the necessary part of the code Code for the CustomCursorAdapter:
public class ViewItems extends ListActivity implements OnItemClickListener{
DBAdapter adapter;
Cursor cursor;
ListView list;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_list);
adapter = new DBAdapter(this);
adapter.open();
fillData();
list = (ListView)findViewById(android.R.id.list); // default android listView id
list.setOnItemClickListener(this);
}
// Different method calls
protected void fillImportantData() {
Cursor cursor = adapter.retrieveImportant();
startManagingCursor(cursor);
String[] from = new String[]{DBAdapter.NAME, DBAdapter.DATE, DBAdapter.TIME, DBAdapter.PRIORITY};
int[] to = new int[]{R.id.viewNameId, R.id.viewDateId, R.id.viewTimeId};
customCursorAdapter items = new customCursorAdapter(this, R.layout.view_items, cursor, from, to);
setListAdapter(items);
}
public class customCursorAdapter extends SimpleCursorAdapter {
private int layout;
Context context;
public customCursorAdapter(Context context, int layout, Cursor cursor, String[]from, int[] to) {
super(context, layout, cursor, from, to);
this.layout = layout;
this.context = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder;
if(view != null){
holder = new ViewHolder();
holder.viewName = (TextView)view.findViewById(R.id.viewNameId);
holder.viewStartDate = (TextView)view.findViewById(R.id.viewDateId);
holder.viewStartTime = (TextView)view.findViewById(R.id.viewTimeId);
view.setTag(holder);
}else{
holder = (ViewHolder)view.getTag();
}
int namecol = cursor.getColumnIndex(DBAdapter.NAME);
String name = cursor.getString(namecol);
if(holder.viewName != null){
holder.viewName.setText(name);
holder.viewName.setTextColor(Color.RED);
}
String startDate = cursor.getString(cursor.getColumnIndex(DBAdapter.DATE));
holder.viewStartDate.setText(startDate);
String startTime = cursor.getString(cursor.getColumnIndex(DBAdapter.TIME));
holder.viewStartTime.setText(startTime);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(layout, parent, false);
return view;
}
#Override
public long getItemId(int id){
return id;
}
#Override
public Object getItem(int position){
return position;
}
}
static class ViewHolder{
TextView viewName;
TextView viewStartDate;
TextView viewStartTime;
}
}
// methods in database
public Cursor retrieveAll(){
String[] resultColumns = new String[] {KEY_ID, NAME DATE, TIME, PRIORITY};
Cursor cursor = db.query(DATABASE_TABLE, resultColumns, null, , null, null, null);
return cursor;
}
public Cursor retrieveImportant(){
String[] resultColumns = new String[] {KEY_ID, NAME DATE, TIME, PRIORITY};
String[] condition = {"important"};
Cursor cursor = db.query(DATABASE_TABLE, resultColumns, PRIORITY + "=" + "?", condition, null, null, null);
return cursor;
}
If you change the data you wish to display, you will need to run a fresh query on the database and get a Cursor back that reflects that changed data. Depending on the nature of the changes, this may require a fresh CursorAdapter or merely a call to changeCursor(). If the new query returns the same columns and you want them displayed the same way, changeCursor() is probably sufficient. Otherwise, you will need to create a new CursorAdapter and call setAdapter() on your ListView to switch over to it.
You only need a different row layout if you are truly changing the row layout. You do not need to change IDs just for grins. Since you are not doing this in the code you have shown above, I am unclear what specifically you are worried about.
Related
In my application I read data from database, put it into cursor and pass it to ListView using adapter. These data are numbers from 1 to 12, but I need them to be presented in the ListView as names of months. How and on which step of reading and displaying these data can I intercept them and change from numbers to text?
You can modify the data, right before it the adapter sets the text to your TextView. It'll be done in adapter's getView method.
Try this
import java.text.DateFormatSymbols;
public String getMonth(int month) {
return new DateFormatSymbols().getMonths()[month-1];
}
You may right a custom adapter for that!. If your data is cursor object you can write custom adapter class extending from "CursorAdapter". Other wise you can extend from "BaseAdapter".
call it by:
ShowListCursorAdapter adapter = new ShowListCursorAdapter(getActivity(), R.layout.fragment_list_detail, cursor,
columns, views, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
getListView().setAdapter(adapter);
In custom Adapter extends cursorAdapter:
Constructor:
public ShowListCursorAdapter(Context context, int layout, Cursor cursor, String[] columns, int[] views, int flag) {
super(context,cursor,flag);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mCursor = cursor;
mLayout = layout;
mTo = views;
mFrom = columns;
}
Implement 2 methods in CursorAdapter.
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {//This will be called once
mView = mInflater.inflate(mLayout, viewGroup, false);
return mView;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {//This is called no.of row times
for(int i = 0; i< mTo.length;i++) {//If you have single column no need of for loop
TextView content = (TextView) view.findViewById(mTo[i]);
content.setText(mCursor.getString(mCursor.getColumnIndex(mFrom[i])));////here you can convert number to month and display
}
}
I'm using SimpleCursorAdapter to manage my query to the database and then showing the results in a ListView.
Here is my code:
database.open();
ListView listContent = (ListView)findViewById(android.R.id.list);
Cursor c = database.getData();
startManagingCursor(c);
String[] from = new String[]{Database._GROUP_NAME};
int[] to = new int[]{android.R.id.text1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, query, from, to);
listContent.setAdapter(adapter);
database.close();
Although, at first look, it it working as expected, I believe that this should NOT be the way to proceed since there is CursorAdapter.
I know that this is a noob question but since just started now programming in Android I still don't know much.
How can I pass this from using SimpleCursorAdapter to CursorAdapter?
Already searched on internet but wasn't able to understand how this can be done.
Not asking code just some directions.
Thanks
favolas
UPDATE FOLLOWING mainu COMMENT
database.open();
ListView listContent = (ListView)findViewById(android.R.id.list);
Cursor c = database.getData();
MyAdapt cursorAdapter = new MyAdapt(this, query);
listContent.setAdapter(adapter);
database.close();
MyAdapt class:
public class MyAdapt extends CursorAdapter {
private final LayoutInflater mInflater;
public MyAdapt(Context context, Cursor c) {
super(context, c);
mInflater = LayoutInflater.from(context);
mContext = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView groupName = (TextView) view.findViewById(android.R.id.text1);
groupName.setText(cursor.getString(cursor
.getColumnIndex(Database._GROUP_NAME)));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final View view = mInflater.inflate(
android.R.layout.simple_list_item_1, parent, false);
return view;
}
}
Is this the correct way?
favolas
SimpleCursorAdapter is the simplest form of Adapter you can use for a custom adapter.
You should use SimpleCursorAdapter only, by when you dont need any customization.
Sorry if this seems stupid, but I'm sort of new to all this stuff. The situation is that i have a lot of data stored in a database that I need to present in list views. The first view pulls 15 rows and uses only two out of 14 columns in the db. I use this adapter to present this in a list view:
private class CustomListAdapter extends SimpleCursorAdapter {
private Cursor cursor;
public CustomListAdapter(Context context, int textViewResourceId, Cursor cursor, String from[], int to[]) {
super(context, textViewResourceId, cursor, from, to);
this.cursor = cursor;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
cursor.moveToPosition(position);
if (cursor != null) {
TextView lt = (TextView) v.findViewById(R.id.lefttext);
TextView rt = (TextView) v.findViewById(R.id.righttext);
if (lt != null) {
lt.setText(/*cursor.getString(cursor.getColumnIndex(EwstableContentProvider.TIMESTAMP))*/cursor.getString(cursor.getColumnIndex(EwstableContentProvider._ID))); }
if (rt != null){
rt.setText(cursor.getString(cursor.getColumnIndex(EwstableContentProvider.TOTALEWS)));
}
}
return v;
}
}
}
This may even be stupid, but at least it works.
Now, on the next activity i need to present data from all the columns, but only from the row that the user selected on the previous activity. I was looking at putting it inside a list view like the one from http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/, which is also where i modified the adapter from.
this way, i would put data from two fields in the db into each item in the list view. this is perfect, it would be one data point and a comment that goes with it.
The problem is that at this point i only have one row in the cursor, so the bit after #Override is only executed once, so instead of the 7 items in the list view, I get one.
I'd really appreciate any help, even if it is to do it in an entirely different way.
Assuming that you know the number of columns, could you just use a for loop to iterate through all the columns, storing each string into a String array.
String[] arr = new String[cursor.getColumnCount()];
for(int i=0; i < cursor.getColumnCount(); i++)
arr[i] = cursor.getString(i);
Then use the String[] with an ArrayAdapter for your listview.
UPDATE: sorry didn't read the question carefully; see other answer.
You need to use a cursor adapter. I recommend the SimpleCursorAdapter (example below).
You will also need to change the "from" parameter to the column name (key) for the text you want displayed. An example from my personal code is below. This line,
new String[] { DBAdapter.KEY_NAME },
is the important one. It is defined in DBAdapter to be:
public static final String KEY_NAME = "name";
which matches the name of the first column in my own database.
DBAdapter dba = new DBAdapter(this);
dba.open();
Cursor c = dba.list_listMode();
SimpleCursorAdapter ca = new SimpleCursorAdapter(
this,
R.layout.list_item,
c,
new String[] { DBAdapter.KEY_NAME },
new int[] { R.id.list_item_text });
lv.setTextFilterEnabled(true);
lv.setAdapter(ca);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id_long) {
I have a listview which populates its content from SQLite Database.
Here's my code:
ListView listView = (ListView) findViewById(R.id.lstText);
listView.setOnItemClickListener(this);
listView.setAdapter(new MySimpleCursorAdapter(this, R.layout.listitems,
managedQuery(Uri.withAppendedPath(Provider.CONTENT_URI,
Database.Project.NAME), new String[] { BaseColumns._ID,
Database.Project.C_PROJECTTITLE,
Database.Project.C_SMALLIMAGE, Database.Project.C_PROJECTDESCRIPTION, Database.Project.C_ORGANIZATIONTITLE}, null, null, null),
new String[] { Database.Project.C_PROJECTTITLE,
Database.Project.C_SMALLIMAGE, Database.Project.C_PROJECTDESCRIPTION, Database.Project.C_ORGANIZATIONTITLE}, new int[] {
R.id.txt_title, R.id.image, R.id.txt_list_desc, R.id.txt_org}));
I want to put an extra String to some TextViews above when its displayed on the list. For example, I want to add a String with the word "from" on R.id.txt_org, before the populated String from the database which is Database.Project.C_ORGANIZATIONTITLE
Let's say the populated String is: New Organisation,
with an extra String "from" what will be displayed is: from New Organisation
Can anybody help me with that? Thank you very much.
EDITED:
FYI, this is my SimpleCursorAdapter method:
class MySimpleCursorAdapter extends SimpleCursorAdapter {
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
loader = new ImageLoader(context);
this.context = context;
}
Context context=null;
ImageLoader loader = null;
public void setViewImage(ImageView v, String value) {
v.setTag(value);
loader.DisplayImage(value, context, v);
}
}
Since you're already using a custom adapter, override the adapter's bindView() and newView() methods, rather than getView(). That way you will not have to manually deal with recycling the row's view.
Within these method you can get the data from the resulting Cursor and manipulate it before binding it to your row's view.
GetView Vs. BindView in a custom CursorAdapter?
How to override CursorAdapter bindView
//Edit: some more code below. Note that this is just a rough outline and by no means complete or tested.
class MySimpleCursorAdapter extends SimpleCursorAdapter {
private ImageLoader mLoader = null;
private LayoutInflater mInflater = null;
private int mBusinessNameIndex = -1;
private int mSmallImageIndex = -1;
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
mLoader = new ImageLoader(context);
mInflater = getLayoutInflater();
mBusinessNameIndex = c.getColumnIndexOrThrow(Database.Project.NAME);
mSmallImageIndex = c.getColumnIndexOrThrow(Database.Project.C_SMALLIMAGE);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.row, null);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Get your views from 'view'
TextView someTextView = (TextView) view.findViewById(R.id.xxx);
ImageView someImageView = (ImageView) view.findViewById(R.id.yyy);
// Set the data
someTextView.setText("from " + cursor.getString(mBusinessNameIndex));
mLoader.DisplayImage(cursor.getString(mSmallImageIndex ), context, someImageView);
}
}
I'm trying to populate listview from my SQLite database... this is how I get my data from database:
Cursor c = database.rawQuery("SELECT * FROM " + TableName, null);
int Column1 = c.getColumnIndex("uri");
int Column2 = c.getColumnIndex("file");
int Column3 = c.getColumnIndex("id");
c.moveToFirst();
if (c != null) {
do {
String uri = c.getString(Column1);
String file = c.getString(Column2);
int id = c.getInt(Column3);
} while (c.moveToNext());
}
I would normally add an array to listview like that:
ListView my_listview2 = (ListView) findViewById(R.id.listView1);
String my_array[] = {"Android", "iPhone"};
my_listview2.setAdapter(new ArrayAdapter<String>(this, R.layout.row, R.id.my_custom_row, my_array));
How can I make an array to setadapter from my sql query?
The best way to do this is to use a CursorAdapter or a SimpleCursorAdapter. This will give you the best performance and once you figure it out you'll find it's the simplest approach when using a SQLite db.
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html
Below is a simple CustomCursorAdapter that I use frequently. Just add the CustomCursorAdapter class as an inner class.
protected class CustomCursorAdapter extends SimpleCursorAdapter {
private int layout;
private LayoutInflater inflater;
private Context context;
public CustomCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.layout = layout;
this.context = context;
inflater = LayoutInflater.from(context);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Log.i("NewView", newViewCount.toString());
View v = inflater.inflate(R.layout.list_cell, parent, false);
return v;
}
#Override
public void bindView(View v, Context context, Cursor c) {
//1 is the column where you're getting your data from
String name = c.getString(1);
/**
* Next set the name of the entry.
*/
TextView name_text = (TextView) v.findViewById(R.id.textView);
if (name_text != null) {
name_text.setText(name);
}
}
Create an instance of the CustomCursorAdapter like so...
You'll need to create your cursor just like you're already doing.
protected String[] from;
protected int[] to;
//From is the column name in your cursor where you're getting the data
//to is the id of the view it will map to
from = new String[]{"name"};
to = new int[]{R.id.textView};
CustomCursorAdapter adapter = new CustomCursorAdapter(this, R.layout.list, cursor, from, to);
listView.setAdapter(adapter);
I found working with the notepad tutorial very useful for learning about this.
It shows you how to implement the listview using the sqlite database in very easy steps.
http://developer.android.com/resources/tutorials/notepad/index.html