Simplecursoradapter with Listview just mixed up while scrolling - android

Folks.
I've a problem with my simplecursorAdapter. Everything works perfectly except when scrolling the listview it just mixes up the Favorite icon for the rows which included in the custom layout and it just appears randomly while scrolling. Can you guide me what's wrong in my code?
Thanks in advance!
public class AlternateRowCursorAdapter extends SimpleCursorAdapter {
int layoutn;
Cursor localCursor, test;
Bitmap bitImg;
Context localContext;
Bitmap Avatar;
ImageView one, two, three, four, five;
LayoutInflater mInflater;
SQLiteDatabase mDb;
MyDbHelper mHelper;
public static final String TABLE_NAME = "MSGS";
public static final String COL_MsgID = "msgIdc";
public static final String COL_MsgCat = "msgCatC";
public static final String COL_MsgTit = "msgtitleC";
public static final String COL_MsgFavor = "msgFavorC";
public AlternateRowCursorAdapter (Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, R.layout.listtype, c, from, to);
this.localContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
final Cursor cursbbn = getCursor();
if (row == null)
{
row = ((LayoutInflater) localContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.listtype, null);
}
final String Title;
String SandID;
final String MsgID;
final String MsgFav;
Typeface tf = Typeface.createFromAsset(localContext.getAssets(),"fonts/khalaadsara.ttf");
Title = cursbbn.getString(2);
SandID = cursbbn.getString(1);
MsgID=cursbbn.getString(0);
MsgFav=cursbbn.getString(4);
TextView titler = (TextView) row.findViewById(R.id.Sandtit);
titler.setTypeface(tf);
titler.setText(Title);
one = (ImageView) row.findViewById(R.id.imageView5);
two = (ImageView) row.findViewById(R.id.imageView4);
three = (ImageView) row.findViewById(R.id.ImageView03);
four = (ImageView) row.findViewById(R.id.ImageView02);
five = (ImageView) row.findViewById(R.id.imageView1);
if(MsgFav.contentEquals("YES"))
{
one.setImageResource(R.drawable.favorpress);
}
return row;
}
}
Edit : Here is my code to refresh the values in Onresume event :
private void refreshvalues() {
mDb = mHelper.getWritableDatabase();
curs = mDb.query(MyDbHelper.TABLE_NAME, columns, null, null, null,
null, null,
null);
cursF = mDb.query(TABLE_NAME, columns, COL_MsgFavor + "=" + "?",
new String[] { "YES" }, null, null, COL_MsgTit + " ASC");
String[] headers = new String[] {MyDbHelper.COL_MsgTit ,MyDbHelper.COL_MsgID};
mAdapter = new AlternateRowCursorAdapter(this, R.layout.listtype, curs,
headers, new int[] { R.id.Sandtit});
fAdapter = new AlternateRowCursorAdapter(this, R.layout.listtype,
cursF, headers, new int[] { R.id.Sandtit });
mList.setAdapter(mAdapter);
fList.setAdapter(fAdapter);
curs.moveToFirst();
cursF.moveToFirst();
mAdapter.notifyDataSetChanged();
fAdapter.notifyDataSetChanged();
mList.invalidateViews();
fList.invalidateViews();
curs.requery();
cursF.requery();
}

First of all, you are customizing the ListView which needs to implement the custom adapter that extends any of the SimpleCustomAdapter, ArrayAdapter, and BaseAdapter.
Now, you get your listview messed up because, you are not holding the values in the views. You need to write a class ViewHolder that holds your views of the ListView in the same state, before it was scrolled. And Inside getView() method, you need to implement the else part of the if statement.
This is the efficient way to use ListView. Check below, how it can be implemented:
For example:
I made a class Task which contains the values from the database as:
static class Task {
int task_id;
String task_brief;
String task_priority;
String is_completed = "false";
Task(int tmp_task_id, String tmp_task_brief, String tmp_task_priority,
String tmp_task_is_completed) {
task_id = tmp_task_id;
task_brief = tmp_task_brief;
task_priority = tmp_task_priority;
is_completed = tmp_task_is_completed;
}
int get_task_id() {
return task_id;
}
String get_task_brief() {
return task_brief;
}
String get_task_priority() {
return task_priority;
}
String get_task_is_completed() {
return is_completed;
}
void set_task_is_completed(String tmp_task_is_completed) {
is_completed = tmp_task_is_completed;
}
}
Now, we create a class TaskViewHolder that holds the view:
static class TaskViewHolder {
TextView tv_task_brief;
ImageView iv_task_is_completed;
public TaskViewHolder(TextView tmp_tv_task_brief,
ImageView tmp_iv_task_is_completed) {
tv_task_brief = tmp_tv_task_brief;
iv_task_is_completed = tmp_iv_task_is_completed;
}
TextView get_tv_task_brief() {
return tv_task_brief;
}
ImageView get_iv_task_is_completed() {
return iv_task_is_completed;
}
}
And after that, implement custom adapter as below:
static class TaskAdapter extends ArrayAdapter<Task> {
LayoutInflater inflater;
public TaskAdapter(Context context, List<Task> tmp_al_task) {
super(context, R.layout.single_row_home,
R.id.textViewSingleRowHome, tmp_al_task);
inflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Task task = (Task) this.getItem(position);
final ImageView imageView;
final TextView textView;
if (convertView == null) {
convertView = inflater.inflate(R.layout.single_row_home, null);
imageView = (ImageView) convertView
.findViewById(R.id.imageViewSingleRowHome);
textView = (TextView) convertView
.findViewById(R.id.textViewSingleRowHome);
convertView.setTag(new TaskViewHolder(textView, imageView));
} else {
TaskViewHolder viewHolder = (TaskViewHolder) convertView
.getTag();
imageView = viewHolder.get_iv_task_is_completed();
textView = viewHolder.get_tv_task_brief();
}
imageView.setTag(task);
textView.setText(task.get_task_brief());
if(task.get_task_priority().equals("High"))
textView.setTextColor(Color.RED);
else if(task.get_task_priority().equals("Medium"))
textView.setTextColor(Color.GREEN);
else
textView.setTextColor(Color.BLUE);
if (task.get_task_is_completed().equals("true")) {
imageView.setImageResource(R.drawable.action_cancel_icon);
textView.setPaintFlags(textView.getPaintFlags()
| Paint.STRIKE_THRU_TEXT_FLAG);
} else {
imageView.setImageResource(R.drawable.action_cancel_icon_2);
textView.setPaintFlags( textView.getPaintFlags() & (~ Paint.STRIKE_THRU_TEXT_FLAG));
}
imageView.setFocusable(false);
imageView.setFocusableInTouchMode(false);
imageView.setClickable(true);
imageView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Task task = (Task) imageView.getTag();
if (task.get_task_is_completed().equals("false")) {
imageView.setImageResource(R.drawable.action_cancel_icon);
ContentValues values = new ContentValues();
values.put("is_completed", "true");
database.update("task_info", values, "task_id=?",
new String[] { task.get_task_id() + "" });
values.clear();
textView.setPaintFlags(textView.getPaintFlags()
| Paint.STRIKE_THRU_TEXT_FLAG);
task.set_task_is_completed("true");
} else {
imageView.setImageResource(R.drawable.action_cancel_icon_2);
ContentValues values = new ContentValues();
values.put("is_completed", "false");
database.update("task_info", values, "task_id=?",
new String[] { task.get_task_id() + "" });
values.clear();
textView.setPaintFlags( textView.getPaintFlags() & (~ Paint.STRIKE_THRU_TEXT_FLAG));
task.set_task_is_completed("false");
}
}
});
return convertView;
}
}
Note: One important thing, if your ListView contains items that has click events, then that items should be set to view.setFocusable(false); view.setFocusableInTouchMode(false); and view.setClickable(true);. We need this because ListView takes the click event of any of the view as its own click event. Also, the view's click event should be separated from ListView's Click event.

