I have a main activity that takes elements from a database and displays them in a clickable listview. I use this method to accomplish the task:
private void fillData() {
// Get all of the notes from the database and create the item list
Cursor c = RequestManager.getRequests(getApplicationContext());
startManagingCursor(c);
String[] from = new String[] { DataBase.KEY_TITLE, DataBase.KEY_BODY };
int[] to = new int[] { R.id.text1, R.id.text2 };
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);
}
I am wondering, is it possible to access a boolean field inside the database, and bold the specific element is the field is marked as unread? The elements are each in a textview, and are then placed in a listview.
Thanks
Edit: Used the suggestion to extend the CursorAdapter Class, but when any element in the list is bolded, the first element is also bolded. Once all the elements are marked as read, the first element goes back to unbolded. Any ideas?
public void bindView(View view, Context context, Cursor cursor) {
TextView textRequestNo = (TextView) view.findViewById(R.id.text1);
TextView textMessage = (TextView) view.findViewById(R.id.text2);
StringBuilder requestNo = new StringBuilder(cursor.getString(cursor
.getColumnIndex("requestNo")));
StringBuilder message = new StringBuilder(cursor.getString(cursor
.getColumnIndex("Message")));
textRequestNo.setText(requestNo);
textMessage.setText(message);
if (cursor.getString(cursor.getColumnIndex("Read")).equals("false"))
{
textRequestNo.setTypeface(null, Typeface.BOLD);
textMessage.setTypeface(null, Typeface.BOLD);
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final View view = mInflater.inflate(R.layout.notes_row, parent, false);
bindView(view, context, cursor);
return view;
}
Unfortunately I think you're going to have to implement your own CursorAdapter in order to achieve this functionality. It's not so bad though; you can make subclass of ResourceCursorAdapter, and then all you need to do is write your own implementation of bindView(). Inside of this implementation, you can read the Cursor to determine if you should bold the row or not.
Related
I am trying to change only one (maybe more) ListView row based on specific condition. I have read many answers on similar questions and tons of other tutorials but I am not able to make anything.
Exactly what I want to achieve is to have row background (easier version) or row picture (I think harder version) set different than others when row from SQLite is set at specific value.
I have got Activity that extends ListActivity and I am setting the ListView adapter like this:
private void refreshList() {
mySQLiteAdapter = new MyDBAdapter(this);
mySQLiteAdapter.open();
String[] columns = { MyDBAdapter.KEY_TITLE, MyDBAdapter.KEY_GENRE,
MyDBAdapter.KEY_PRICE, MyDBAdapter.KEY_ID };
Cursor contentRead = mySQLiteAdapter.getAllEntries(false, columns,
null, null, null, null, MyDBAdapter.KEY_TITLE, null);
SimpleCursorAdapter adapterCursor = new SimpleCursorAdapter(this,
R.layout.row, contentRead, columns, new int[] {
R.id.text1, R.id.detail });
this.setListAdapter(adapterCursor);
mySQLiteAdapter.close();
}
This function is called in onCreate method and in onResume. I want to set different color/image of row where value from column MyDBAdapter.KEY_PRICE is equal to 5. The R.layout.row is my xml file with row design.
Maybe someone can help me with this? Or at least show tutorial describing it?
Simply extend SimpleCursorAdapter and override bindView():
public class MyAdapter extends SimpleCursorAdapter {
public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
super.bindView(view, context, cursor);
if(cursor.getLong(cursor.getColumnIndex(MyDBAdapter.KEY_PRICE)) == 5)
view.setBackgroundColor(0xff00ff00);
else // this will be the default background color: transparent
view.setBackgroundColor(0x00000000);
}
}
You can try to create your custom adapter that extends on SimpleCursorAdapter and inside that, on the method bindView, you can look if the condition you look for is accomplished and make what you want on that method.
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html#bindView(android.view.View, android.content.Context, android.database.Cursor)
Hope to help :)
I've tried all the examples in this site that talk about binding data to a TextView
but nothing solve my problem .
I have a dataBase, and TextView , I bind them together with a simple cursor adapter
MyDataBase mDB = new MyDataBase(this);
Cursor cursor = mDB.all(this);
String[] from = new String[] {mDB.VALUE};
int[] to = new int[] {R.id.text1View1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.main, cursor, from , to );
adapter.setViewBinder(new myViewBinder());
and here is the code of the myViewBinder
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
TextView txtWelcome = (TextView) view;
String name = cursor.getString(VALUE_ID);
txtWelcome.setText(name);
}
can any one help me to know why there's no change in the main activity when it's lunched?
what extra code I need to add ?
Try adding adapter.notifyDataSetChanged() after setting the adapter?
I believe for this to work you would have to be able to set the SimpleCursorAdapter as the adapter on the TextView but the TextView class doesn't support that operation out of the box.
I'm a little stuck at the moment. I know similar questions have been asked, but I haven't been able to find anything that has helped.
I'm trying to get and image to appear in ListView from an internal database inside my android application. I have a database with 141 rows, and each row is labeled 1,2 or 3. I need a different png image (saved in my res/drawable folder) to show depending on the 1,2, or 3. Here is my current Query. Any advice would be welcome. I realize there may be a better way to display the info I need.
public void whosnext(View view) {
// || is the concatenation operation in SQLite
cursor = db.rawQuery("SELECT * FROM eventsv1 WHERE start_time > (DATETIME('now')) AND title LIKE ? ORDER BY date ASC, time DESC",
new String[]{"%" + searchText.getText().toString() + "%"});
adapter = new SimpleCursorAdapter(
this,
R.layout.artist_list_item,
cursor,
new String[] {"title", "time", "date", "title3", "style"},
new int[] {R.id.title, R.id.time, R.id.date, R.id.title3, R.id.style});
setListAdapter(adapter);
}
I would write a custome CursorAdapter
public class WhosNextAdapter extends CursorAdapter
{
public WhosNextAdapter(Context context, Cursor cursor, boolean autoRequery) {
super(context, cursor, autoRequery);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
//This is were you would check your cursor for style (I think that is 1,2,3 your column)
int style = cursor.getInt(cursor.getColumnIndex("style"));
ImageView img = (ImageView) view.findViewById(R.id.yourImageViewId);
switch (style) {
case 1:
img.setImageResource(R.drawable.yourImageForStyle1);
break;
case 2:
img.setImageResource(R.drawable.yourImageForStyle2);
break;
//etc.
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
//Inflate layout R.layout.artist_list_item
//Call bindView passing inflated layout, context, and cursor
//return layout
}
}
You definitely need to extend SimpleCursorAdapter and if your item layout is simple enough, the only thing you need to do is to override setViewImage() method where you simply convert provided value from the database and call setImageResource() method on the ImageView object. Then you won't have to alternate much your attached code.
public class MySimpleCursorAdpater extends SimpleCursorAdapter {
public MySimpleCursorAdpater(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public void setViewImage(ImageView v, String value) {
/*your code to convert value from database to drawable resource id*/
v.setImageResource(resourceId);
}
}
I have a ListView that is fed by an SQLiteDB. On each row returned, I have a clickable TextView that onClick should delete the item on that row. So I need to find the sql rowid, so I can call deleteItem(rowid).
I've tried putting in an invisible TextView that I fill with the sql rowid as the ListView is populated, it works. But I set content view to R.layout.list_view and the invisible TextView is in R.layout.list_item (custom layout for each item line), so I can't seem to access it.
How do I go about making this work or is there a better way?
Here is the code that populates the listview:
private void fillData() {
// Get all of the notes from the database and create the item list
Cursor c = mDbHelper.fetchAllNotes();
startManagingCursor(c);
String[] from = new String[] { CommonDbAdapter.KEY_NOTES };
int[] to = new int[] { R.id.text1 };
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);
}
Here is my current click listener, I'm not sure how to differentiate between a click on the item, which returns the item to another activity and a click on the textview that would delete the item.
itemList = (ListView) findViewById(android.R.id.list);
itemList.setTextFilterEnabled(true);
itemList.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Intent intent = new Intent();
Bundle b = new Bundle();
b.putString("TEXT", ((TextView)v.findViewById(R.id.text1)).getText().toString());
intent.putExtras(b);
setResult(SUCCESS_RETURN_CODE, intent);
finish();
}
});
I was originally trying to get the rowid and use a simple onClick set in the layout. But had problems getting the rowid.
public void clickDelete(View view) {
mDbHelper.deleteNote(rowid);
}
here is a quick way to get a click listener for just your textview:
replace your lines:
SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);
with this:
setListAdapter(new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
final TextView t = (TextView)v.findViewById(R.id.text1);
t.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Hello " + t.hashCode(), Toast.LENGTH_SHORT).show();
}
});
return v;
}
});
now, your text1 view will have an onclick listener, and you can do whatever you want. you need to store the rowId somewhere accessible from inside the onClick method though.
this doesn't exactly answer the question i guess, but it gives you a click listener for an individual view in the listview.
you really should implement a custom CursorAdapter class to do something like this, although you could hack around and retrieve the rowId from somewhere
or you could instead use an invisible textview and add an onclick listener to it(like i've shown above), grab it's value(which is a rowId), and perform an operation.
Are you using a CursorAdapter? If so you can query the Cursor directly for the rowid.
You may want to use OnItemClickListener instead of an OnClickListener. This will set you up with the ListView, the position and the id. I believe if you are using a CursorAdapter that the id given to you is the actual rowid of the row in the database.
Edit: if using OnItemClickListener is not possible, you'll have to change to CursorAdapter from SimpleCursorAdapter to do this. In your bindView method you'll have access to the rowid of the View you are creating, and you can reference this in the OnClickListener you create.
I have list of checkboxes in list binded by Custom simpleCursorAdapter.
In my custom simpleCursorAdapter, I've overridden newView and bindView with my modifications.
I've managed somehow to do multichoice.
The wierd thing is, after I delete any item from my list, the first item's checkbox is being checked all of a sudden. How does that happen? How can I solve it?
My SimpleCursorAdapter class:
public class MyListCursorAdapter extends SimpleCursorAdapter
{
private Context context;
private int layout;
public MyCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to)
{
super(context, layout, c, from, to);
this.context = context;
this.layout = layout;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
Cursor c = getCursor();
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(layout, parent, false);
CheckBox chkBoxBtn = (CheckBox) v.findViewById (R.id.deleteTwittChkBox);
if (chkBoxBtn != null)
{
chkBoxBtn.setChecked(false);
}
return v;
}
#Override
public void bindView(View v, Context context, Cursor c)
{
--binding view to my textsview in my items
//now it's the importat part:
CheckBox chkBoxBtn = (CheckBox) v.findViewById(R.id.deleteTwittChkBox);
if (chkBoxBtn != null)
{
chkBoxBtn.setId(Integer.valueOf(c.getString(c
.getColumnIndex(MyUsers.User._ID))));
chkBoxBtn.setOnClickListener(new OnItemClickListener(chkBoxBtn, v));
chkBoxBtn.setChecked(false);
}
}
//i couldnt find another way of doing this, but this is how i set listeners to my checkboxses
static ArrayList<String> checkedItemsList = new ArrayList<String>();
private class OnItemClickListener implements OnClickListener
{
private int mPosition;
private CheckBox chkBox;
OnItemClickListener(CheckBox mChkBox, View v)
{
chkBox = mChkBox;
chkBox.setChecked(false);
}
#Override
public void onClick(View v)
{
if (chkBox.isChecked())
{
checkedItemsList.add(String.valueOf(chkBox.getId()));
}
else
{
checkedItemsList.remove(String.valueOf(chkBox.getId()));
}
}
}
}
Here is the code part from the ListActivity class which describes the button that deletes the checked box items:
OnClickListener btListener = new OnClickListener()
{
public void onClick(View view)
{
// long[] items = listView.getCheckItemIds();
int x = 0;
Uri myUri = Uri
.parse("content://com.idan.datastorageprovider/users");
String where = "_id" + "=?";
//here i am tatking all checkboxes which ive added from the adapter class
ArrayList<String> checkedItemsList = MySimpleCursorAdapter.checkedItemsList;
for (String itemID : checkedItemsList)
{
getContentResolver()
.delete(myUri, where, new String[] { itemID});
checkedItemsList.remove(itemID);
}
}
};
I doubt that SimpleCursorAdapter is the right class to extend here.
Is the "checked" state connected to the data XML in any way? No? So you need your own custom adapter!
Basically all adapters have to implement a way to generate a view from a given element (more precisely an element position!). This will be called at any time where the list wants to display an element. Now, the trick it uses is to re-use formerly created list view elements that cannot be seen on screen any more! Thus: when you scroll your list down and an element disappears at the top, EXACTLY this view object will be re-used for the next appearing item.
So, when this method is called with a given "old" view that should be re-used, all contained elements will have to be set according the elements data. If a checkbox is part of this game, you will have to have a storage for the checked state! It is not sufficient to have a checkbox as there will be less checkbox objects as there are list elements!
SimpleCursorAdapters are there to - yeah - represent SIMPLE things. An XML describing data (images and text, as the documentation states). Because of this simplicity all you have to do here is provide a method to create NEW element view objects - you are not intercepting the re-use process AT ALL! It basically only knows how to put the data into an existing view object - but it is lacking the knowledge of how to handle checked/unchecked boxes!
Your solution: write your own BaseAdapter extension and do what has to be done: implement "getView" (and some other methods like getItem, getItemId and getCount). It's not hard at all!
This API Demo uses a BaseAdapter and the mExpanded state here is basically identical to your checkbox states!
Good luck!
You might need to call notifyDataSetChanged when you modify the data.
The problem is probably that you're calling setChecked from within the onItemClickListener. One hacky way around this is to do the following before and after you call setChecked from within your listener:
chkBox.setClickable(false);
chkBox.setChecked(false);
checkBox.setClickable(true);
This will prevent your onItemClickListener from getting called when you manually call setChecked.