I have a spinner populated from a cursor using SimpleCursorAdapter
I want to delete some values from this adapter depending on a variable
I try something like this but doesn't work fine
SimpleCursorAdapter toListAdapter = new SimpleCursorAdapter(MoreTicketSalesActivity.this, R.layout.generic_spinneritem, cursor, column,
viewIds) {
#Override
public void bindView(View view, Context context, Cursor cursor) {
super.bindView(view, context, cursor);
if (cursor.getLong(3) < session.getStopIndex()) {
view.setVisibility(View.INVISIBLE);
}
}
};
Please help me
So i find a solution who is just perfect for me
TextView textView = (TextView) view.findViewById(R.id.spinner_item_name);
int index = cursor.getInt(cursor.getColumnIndex("index"));
String name = cursor.getString(cursor.getColumnIndex("name"));
textView.setText(name);
if (index <= this.index) {
textView.setTextColor(Color.LTGRAY);
textView.setClickable(true);
} else {
textView.setTextColor(Color.BLACK);
textView.setClickable(false);
}
First of All you check value of your variable and get location of items to be deleted from the cursor.
Then remove those values from Cursor ( by remove(position of value) or etc ).
Then use toListAdapter.notifyDataSetChanged();
Related
I'm trying to develop an app to record debts in which I have a SwipeMenuListView from this github https://github.com/baoyongzhang/SwipeMenuListView for adding a swipe menu. Using a custom CursorAdapter, I populate the ListView with the name and total debt.
Now, I want to group each listview items depending on the due date. I've created a new column on my SQLite to add a header for each day. Now I just need to use different style for header and items of the ListView. By detecting the new column from bindView and depending on if it's a header or items, it will change, hide and show elements from the same layout.
The problem is that when I scroll the ListView, some of the listview items changed style. It get worse if I keep scrolling up and down. Here's the picture of the error from the listview. Notice that it's all in one session, the header style seems to have been used in some of the items and the header itself changed to red color which suppose to be color code for the items. If I click one of the item, it still get the correct item so I figure its a problem within the cursorAdapter but I just can't figure it out. It is not a mistake in the SQL database which I have checked.
Here's the cursorAdapter.
public class DebtCursorAdapterMain extends CursorAdapter {
public DebtCursorAdapterMain(Context context, Cursor c, int flags) {
super(context, c, flags);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.debt_list_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
int x = Integer.parseInt(cursor.getString(cursor.getColumnIndex(DBHelper.DATE_SEPARATOR_COLUMN)));
TextView tvName = (TextView) view.findViewById(R.id.tvName);
TextView tvTotal = (TextView) view.findViewById(R.id.tvTotal);
if(x == 0) {
DecimalFormat df = new DecimalFormat("#.00");
String nameText = cursor.getString(cursor.getColumnIndex(DBHelper.NAME_COLUMN));
String totalText = "$ " + df.format(cursor.getDouble(cursor.getColumnIndex(DBHelper.TOTAL_COLUMN)));
String type = cursor.getString(cursor.getColumnIndex(DBHelper.TYPE_COLUMN));
if (tvName != null)
tvName.setText(nameText);
if (tvTotal != null)
tvTotal.setText(totalText);
if (type.equals("L"))
view.setBackgroundColor(Color.parseColor("#ff9999"));
if (type.equals("B"))
view.setBackgroundColor(Color.parseColor("#99ff99"));
}
if(x == 1){
String date = cursor.getString(cursor.getColumnIndex(DBHelper.DUE_DATE_COLUMN));
if (tvName != null && tvTotal != null) {
tvName.setText(date);
tvName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22);
tvTotal.setVisibility(View.GONE);
}
}
}
}
Here is the main activity in which the cursorAdapter is called.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find SwipeMenuListView
final SwipeMenuListView swipeMenuList = (SwipeMenuListView) findViewById(R.id.swipeMenuList);
// Create Debt database cursor adapter
cursorAdapter = new DebtCursorAdapterMain(this, null, 0);
// Create SwipeMenuList and set item
SwipeMenuCreator creator = createMainActivitySwipeMenu();
swipeMenuList.setMenuCreator(creator);
swipeMenuList.setAdapter(cursorAdapter);
swipeMenuList.setSwipeDirection(SwipeMenuListView.DIRECTION_LEFT);
// Set SwipeMenuList on item's menu click
swipeMenuList.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
....
}
});
// Swipe menu on Click function
swipeMenuList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
....
}
});
// Initialize cursor and check database for updating top info
getLoaderManager().initLoader(0, null, this);
checkDataBase();
}
I'm still new in android development so please tell me if there's a better approach to this problem. Thanks guys.
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 have a ListView where I send data from a database using SimpleCursorAdapter, but I need to have dynamic row layout, because every table can have different number of columns.
Let's say I create TextViews according to the number of columns:
public int getColumnNumbers() {
int i = 0;
cursor = db.rawQuery("PRAGMA table_info("+DATABASE_TABLE_NAME+")", null);
if (cursor.moveToFirst()) {
do {
i++;
} while (cursor.moveToNext());
}
cursor.close();
return i;
}
........
int rowsNumber = getColumnNumbers();
textViews = new TextView[rowsNumber];
for(i = 0; i < rowsNumber; i++) {
textViews[i] = new TextView(this);
textViews[i].setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
What I'm basically looking for, is a way to get these TextViews passed to CursorAdapter's (or other adapter's) argument int[] to
I'm pretty new to this, so I would appreciate any help or advice.
EDIT:
I'm adding my implementation of bindViewmethod, which I made with help of the links provided here, in case someone would have to face similar issue in the future.
#Override
public void bindView(View view, Context context, Cursor cursor) {
int i, count = myHelper.getColumnNumbers();
String[] columnNames = myHelper.getColumnNamesString();
String text;
LinearLayout layout = (LinearLayout) view.findViewById(R.id.linear_layout_horizontal);
for(i = 0; i < (count-1); i++) {
TextView textView = new TextView(context);
textView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1f));
text = cursor.getString(cursor.getColumnIndexOrThrow(columnNames[i+1]));
textView.setText(text);
layout.addView((TextView)textView);
}
}
EDIT 2:
I found out yesterday that the implementation mentioned above works until you need to scroll. After scrolling, ListView gets deformed.
So again, in case someone would like to do something similar, I'm adding my whole Adapter class.
public class DatabaseCursorAdapter extends CursorAdapter {
private DatabaseHelper myHelper;
private int count;
private String[] columnNames;
public DatabaseCursorAdapter(Context context, Cursor cursor) {
super(context, cursor, 0);
myHelper = new DatabaseHelper(context);
count = myHelper.getColumnNumbers();
columnNames = myHelper.getColumnNamesString();
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(R.layout.text_select, parent, false);
LinearLayout layout = (LinearLayout) view.findViewById(R.id.linear_layout_horizontal);
int i;
for(i = 0; i < count; i++) {
TextView textView = new TextView(context);
textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1f));
textView.setTag(Integer.valueOf(i));
layout.addView(textView);
}
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
int i;
String text;
for(i = 0; i < count; i++) {
TextView textView = (TextView) view.findViewWithTag(Integer.valueOf(i));
text = cursor.getString(cursor.getColumnIndexOrThrow(columnNames[i]));
textView.setText(text);
}
}
}
In the and, as it is with most issues, the solution is pretty easy. Technique is almost the same as if you would use a static layout, except instead of using findViewById, you just tag elements of your layout and use findViewWithTag method.
You need to look at good tutorial, a link is
Populating a ListView with a CursorAdapter . The web page has some nice explanations.
Look at TodoCursorAdapter and the bindView method to check which column/data is available from the database. Snippet of code from tutorial:
#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);
// Extract properties from cursor
String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
// Populate fields with extracted properties
tvBody.setText(body);
}
I think this is a simple code design.
Code in the webpage to populate data onto Listview:
// 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);
You can implement an ArrayAdapter instead of CursorAdapter. This makes sense if your app is not continually interfacing with the database. The link is Using an ArrayAdapter with ListView . It is the same website.
In this case, look at getView method instead of the similar bindView.
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 am creating demo of simple MultiAutoCompleteTextView.
I have gone through the official docs MultiAutoCompleteTextView. Completed this simple tutorial.
But this is something different than what i am trying to achieve.
What i want is :
When i type 'TY' then autocomplete result must suggest me 'Thank You'.
Such acronym and meaning pairs are stored in the database.
Ofcourse my acronym and meaning pairs are not many so storage is not a problem(can store in String Array too).
How can i achieve this ?
My guess would be to do your own ArrayAdapter adapter.
And in that adapter check what the string value is, if it is ie TY then add "Thank you".
Well I solved it by myselves :
I created Custom CursorAdapter. Using the object of my Custom CursorAdapter, i got desired results.
public static class MessageAdapter extends CursorAdapter implements Filterable
{
DatabaseHelper dbHelper;
public MessageAdapter(Context context, Cursor c)
{
super(context, c);
dbHelper=new DatabaseHelper(context);
dbHelper.open();
mContent = context.getContentResolver();
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
final LayoutInflater inflater = LayoutInflater.from(context);
final TextView view = (TextView) inflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false);
view.setText(cursor.getString(cursor.getColumnIndex(DatabaseHelper.KEY_MEANING)));
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor)
{
((TextView) view).setText(cursor.getString(cursor.getColumnIndex(DatabaseHelper.KEY_MEANING)));
}
#Override
public String convertToString(Cursor cursor) {
return cursor.getString(cursor.getColumnIndex(DatabaseHelper.KEY_MEANING));
}
#Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint)
{
if (getFilterQueryProvider() != null)
{
return getFilterQueryProvider().runQuery(constraint);
}
StringBuilder buffer = null;
String args = null;
if (constraint != null)
{
args=constraint.toString();
}
Cursor newCursor=dbHelper.getMeaning(args);
//You have to return results based on the above cursor results. So query whatver you want and return this cursor back.
return newCursor;
}
private ContentResolver mContent;
}
For Simplicity I have created getMeaning() method in my DatabaseHelper class which returns desired results based on String in MultiAutoCompleteTextView:
In DBHelper Class,
public Cursor getMeaning(String searchString)
{
Cursor cursor=sqdb.query(MY_DB, new String[]{KEY_ID,KEY_MEANING}, KEY_SEARCH+" like '"+searchString.toUpperCase()+"%'", null,null, null, null);
return cursor;
}
Reference : http://hello-android.blogspot.com/2011/06/using-autocompletetextview-with-sqlite.html
One way to achieve this would be to attach acronym and full strings something like Thank You - TY in the String array. This way autocomplete can recognize it when you type acronym too. Once the word is selected by the user, you can remove the part after hyphen '-'.