ListView recycles list item Views. So make sure to always call one.setImageResource().
if (MsgFav.contentEquals("YES")) {
one.setImageResource(R.drawable.favorpress);
} else {
one.setImageResource(R.drawable.default_drawable_as_specified_in_layout);
}

Related

Why is that when I am scrolling up or down the list it activates a Switch listener in my custom cursor adapter?

I can see through the toasts that I have implemented and debugging that when I scroll up or down on my list the onCheckedChanged method is called from my listener. I am recycling the views (view holder pattern) and would imagine that the recycling of views is causing the problem but not sure what to do. Here is the code for the custom cursor adapter -
public class MyCursorAdapter extends CursorAdapter {
private Context mContext;
private LayoutInflater cursorInflater;
private int res;
private String mgName;
private String mMfg;
private String mRarity;
private String mLoosePrice;
private String mgYear;
private String mYear_Mfg;
private int mOwned;
private boolean isOwned;
private Switch mySwitch;
private String mID;
private String mIDfinal;
private View v;
private int position = 1;
public MyCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
cursorInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mContext = context;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
v = cursorInflater.inflate(R.layout.fragment_list, viewGroup, false);
ViewHolder holder = new ViewHolder();
holder.imageView = (ImageView) v.findViewById(R.id.game);
holder.textView1 = (TextView) v.findViewById(R.id.game_Title);
holder.textView2 = (TextView) v.findViewById(R.id.game_mfg);
holder.textView3 = (TextView) v.findViewById(R.id.rarity_value);
holder.textView4 = (TextView) v.findViewById(R.id.loose_cart_value);
holder.switch1 = (Switch) v.findViewById(R.id.owned_switch);
v.setTag(holder);
return v;
}
#Override
public void bindView(final View view, Context context, Cursor cursor) {
//Determines row colors
if (position % 2 == 1) {
view.setBackgroundColor(Color.parseColor("#bbbbbb"));
position++;
} else {
view.setBackgroundColor(Color.parseColor("#7b7b7b"));
position++;
}
if (position > 10) {
position = 1;
}
ViewHolder holder = (ViewHolder) view.getTag();
String mboxArt = cursor.getString(cursor.getColumnIndex("_id"));
mboxArt = "a" + mboxArt;
res = context.getResources().getIdentifier(mboxArt, "drawable", context.getPackageName());
mgName = cursor.getString(cursor.getColumnIndex("gName"));
mMfg = cursor.getString(cursor.getColumnIndex("mfg"));
mgYear = cursor.getString(cursor.getColumnIndex("gYear"));
mYear_Mfg = mMfg + "," + mgYear;
mRarity = cursor.getString(cursor.getColumnIndex("rarity"));
mOwned = cursor.getInt(cursor.getColumnIndex("cart"));
mLoosePrice = cursor.getString(cursor.getColumnIndex("lPrice"));
// mID = cursor.getString(cursor.getColumnIndex("My_Collection_T._id"));
// mIDfinal = "'" + mID + "'";
if (mOwned == 1) {
isOwned = true;
} else {
isOwned = false;
}
view.setTag(holder);
holder.imageView.setImageResource(res);
holder.textView1.setText(mgName);
holder.textView2.setText(mYear_Mfg);
holder.textView3.setText(mRarity);
holder.textView4.setText(mLoosePrice);
holder.switch1.setChecked(isOwned);
//Listener for owned switch
mySwitch = (Switch) view.findViewById(R.id.owned_switch);
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ContentValues mNewValues = new ContentValues();
TextView gameN = (TextView) view.findViewById(R.id.game_Title);
CharSequence text = gameN.getText();
text = "'" + text + "'";
String gameName = text.toString();
if (buttonView.isChecked()) {
mNewValues.put("cart", 1);
mNewValues.put("numCart", 1);
gameName = "gName = " + gameName;
mContext.getContentResolver().update(GamesContract.My_Collection_T.CONTENT_URI, mNewValues, gameName, null);
ContentResolver resolver = mContext.getContentResolver();
Cursor c = resolver.query(GamesContract.My_Collection_T.CONTENT_URI, null, null, null, null);
//For debugging -
if (c != null) {
StringBuilder sb = new StringBuilder();
dumpCursor(c, sb);
String result = sb.toString();
Toast.makeText(mContext,
result,
Toast.LENGTH_LONG
).show();
c.close();
}
/////////////////////////
mContext.getContentResolver().notifyChange(GamesContract.My_Collection_T.CONTENT_URI, null);
} else {
mNewValues.put("cart", 0);
mNewValues.put("numCart", 0);
gameName = "gName = " + gameName;
mContext.getContentResolver().update(GamesContract.My_Collection_T.CONTENT_URI, mNewValues, gameName, null);
ContentResolver resolver = mContext.getContentResolver();
Cursor c = resolver.query(GamesContract.My_Collection_T.CONTENT_URI, null, null, null, null);
//For debugging
if (c != null) {
StringBuilder sb = new StringBuilder();
dumpCursor(c, sb);
String result = sb.toString();
Toast.makeText(mContext,
result,
Toast.LENGTH_LONG
).show();
c.close();
}
/////////////////////////////////////////////
mContext.getContentResolver().notifyChange(GamesContract.My_Collection_T.CONTENT_URI, null);
}
}
});
}
static class ViewHolder {
ImageView imageView;
TextView textView1;
TextView textView2;
TextView textView3;
TextView textView4;
Switch switch1;
}
}
Unfortunately, calling setChecked(boolean) triggers the listener, even if you do it programmatically. That is, there's no way to know whether a user clicked it or if you changed the state programmatically.
Since the Views are recycled, the first time you create the view, owned_switch has no listener attached. You then set the state:
holder.switch1.setChecked(isOwned);
and then attach a listener:
mySwitch.setOnCheckedChangeListener(...);
And everything works as expected. However, after the view is recycled, it still has the listener attached (the same View is returned as convertView in getView()), so the call to:
holder.switch1.setChecked(isOwned);
will trigger the original listener that you've set on the view previously. One simple workaround would be to null out the listener before adjusting the checked state and resetting the listener:
mySwitch.setOnCheckedChangeListener(null);
holder.switch1.setChecked(isOwned);
mySwitch.setOnCheckedChangeListener(...);
Also, not sure why you're making a new variable for mySwitch, as it's the same view as holder.switch1.
As you have stated, since you are recycling the same components, as you scroll up or down, depending upon the item being displayed, the switch button settings (ON/OFF) change. So the switch button which might be set to true in one place for that item will now be showing false for another item in another place (you get the idea) as there is a listener that was attached to this switch. That's an expected outcome of recycling while using the ViewHolder pattern.
One thing you could do is to have a method that resets the onCheckedChanged() listener.

Android AdapterView cannot display database records in some device

I would like to ask some question about AdapterView.
In my application, there is an activity which retrieve data from database and display them in AdapterView.
However, when i install the application in different devices, I found that the part I have just mentioned could only function on some devices. The others cannot show the database results.
Here is my code:
private void showResults(String query) {
Cursor cursor = searchCustByInputText(query);
if (cursor == null) {
//
} else {
// Specify the columns we want to display in the result
String[] from = new String[] {
"cust_code",
"chinese_name"};
// Specify the Corresponding layout elements where we want the columns to go
int[] to = new int[] {
R.id.scust_code,
R.id.schinese_name};
// Create a simple cursor adapter for the definitions and apply them to the ListView
SimpleCursorAdapter customers = new SimpleCursorAdapter(this,R.layout.cust_list_item, cursor, from, to);
mListView.setAdapter(customers);
// Define the on-click listener for the list items
mListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor c = (Cursor) mListView.getItemAtPosition(position);
String cust_code = c.getString(c.getColumnIndex("cust_code"));
if (callFromAct.equals("Main")) {
String pay_term = c.getString(c.getColumnIndex("pay_term"));
String chinese_name = c.getString(c.getColumnIndex("chinese_name"));
String english_name = c.getString(c.getColumnIndex("english_name"));
String address_1 = c.getString(c.getColumnIndex("address_1"));
String address_2 = c.getString(c.getColumnIndex("address_2"));
String address_3 = c.getString(c.getColumnIndex("address_3"));
String address_4 = c.getString(c.getColumnIndex("address_4"));
String contact = c.getString(c.getColumnIndex("contact"));
String telephone = c.getString(c.getColumnIndex("telephone"));
String last_order_date = c.getString(c.getColumnIndex("last_order_date"));
//Pass data to another Activity
Intent it = new Intent(CustEnqActivity.this, CustEnqDetailsActivity.class);
Bundle bundle = new Bundle();
bundle.putString("cust_code", cust_code);
bundle.putString("pay_term", pay_term);
bundle.putString("chinese_name", chinese_name);
bundle.putString("english_name", english_name);
bundle.putString("address_1", address_1);
bundle.putString("address_2", address_2);
bundle.putString("address_3", address_3);
bundle.putString("address_4", address_4);
bundle.putString("contact", contact);
bundle.putString("telephone", telephone);
bundle.putString("last_order_date", last_order_date);
it.putExtras(bundle);
startActivity(it);
}
else {
returnToCallingAct(cust_code);
}
//searchView.setQuery("",true);
}
});
}
}
Besides, I discovered there were two warnings in my logcat.
The constructor SimpleCursorAdapter(Context, int, Cursor, String[], int[]) is deprecated
AdapterView is a raw type. References to generic type AdapterView should be parameterized
Are they related to the problem?
Try to create a class that extends BaseAdapter and use ViewHolders for performance
eg:
public class MyBaseAdapter extends BaseAdapter {
ArrayList<ListData> myList = new ArrayList<ListData>();
LayoutInflater inflater;
Context context;
public MyBaseAdapter(Context context, ArrayList<ListData> myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context); // only context can also be used
}
#Override
public int getCount() {
return myList.size();
}
#Override
public ListData getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyViewHolder mViewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.layout_list_item, null);
mViewHolder = new MyViewHolder();
convertView.setTag(mViewHolder);
} else {
mViewHolder = (MyViewHolder) convertView.getTag();
}
mViewHolder.tvTitle = detail(convertView, R.id.tvTitle, myList.get(position).getTitle());
mViewHolder.tvDesc = detail(convertView, R.id.tvDesc, myList.get(position).getDescription());
mViewHolder.ivIcon = detail(convertView, R.id.ivIcon, myList.get(position).getImgResId());
return convertView;
}
// or you can try better way
private TextView detail(View v, int resId, String text) {
TextView tv = (TextView) v.findViewById(resId);
tv.setText(text);
return tv;
}
private ImageView detail(View v, int resId, int icon) {
ImageView iv = (ImageView) v.findViewById(resId);
iv.setImageResource(icon); //
return iv;
}
private class MyViewHolder {
TextView tvTitle, tvDesc;
ImageView ivIcon;
}
}
More info/example:
http://www.pcsalt.com/android/listview-using-baseadapter-android/#sthash.lNGSCiyB.dpbs

setting text view according its position of the row a listview filled by SimpleCursorAdapter database with click on the row

setting the text view according its position in of the row a list view filled from SimpleCursorAdapter from database on the click of the onlistitemclicked
my custom list view has an image& textview for a name and another invisible text view which will be visible and be setting with a different number on the row clicked only but the problem is that when i clicked any row the text appeared on the view at the first row only whatever the row i clicked
and I tried to use the set and get methods but i found its used for the Base Adapter.
and the textview which will visible is not from data base
can some one tell me how to do it please
here is a part of the code
public class Select_players_two extends ListActivity
{
protected static class RowViewHolder
{
public TextView tvOne;
public TextView tvTwo;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(android.view.Menu menu)
{
// TODO Auto-generated method stub
return super.onCreateOptionsMenu(menu);
}
public class CustConAdpterSelect extends SimpleCursorAdapter
{
int i = 0;
int count;
private int layout;
LayoutInflater inflator;
final SQLiteConnector sqlCon = new SQLiteConnector(mContext);
private ImageButton editBtn;
private ImageButton delBtn;
int id ;
TextView txt_select;
CharSequence txt_char;
static final String KEY_No = "playerNo";
public CustConAdpterSelect(Context context, int layout, Cursor c,
String[] from, int[] to, int flags)
{
super(context, layout, c, from, to,0);
this.layout = layout;
inflator= LayoutInflater.from(context);
}
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View retView = inflater.inflate(R.layout.lv_name_photo, parent, false);
RowViewHolder holder = new RowViewHolder();
holder.tvOne = (TextView) retView.findViewById(R.id.name);
holder.tvTwo = (TextView) retView.findViewById(R.id.txt_number);
// holder.tvOne.setOnClickListener(tvOneLapOnClickListener);
retView.setTag(holder);
return retView;
}
#Override
public void bindView(View v, final Context context, Cursor c)
{
editBtn=(ImageButton) v.findViewById(R.id.edit_btn);
if( editBtn.getVisibility() == View.VISIBLE )
editBtn.setVisibility(View.INVISIBLE);
else
editBtn.setVisibility(View.INVISIBLE);
//set delete button invisble
delBtn=(ImageButton) v.findViewById(R.id.del_btn);
if( delBtn.getVisibility() == View.VISIBLE )
delBtn.setVisibility(View.INVISIBLE);
else
delBtn.setVisibility(View.INVISIBLE);
//final int
id = c.getInt(c.getColumnIndex(Contacts.ID));
final String name = c.getString(c.getColumnIndex(Contacts.NAME));
final String phone = c.getString(c.getColumnIndex(Contacts.PHONE));
final String email = c.getString(c.getColumnIndex(Contacts.MAIL));
final String fb = c.getString(c.getColumnIndex(Contacts.FB));
final byte[] image = c.getBlob(c.getColumnIndex(Contacts.IMAGE));
ImageView iv = (ImageView) v.findViewById(R.id.photo);
if (image != null)
{
if (image.length > 3)
{
iv.setImageBitmap(BitmapFactory.decodeByteArray(image, 0,image.length));
}
}
TextView tname = (TextView) v.findViewById(R.id.name);
tname.setText(name);
TextView tphone = (TextView) v.findViewById(R.id.phone);
tphone.setText(phone);
TextView temail = (TextView) v.findViewById(R.id.email);
temail.setText(email);
txt_select=(TextView)v.findViewById(R.id.txt_number);
// final SQLiteConnector sqlCon = new SQLiteConnector(context);
//for( i = 0; i <=4; i++)
/*
v.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//onitem clicked
txt_char = txt_select.getText();
{
if (txt_char != null)
{
int txt_int = Integer.parseInt(txt_char.toString());
int count = txt_int;
Log.d("count1",String.valueOf(count));
count++;
txt_select.setText(String.valueOf(count));
Log.d("count",String.valueOf(count));
if( txt_select.getVisibility() == View.INVISIBLE )
txt_select.setVisibility(View.VISIBLE);
else
txt_select.setVisibility(View.INVISIBLE);
Log.d("number", String.valueOf(i));
}
/* if( txt_select.getVisibility() == View.INVISIBLE )
txt_select.setVisibility(View.VISIBLE);
else
txt_select.setVisibility(View.INVISIBLE);
i++;
Log.d("number", String.valueOf(i));*/
/* }
}
});
*/
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
final View view = super.getView(position, convertView, parent);
final TextView textView = (TextView)view.findViewById(R.id.txt_number);
/* textView.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Log.i("Click", "TextView clicked on row " + position);
// textView.setTag(position);
txt_char = txt_select.getText();
Log.d("txt", txt_char.toString());
if (txt_char != null)
{
int txt_int = Integer.parseInt(txt_char.toString());
Log.d("txt2", txt_char.toString());
int count = txt_int;
Log.d("count1",String.valueOf(count));
count++;
txt_select.setText(String.valueOf(count));
CharSequence txt_char2 = txt_select.getText();
Log.d("ttxt", txt_char2.toString());
Log.d("count",String.valueOf(count));
if( txt_select.getVisibility() == View.INVISIBLE )
txt_select.setVisibility(View.VISIBLE);
else
txt_select.setVisibility(View.INVISIBLE);
Log.d("number", String.valueOf(i));
i++;
}
}*/
// }); // TODO Auto-generated method stub
return view;
}
private OnClickListener tvOneLapOnClickListener = new OnClickListener()
{
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// get the RowViewHolder
RowViewHolder holder = new RowViewHolder();
// Get the holder for the row
holder = (RowViewHolder) ((View) v.getParent()).getTag();
if (holder.tvOne.getVisibility() == View.INVISIBLE)
holder.tvOne.setVisibility(View.VISIBLE);
else
holder.tvOne.setVisibility(View.INVISIBLE);
}
};
}
}
that is the database class "SQLiteConnector"
public class SQLiteConnector
{
private SQLiteDatabase db;
private SQLiteHelper sqlHp,sqlhpc;
private Cursor cur,curc;
public SQLiteConnector(Context context)
{
sqlHp = new SQLiteHelper(context, Contacts.DB_NAME, null, 1);
sqlhpc = new SQLiteHelper(context, Contacts.DB_NAME, null, 1);
}
// insert new player in the list//
public void insertContact(String name, String phone, String mail,String fb,byte[] blob) {
ContentValues cv = new ContentValues();
cv.put(Contacts.NAME, name);
cv.put(Contacts.PHONE, phone);
cv.put(Contacts.MAIL, mail);
cv.put(Contacts.FB, fb);
cv.put(Contacts.IMAGE,blob);
db = sqlHp.getWritableDatabase();
db.insert(Contacts.TABLE, null, cv);
db.close();
}
// insert the score sheet //
public void insertContact_score(String score, String num_call, String num_collection ,String shape_type,
String score_sec, String num_call_sec, String num_collection_sec ,String shape_type_sec,
String score_third, String num_call_third, String num_collection_third ,String shape_type_third,
String score_forth, String num_call_forth, String num_collection_forth ,String shape_type_forth)
{
ContentValues cvscore = new ContentValues();
cvscore.put(Contacts.SCORE_st, score);
cvscore.put(Contacts.NUM_CALL_st, num_call);
cvscore.put(Contacts.NUM_COLLECTION_st, num_collection);
cvscore.put(Contacts.SHAPE_CALL_st, shape_type);
cvscore.put(Contacts.SCORE_sec, score_sec);
cvscore.put(Contacts.NUM_CALL_sec, num_call_sec);
cvscore.put(Contacts.NUM_COLLECTION_sec, num_collection_sec);
cvscore.put(Contacts.SHAPE_CALL_sec, shape_type_sec);
cvscore.put(Contacts.SCORE_third, score_third);
cvscore.put(Contacts.NUM_CALL_third, num_call_third);
cvscore.put(Contacts.NUM_COLLECTION_third, num_collection_third);
cvscore.put(Contacts.SHAPE_CALL_third,shape_type_third);
cvscore.put(Contacts.SCORE_forth, score_forth);
cvscore.put(Contacts.NUM_CALL_forth, num_call_forth);
cvscore.put(Contacts.NUM_COLLECTION_forth, num_collection_forth);
cvscore.put(Contacts.SHAPE_CALL_forth,shape_type_forth);
//cvscore.put(Contacts.IMAGE,blob);
db = sqlhpc.getWritableDatabase();
db.insert(Contacts.TABLESCORE, null, cvscore);
db.close();
}
public void updateContact_score(long id,String score, String num_call, String num_collection ,String shape_type,
String score_sec, String num_call_sec, String num_collection_sec ,String shape_type_sec,
String score_third, String num_call_third, String num_collection_third ,String shape_type_third,
String score_forth, String num_call_forth, String num_collection_forth ,String shape_type_forth)
{
ContentValues cvscore = new ContentValues();
cvscore.put(Contacts.SCORE_st, score);
cvscore.put(Contacts.NUM_CALL_st, num_call);
cvscore.put(Contacts.NUM_COLLECTION_st, num_collection);
cvscore.put(Contacts.SHAPE_CALL_st, shape_type);
cvscore.put(Contacts.SCORE_sec, score_sec);
cvscore.put(Contacts.NUM_CALL_sec, num_call_sec);
cvscore.put(Contacts.NUM_COLLECTION_sec, num_collection_sec);
cvscore.put(Contacts.SHAPE_CALL_sec, shape_type_sec);
cvscore.put(Contacts.SCORE_third, score_third);
cvscore.put(Contacts.NUM_CALL_third, num_call_third);
cvscore.put(Contacts.NUM_COLLECTION_third, num_collection_third);
cvscore.put(Contacts.SHAPE_CALL_third,shape_type_third);
cvscore.put(Contacts.SCORE_forth, score_forth);
cvscore.put(Contacts.NUM_CALL_forth, num_call_forth);
cvscore.put(Contacts.NUM_COLLECTION_forth, num_collection_forth);
cvscore.put(Contacts.SHAPE_CALL_forth,shape_type_forth);
//cvscore.put(Contacts.IMAGE,blob);
db = sqlhpc.getWritableDatabase();
db.update(Contacts.TABLESCORE, cvscore, Contacts.ID+"="+ id, null);
db.close();
}
public void updateContact(long id,String name, String phone, String mail,String fb,byte[] blob) {
ContentValues cv = new ContentValues();
cv.put(Contacts.NAME, name);
cv.put(Contacts.PHONE, phone);
cv.put(Contacts.MAIL, mail);
cv.put(Contacts.FB, fb);
cv.put(Contacts.IMAGE,blob);
db = sqlHp.getWritableDatabase();
db.update(Contacts.TABLE, cv, Contacts.ID+"="+ id, null);
db.close();
}
public Cursor getAllContacts() {
db = sqlHp.getReadableDatabase();
cur=db.query(Contacts.TABLE,null, null,null, null, null, "name");
return cur;
}
public Cursor getAllScores() {
db = sqlhpc.getReadableDatabase();
curc=db.query(Contacts.TABLESCORE,null, null,null, null, null, "score_st");
return curc;
}
public void deletescore(long id) {
System.out.println("DELETE ");
db = sqlhpc.getWritableDatabase();
db.delete(Contacts.TABLESCORE, "_id="+id , null);
db.close();
}
public Cursor getOneContact(long id) {
db = sqlHp.getReadableDatabase();
cur=db.query(Contacts.TABLE, null, "_id="+ id, null, null, null,null);
return cur;
}
public void deleteContact(long id) {
System.out.println("DELETE ");
db = sqlHp.getWritableDatabase();
db.delete(Contacts.TABLE, "_id="+id , null);
db.close();
}
}
I believe what you need to do is use the Tag facility of the row view container to identify the textview it contains and then retrieve it in the listener to identify the correct textview. The way I've done it is to use a holder for the row contained views, so you can access any that you need. For example:
protected static class RowViewHolder {
public TextView tvOne;
public TextView tvTwo;
}
Then in your newView method, populate the holder and set the Tag to it:
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View retView = inflater.inflate(R.layout.single_row_item, parent, false);
RowViewHolder holder = new RowViewHolder();
holder.tvOne = (TextView) retView.findViewById(R.id.name);
holder.tvTwo = (TextView) retView.findViewById(R.id.txt_number);
retView.setTag(holder);
return retView;
}
In your listener then you can access the correct textview:
public void onClick(View v) {
ListView lv = (ListView) v.getParent();
final int position = lv.getPositionForView((View) v.getParent());
// get the RowViewHolder
RowViewHolder holder = new RowViewHolder();
holder = (RowViewHolder) ((View) v.getParent()).getTag();
if(holder.tvOne.getVisibility() == View.INVISIBLE ) {
holder.tvOne.setVisibility(View.VISIBLE);
}
else
{
holder.tvOne.setVisibility(View.INVISIBLE);
}
}
Apologies, but I've not been able to test this code but I hope it gives you a pointer to the process. You shouldn't need the RowViewHolder but I've included it so you or others can see how to access multiple views within the row.
You may find the this video helpful The World of ListView I think you'll find the relevant discussion at about 4:10 in which describes how the views are res-used and how index, position etc. relate.
I also found one of the answers to this question helpful Android: ListView elements with multiple clickable buttons
There are multiple ways of doing this. The way I was suggesting assumes you have a single code module for the activity containing the CustConAdpterSelect class. So the structure looks something like this.
package com.example.totastest;
// imports
public class Copy_2_of_MainActivity extends Activity {
protected static class RowViewHolder
{
public TextView tvOne;
public TextView tvTwo;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public class CustConAdpterSelect extends SimpleCursorAdapter
{
// ...
public CustConAdpterSelect(Context context, int layout, Cursor c, String[] from, int[] to)
{
super(context, layout, c, from, to, 0);
// ...
}
public View newView(Context context, Cursor cursor, ViewGroup parent)
{
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View retView = inflater.inflate(R.layout.lv_name_photo, parent, false);
RowViewHolder holder = new RowViewHolder();
holder.tvOne = (TextView) retView.findViewById(R.id.name);
holder.tvTwo = (TextView) retView.findViewById(R.id.txt_number);
holder.tvOne.setOnClickListener(tvOneLapOnClickListener);
retView.setTag(holder);
return retView;
}
#Override
public void bindView(View v, final Context context, Cursor c)
{
// ...
}
#SuppressWarnings("unchecked")
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
// ...
}
private OnClickListener tvOneLapOnClickListener = new OnClickListener() {
#Override
// When the tvOne button is clicked, execute this code
public void onClick(View v) {
// get the RowViewHolder
RowViewHolder holder = new RowViewHolder();
// Get the holder for the row
holder = (RowViewHolder) ((View) v.getParent()).getTag();
if (holder.tvOne.getVisibility() == View.INVISIBLE)
holder.tvOne.setVisibility(View.VISIBLE);
else
holder.tvOne.setVisibility(View.INVISIBLE);
}
};
}
protected void onListItemClick(ListView l, View v, int position, long id)
{
// ...
}
}

getting listview row data

I have a listview in my application.I want to set the value of textview in that particular row when I click one of the textview in that row itself.so,I tried like below
likes.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
TextView t=(TextView)v;
TextView likesnumber1 = (TextView) findViewById(R.id.likesnumber);
int i= Integer.parseInt(likescount.get(position));
if(like_or_ulike.get(position).equals("Like")){
Log.e("inlike","like");
like_or_ulike.set(position, "Unlike");
t.setText(like_or_ulike.get(position));
UrltoValue.getValuefromUrl("https://graph.facebook.com/"+objectid.get(position)+"/likes?access_token="+accesstoken+"&method="+"post");
j=i+1;
String s=Integer.toString(j);
likescount.set(position, s);
likesnumber1.setText(likescount.get(position));
}
else{
Log.e("unlike","unlike");
like_or_ulike.set(position, "Like");
t.setText(like_or_ulike.get(position));
UrltoValue.getValuefromUrl("https://graph.facebook.com/"+objectid.get(position)+"/likes?access_token="+accesstoken+"&method="+"DELETE");
j=i-1;
String s=Integer.toString(j);
likescount.set(position, s);
likesnumber1.setText(likescount.get(position));
}
}
});
the "likes" reference which I used is textview and I want to set the textview by getting the id of that particular row.
TextView likesnumber1 = (TextView) findViewById(R.id.likesnumber);
when I use this I am getting the id of the first visible row of the screen.
How can I get the id of textview of that particular row,on a textview click.
Thanks
I'm not sure how you are populating your list with data, however here is a method I use that works very well.
Data Models
public class Publication {
public String string1;
public String string2;
public Publication() {
}
public Publication(String string1, String string2) {
this.string1= string1;
this.string2= string2;
}
}
Create an array adapter
public class ContactArrayAdapter extends ArrayAdapter<ContactModel> {
private static final String tag = "ContactArrayAdapter";
private static final String ASSETS_DIR = "images/";
private Context context;
//private ImageView _emotionIcon;
private TextView _name;
private TextView _email;
private CheckBox _checkBox;
private List<ContactModel> contactModelList = new ArrayList<ContactModel>();
public ContactArrayAdapter(Context context, int textViewResourceId,
List<ContactModel> objects) {
super(context, textViewResourceId, objects);
this.context = context;
this.contactModelList = objects;
}
public int getCount() {
return this.contactModelList.size();
}
public ContactModel getItem(int index) {
return this.contactModelList.get(index);
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
// ROW INFLATION
Log.d(tag, "Starting XML Row Inflation ... ");
LayoutInflater inflater = (LayoutInflater) this.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.contact_list_entry, parent, false);
Log.d(tag, "Successfully completed XML Row Inflation!");
}
// Get item
final ContactModel contactModel = getItem(position);
Resources res = this.getContext().getResources();
//Here are some samples so I don't forget...
//
//_titleCount = (TextView) row.findViewById(R.id.category_count);
// _category.setText(categories1.Category);
//
//if (categories1.Category.equals("Angry")) {
//Drawable angry = res.getDrawable(R.drawable.angry);
//_emotionIcon.setImageDrawable(angry);
//}
_checkBox = (CheckBox) row.findViewById(R.id.contact_chk);
_email = (TextView) row.findViewById(R.id.contact_Email);
_name = (TextView)row.findViewById(R.id.contact_Name);
//Set the values
_checkBox.setChecked(contactModel.IsChecked);
_email.setText(contactModel.Email);
_name.setText(contactModel.Name);
_checkBox.setOnClickListener(new CompoundButton.OnClickListener() {
#Override
public void onClick(View view) {
if (contactModel.IsChecked) {
contactModel.IsChecked = false;
notifyDataSetChanged();
}
else {
contactModel.IsChecked = true;
notifyDataSetChanged();
}
}
});
return row;
}
}
Use the array adapter to fill your list
ContactArrayAdapter contactArrayAdapter;
//
List<ContactModel> contactModelList;
//Fill list with your method
contactModelList = getAllPhoneContacts();
//
contactArrayAdapter = new ContactArrayAdapter(getApplicationContext(), R.layout.contact_list_entry, contactModelList);
//
setListAdapter(contactArrayAdapter);
A sample method to fill data:
public List<ContactModel> getAllPhoneContacts() {
Log.d("START","Getting all Contacts");
List<ContactModel> arrContacts = new Stack<ContactModel>();
Uri uri = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
Cursor cursor = getContentResolver().query(uri, new String[] {ContactsContract.CommonDataKinds.Email.DATA1
,ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
,ContactsContract.CommonDataKinds.Phone._ID}, null , null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
cursor.moveToFirst();
while (cursor.isAfterLast() == false)
{
String email= cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
if (email != null)
{
ContactModel contactModel = new ContactModel();
contactModel.Name = name;
contactModel.Email = email;
contactModel.IsChecked = false;
arrContacts.add(contactModel);
}
cursor.moveToNext();
}
cursor.close();
cursor = null;
Log.d("END","Got all Contacts");
return arrContacts;
}
Accessing the data on click
final ListView lv = getListView();
lv.setTextFilterEnabled(true);
//Click handler for listview
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View view, int position, long id) {
ContactModel contact= getItem(position);//This gets the data you want to change
//
some method here tochange set data
contact.email = "new#email.com"
//send notification
contactArrayAdapter.notifyDataSetChanged();
}
});

Binding Cursor data to a non-list layout

I'm writing a screen that displays a row's worth of information from a DB. Basically it's a Detail Fragment that represents information pertaining to one 'row' in a table. I want to understand the best practice for binding data from a cursor (one unique row from a table) to a layout of textviews, checkboxes, etc.
Is AdapterView the ticket?
#JoeMalin suggested:
Then write an adapter between a cursor and an array of text views.
Which boils down my question. What's the right way to hook a series of text views to a cursor?
If you want to do processing on some of the cursor data before you move it to the text views, then you're going beyond the adapter pattern, which assumes that "recasting" the form of a data structure to another data structure without any intermediate processing. The virtue of an adapter is that, for two data structures A and B linked by an adapter, it's assumed that B automatically changes whenever A changes.
Of course, you can redefine the idea of adapter to insert your own intermediate operation, such as converting dates, or you could make the conversion an aspect of the view that's displaying the data. I am guessing that the "processing" is really formatting, which you do for display purposes. That's an attribute of the text view, not the data; write something that extends text view and converts dates as needed. Then write an adapter between a cursor and an array of text views.
I recently implemented my own data adapter class that may be in the ball park.
public class NoteImageDataAdapter {
private final View mMainView;
private Cursor mCursor;
private ViewHolder holder;
private ContentObserver mContentObserver;
public static class ViewHolder {
public TextView title;
public TextView text;
public ImageView image;
}
public NoteImageDataAdapter(View mainView, Cursor c) {
if (mainView == null) {
throw new IllegalArgumentException("View mainView cannot be null");
}
if (c == null) {
throw new IllegalArgumentException("Cursor c cannot be null");
}
mMainView = mainView;
mCursor = c;
holder = new ViewHolder();
holder.title = (TextView) mMainView.findViewById(R.id.title);
holder.text = (TextView) mMainView.findViewById(R.id.text);
holder.image = (ImageView) mMainView.findViewById(R.id.myImageView);
mContentObserver = new ImageNoteContentObserver(new Handler());
mCursor.registerContentObserver(mContentObserver);
bindView();
}
class ImageNoteContentObserver extends ContentObserver {
public ImageNoteContentObserver(Handler handler) {
super(handler);
}
#Override
public boolean deliverSelfNotifications() {
return true;
}
#Override
public void onChange(boolean selfChange) {
Log.d("NoteImageDataAdapter", "ImageNoteContentObserver.onChange( "
+ selfChange + ")");
super.onChange(selfChange);
mCursor.requery();
bindView();
}
}
public void bindView() {
Log.d("NoteImageDataAdapter", "bindView");
mCursor.moveToFirst();
holder.text.setText(Note.getText(mCursor));
holder.title.setText(Note.getTitle(mCursor));
Uri imageUri = Note.getImageUri(mCursor);
if (imageUri != null) {
assignImage(holder.image, imageUri);
} else {
Drawable d = Note.getImageThumbnail(mCursor);
holder.image.setImageDrawable(d);
holder.image.setVisibility(View.VISIBLE);
}
}
private static final int MAX_IMAGE_PIXELS = 1024*512;
private void assignImage(ImageView imageView, Uri imageUri){
if (imageView != null && imageUri != null){
ContentResolver cr = imageView.getContext().getContentResolver();
Display display = ((WindowManager) imageView.getContext()
.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
int width = (int) (display.getWidth() * 0.9);
int height = (int) (display.getHeight() * 0.9);
int minSideLength = Math.min(height, width);
Bitmap b = Util.makeBitmap(minSideLength, MAX_IMAGE_PIXELS, imageUri, cr, false);
if (b == null){
b = Util.makeBitmap(minSideLength, MAX_IMAGE_PIXELS/2, imageUri, cr, false);
}
if (b != null){
imageView.setImageBitmap(b);
imageView.setAdjustViewBounds(true);
imageView.setVisibility(View.VISIBLE);
}
}
}
}
and in your activity
private NoteImageDataAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_image_view_layout);
wireDataAdapter();
}
private void wireDataAdapter() {
final String[] COLUMNS = new String[] {
Note.Columns.TITLE,
Note.Columns.TEXT,
Note.Columns.IMAGE_URI,
Note.Columns.IMAGE_THUMBNAIL,
Note.Columns._ID };
// the uri for the note row
Uri contentUri = getIntent().getData();
Cursor cur = managedQuery(contentUri, COLUMNS, null, null, null);
View mainLayout = this.findViewById(R.id.noteImageViewLayout);
mAdapter = new NoteImageDataAdapter(mainLayout, cur);
}
From the activity use:
Adpater adapter = new Adapter(Activity.this or context , Cursor);
setListAdapter(adapter) in case of List Activity;
Otherwise
listViewObj.setAdpater(adapter)
public class CustomCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private Context activityContext;
private ViewHolder holder;
public ContactsAdapter(Context aContext,Cursor cursor) {
super(mContext, cursor);
mInflater = LayoutInflater.from(mContext);
activityContext = aContext;
}
public static class ViewHolder{
public TextView textView1;
// View Group on Row inflate lyaout that need to be used
public ImageView imageView;
}
#Override
public void bindView(View v, Context context, Cursor c) {
holder=(ViewHolder)v.getTag();
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.item_inflate_layout, parent, false);
holder = new ViewHolder();
holder.textView1 = (TextView) v.findViewById(R.id.TEXTVIEW1);
// Other Id that need to be used and are available on item_inflate_layout
holder.imageView = (ImageView) v.findViewById(R.id.IMAGEVIEW);
v.setTag(holder);
bindView(v, context, cursor);
return v;
}
}

Categories

Resources