Listview not showing consistent data android - android

I am trying to parse this JSON response onto a ListView in android where I am trying to modify the listview by showing an image depending upon the gender and adding a button for male records.
The logic is working fine, except for the last two entries.John Wayne & Leonardo Dicaprio are having details button, same is expected for Johnny Depp & Ravi Tambda.Please guide me for the same.
Using this code, I am trying to differentiate them according to the genders
if(rowData.mgender.equalsIgnoreCase("male"))
{
imageViewStatus.setImageResource(R.drawable.male);
}
else{
imageViewStatus.setImageResource(R.drawable.female);
button.setVisibility(View.GONE);
}
EDIT 1
public View getView(final int position, View convertView, ViewGroup parent){
ViewHolder holder = null;
TextView title = null;
TextView detail = null;
TextView data=null;
TextView message=null;
ImageView imageViewStatus=null;
Button button=null;
final RowData rowData= getItem(position);
if(null == convertView)
{
convertView = layoutInflater.inflate(R.layout.record, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
button=(Button)holder.getProceedButton();
message=holder.getEmail();
message.setText(rowData.mEmail);
title = holder.getName();
title.setText(rowData.mName);
detail = holder.getAddress();
detail.setText(rowData.mAdress);
data= holder.getPhoneNumber();
data.setText(rowData.mMobile+" "+rowData.mOffice);
imageViewStatus=holder.getImage();
System.out.println("This is the gender "+rowData.mgender);
if(rowData.mgender.equalsIgnoreCase("male"))
{
imageViewStatus.setImageResource(R.drawable.male);
}
else{
imageViewStatus.setImageResource(R.drawable.female);
System.out.println("Button Visibility"+button.getVisibility());
button.setVisibility(View.GONE);
}
return convertView;
}

Keep in mind that ListView children are always reused while you scroll them. When you set a property according to some condition in getView(), you have to revert that property when the condition isn't met. You're hiding the button when the gender is female, but when this view gets reused to populate a male contact, the button is still invisible and you have to set it as visible again.
Check this out:
if(rowData.mgender.equalsIgnoreCase("male"))
{
imageViewStatus.setImageResource(R.drawable.male);
button.setVisibility(View.VISIBLE); // You need to add this line in your code
} else {
imageViewStatus.setImageResource(R.drawable.female);
button.setVisibility(View.GONE);
}

Related

Event error when clicked each delete button in Android ListView

I am making Android app but I am stuck on constructing list view.
I want to remove each item by using delete button on each list item. What I mean that if I press a delete button in a specific row, a list item on the same row should be removed.
However, I got some bugs on here. When I press any delete buttons on the view, only last item on the view is deleted, not the item in same row. I don't know why each delete button's event action is connected to only last item's id.
Here is my Adapter code.
public View getView(int i, View convertView, ViewGroup parent){
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.item,null);
viewHolder = new ViewHolder();
viewHolder.nickname_textView = (TextView)convertView.findViewById(R.id.nickname);
viewHolder.content_textView = (TextView)convertView.findViewById(R.id.post_content);
viewHolder.date_textView = (TextView)convertView.findViewById(R.id.date);
viewHolder.company_textView = (TextView)convertView.findViewById(R.id.company);
viewHolder.location_textView = (TextView)convertView.findViewById(R.id.location);
viewHolder.profile_imageView = (ImageView)convertView.findViewById(R.id.imageView);
viewHolder.deleteButton = (Button)convertView.findViewById(R.id.deleteButton);
viewHolder.idHolder_textView = (TextView)convertView.findViewById(R.id.idView);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.nickname_textView.setText(list_itemArrayList.get(i).getNickname());
viewHolder.content_textView.setText(list_itemArrayList.get(i).getContent());
viewHolder.date_textView.setText(list_itemArrayList.get(i).getWrite_date().toString());
viewHolder.location_textView.setText(list_itemArrayList.get(i).getLocation());
viewHolder.company_textView.setText(list_itemArrayList.get(i).getCompany());
viewHolder.profile_imageView.setImageResource(list_itemArrayList.get(i).getProfile_image());
viewHolder.idHolder_textView.setText(""+list_itemArrayList.get(i).getId());
viewHolder.idHolder_textView.setVisibility(View.INVISIBLE);
viewHolder.deleteButton.setId(list_itemArrayList.get(i).getId());
viewHolder.deleteButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String sID = viewHolder.idHolder_textView.getText().toString();
long id = Long.parseLong(sID);
UserPosts deletePost = new UserPosts(context);
deletePost.open();
deletePost.deleteItem(id);
deletePost.close();
}
});
return convertView;
}
I have no idea why my deleteButton.setOnClickListener doesn't work well.
Thank you.
Here is my application screenshot
enter image description here
viewHolder.idHolder_textView.getText() will return the value of last visible items of the ListView. Try replacing these lines
String sID = viewHolder.idHolder_textView.getText().toString();
long id = Long.parseLong(sID);
With this
long id = list_itemArrayList.get(i).getId();

Listview button backround issue while scrolling in Android

I have a Listview which shows Facebook friend image and name.There is a Button on each row on the right side to do some operation withe that particular Facebook friend.The Button can either have 3 backgrounds based on some condition. Those are as Follows,
1.Set the button background to "Background1.png" if that friend is not invited.
2.Set the button background to "background2.png" if that friend is invited.
3.Set the button background to "background3.png" if that friend had completed the survey.
I have some given conditions which checks whether the friend is invited or not.Also for the survey thing.Attached screenshot shows what I need actually.
My problem is the button background changes while scrolling as Listview reuses the position.I cant use general views to show it as number of Facebook friend varies and it will show memory issue.
Below is what I have tried so far. Please guide me how to achieve this.
Code:
#Override
public View getView(int position, View convertView,
ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = mInflater.inflate(R.layout.category_listview, null);
Facebook_FriendImage=(SmartImageView)vi.findViewById(R.id.category_image);
Facebook_FriendName = (TextView) vi.findViewById(R.id.category_name);
invite = (Button) vi.findViewById(R.id.invite);
invite.setTag(position);
if (position==2 || position==3) {
invite.setBackgroundResource(R.drawable.background1);
}
else if (position==5 || position==8) {
invite.setBackgroundResource(R.drawable.background2);
}
else {
invite.setBackgroundResource(R.drawable.background3);
}
//Snippet for loading FB Friend Image
int loader = R.drawable.no_image;
Facebook_FriendImage.setScaleType(ImageView.ScaleType.FIT_XY);
Facebook_FriendImage.setImageUrl(GlobalClass.FACEBOOK_FRIEND_IMAGE_URL.get(position), loader);
//Snippet for Loading FB Friend Name
String unicode=new String(GlobalClass.FACEBOOK_FRIEND_NAME.get(position));
Typeface font= Typeface.createFromAsset(getAssets(), "NotoSans-Bold.ttf");
Facebook_FriendName.setTypeface(font);
Facebook_FriendName.setText(unicode);
return vi;
}
The if conditions I have given here is just for simplification.
solution may be this:
simply delete only condition.
if(convertView == null)
may this help.
you should also try to make new View:
View vi = convertView;
if(vi == null) {
//your code
}
return vi;
Use a Holder to your ListView like this :
public View getView(int position, View convertView,
ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null){
convertView = mInflater.inflate(R.layout.category_listview, null);
holder = new ViewHolder();
holder.Facebook_FriendImage=(SmartImageView)convertView.findViewById(R.id.category_image);
holder.Facebook_FriendName = (TextView) convertView.findViewById(R.id.category_name);
holder.invite = (Button) convertView.findViewById(R.id.invite);
invite.setTag(position);
convertView.setTag(holder);
}
else {
holder = (ViewHolder)convertView.getTag();
}
if (position==2 || position==3) {
holder.invite.setBackgroundResource(R.drawable.background1);
}
else if (position==5 || position==8) {
holder.invite.setBackgroundResource(R.drawable.background2);
}
else {
holder.invite.setBackgroundResource(R.drawable.background3);
}
//Snippet for loading FB Friend Image
int loader = R.drawable.no_image;
holder.Facebook_FriendImage.setScaleType(ImageView.ScaleType.FIT_XY);
holder.Facebook_FriendImage.setImageUrl(GlobalClass.FACEBOOK_FRIEND_IMAGE_URL.get(position), loader);
//Snippet for Loading FB Friend Name
String unicode=new String(GlobalClass.FACEBOOK_FRIEND_NAME.get(position));
Typeface font= Typeface.createFromAsset(getAssets(), "NotoSans-Bold.ttf");
holder.Facebook_FriendName.setTypeface(font);
holder.Facebook_FriendName.setText(unicode);
return convertView;
}
and the class ViewHolder should be like this :
class ViewHolder{
SmartImageView Facebook_FriendImage;
TextView Facebook_FriendName;
Button invite;
}
This is the problem of view recycling i also faced the same problem. Go through link nelow it solved my problem
check box in listview not working properly

Scrolling ListView populates dummy values

My listview contains one image,and some textview; there are two textiview which contains the price and special price,if special price is 0 than set only price textview and special price let it null,but special price is > 0 than set price value as well special price,fisrt time everything is going good but when i am scrolling the listview then blank textview set with dumyy valueenter code here
Here is my getView method code.
#Override
public View getView(final int position, View convertView, ViewGroup parent){
//public View getView(int position, View convertView, ViewGroup parent) {
/*View vi = convertView;
if (convertView == null)
{
vi = inflater.inflate(R.layout.list_row, null);
}
*/
int pos=position;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_row, null);
viewHolder=new ViewHolder();
viewHolder.txt_id = (TextView) convertView.findViewById(R.id.id); // title
viewHolder.txt_product_name = (TextView) convertView.findViewById(R.id.title); // title
viewHolder.artist = (TextView) convertView.findViewById(R.id.artist); // artist
// name
viewHolder.txt_mspecialprice_withouttax = (TextView) convertView.findViewById(R.id.duration); // duration
viewHolder.stock = (TextView) convertView.findViewById(R.id.stck);
viewHolder.txt_mprice_withouttax = (TextView) convertView.findViewById(R.id.txtmpricewithouttax);
viewHolder.thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb
// image
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
String mspecialprice_str=song.get(CustomizedListView.KEY_PRODUCT_MSPECIAL_WITHOUT_TAX);
//String substr_mspecialprice_str=mspecialprice_str.substring(1,mspecialprice_str.indexOf("."));
//String substr_mspecialprice_str_replaced=substr_mspecialprice_str.replace(",", "");
String msaleprice_str=song.get(CustomizedListView.KEY_PRODUCT_MPRICE_WITHOUT_TAX);
//String substr_msaleprice_str=msaleprice_str.substring(0,msaleprice_str.indexOf("."));
//String substr_msaleprice_str_replaced=substr_msaleprice_str.replace(",", "");
viewHolder.txt_id.setText(song.get(CustomizedListView.KEY_PRODUCT_ID));
viewHolder.txt_product_name.setText(song.get(CustomizedListView.KEY_PRODUCT_NAME));
viewHolder.artist.setText(song.get(CustomizedListView.KEY_PRODUCT_DESCRIPTION));
viewHolder.stock.setText(song.get(CustomizedListView.KEY_STOCK));
if(mspecialprice_str.equals("0"))
{
//txt_mspecialprice_withouttax.setText(song.get(CustomizedListView.KEY_PRODUCT_MSPECIAL_WITHOUT_TAX));
viewHolder.txt_mprice_withouttax.setText("$"+(song.get(CustomizedListView.KEY_PRODUCT_MPRICE_WITHOUT_TAX)));
viewHolder.txt_mprice_withouttax.setTextColor(Color.parseColor("#64aef9"));
}
//if(!(mspecialprice_str.equals("0")))
//{
else
{
viewHolder.txt_mspecialprice_withouttax.setText("$"+(song.get(CustomizedListView.KEY_PRODUCT_MSPECIAL_WITHOUT_TAX)));
viewHolder.txt_mprice_withouttax.setText("$"+(song.get(CustomizedListView.KEY_PRODUCT_MPRICE_WITHOUT_TAX)));
viewHolder.txt_mprice_withouttax.setPaintFlags(viewHolder.txt_mprice_withouttax.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
viewHolder.txt_mprice_withouttax.setTextColor(Color.parseColor("#F01616"));
}
imageLoader.DisplayImage(
song.get(CustomizedListView.KEY_PRODUCT_IMAGEURL), viewHolder.thumb_image);
return convertView;
}
}
class ViewHolder {
TextView txt_id ; // title
TextView txt_product_name; // title
TextView artist ; // artist
// name
TextView txt_mspecialprice_withouttax; // duration
TextView stock ;
TextView txt_mprice_withouttax;
ImageView thumb_image ; // thumb
}
ListView, GridView reuse views used as list items/grid elements. getView() is called everytime android tries to draw next element while scrolling your view. There is no need to prevent that!
Edit - Atrix1987
From the developer docs
An Adapter object acts as a bridge between an AdapterView and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set.
Suppose you have 10 elements which you want to show using your GridView/ListView and the maximum visible items is 5 then the same 5 views can be reused to display the rest of the 5 elements when you scroll. This is the intended behavior and is the right way to do things [keeps number of views to a minimum].
You don't have control on getView method, the framework does that for you.
The GridView widget extends AdapterView. It uses the adapter to allow the reuse of Views and improve performance. There is no way to avoid calling getView() - it is essential to the whole AdapterView idea. If you want a static layout, perhaps you should use something else.

ListView item style keeps changing randomly when there are multiple style in the same ListView

I have made a chat application where the chat view is formed from many rows in a ListView where messages sent by the user are displaying in white and messages received by friend are displayed in blue.
This behavior works fine, but when I scroll the list after becoming really big (e.g. 30 rows) the colors are messed. I use different layouts for each row, white row layout and blue row layout.
When I scroll multiple times up and down the list the colors keeps switching randomly (i.e. some of my messages are in blue and others in white, and some of the other end (the friend chatting with me) becomes white and other messages become blue in a random way.
I'll give you a snipped preview on the code used:
This is the getView method in my custom adapter which extends BaseAdapter:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final int pos = position;
String from = messages.get(pos).getFrom();
if (convertView == null) {
holder = new ViewHolder();
// If message is sent by me (the user)
if(from.toString().toLowerCase().equals("me")){
convertView = mInflater.inflate(R.layout.chat_msg_row2, null);
}
// if message is sent by his friend (the other end user)
else{
convertView = mInflater.inflate(R.layout.chat_msg_row, null);
}
holder.userName = (TextView) convertView.findViewById(R.id.msgusername);
holder.userImage = (ImageView) convertView.findViewById(R.id.ppic);
holder.date = (TextView) convertView.findViewById(R.id.msgdate);
holder.text = (TextView) convertView.findViewById(R.id.msg);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.userName.setText( messages.get(pos).getFrom() );
holder.text.setText( messages.get(pos).getText() );
holder.date.setText( messages.get(pos).getDate() );
String img = messages.get(pos).getImage();
if(img.substring(0,4).equalsIgnoreCase("http") ){
try{
ImageLoader imloader = new ImageLoader( ChatActivity.this );
holder.userImage.setTag(img);
imloader.DisplayImage( img, ChatActivity.this , holder.userImage );
}
catch(Exception e){
e.printStackTrace();
}
}
return convertView;
}
public long getItemId(int position){
return 1;
}
public class ViewHolder{
TextView userName;
ImageView userImage;
TextView text;
TextView date;
}
The two layouts, chat_msg_row2 and chat_msg_row, are identical except for the Drawable used, where one is using a white image and the other using a blue image.
I recently faced similar problem. What I did was remove the
if (convertView == null)
and the return the View itself. What that above code does is : it checks if there are previous cache present in the present list. If present it re-uses previously present list. Hope it helps
As you didn't use the getItemViewType and the getViewTypeCount methods of the adapter, then the ListView will assume you only have one type of row(although you actually use two types) and will recycle rows as they appear in the list. So, when the convertView is not null you get a recycled row that could be either one of those two types depending on its position.
But the methods above should be implemented only if your rows are really different(extra widgets, placement rules etc). If your two rows are different only by the background image then you need only one row and you'll be setting the background based on your app's logic, something like this:
//...
if (convertView == null) {
holder = new ViewHolder();
// just inflate one of the rows if they are identical
convertView = mInflater.inflate(R.layout.chat_msg_row, parent, false);
holder.userName = (TextView) convertView.findViewById(R.id.msgusername);
holder.userImage = (ImageView) convertView.findViewById(R.id.ppic);
holder.date = (TextView) convertView.findViewById(R.id.msgdate);
holder.text = (TextView) convertView.findViewById(R.id.msg);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// set the background image as desired
if(from.toString().toLowerCase().equals("me")){
// I assumed you set the background on the root of the View row, convertView
// otherwise search for the desired view in convertView and set the background
convertView.setBackgroundResource(R.drawable.the_me_background_drawable);
} else {
convertView.setBackgroundResource(R.drawable.the_other_user_background_drawable);
}
// ...

Deleting items from a ListView using a custom BaseAdapter

I am using a customised BaseAdapter to display items on a ListView. The items are just strings held in an ArrayList.
The list items have a delete button on them (big red X), and I'd like to remove the item from the ArrayList, and notify the ListView to update itself.
However, every implementation I've tried gets mysterious position numbers given to it, so for example clicking item 2's delete button will delete item 5's. It seems to be almost entirely random.
One thing to note is that elements may be repeated, but must be kept in the same order. For example, I can have "Irish" twice, as elements 3 and 7.
My code is below:
private static class ViewHolder {
TextView lang;
int position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.language_link_row, null);
holder = new ViewHolder();
holder.lang = (TextView)convertView.findViewById(R.id.language_link_text);
holder.position = position;
final ImageView deleteButton = (ImageView)
convertView.findViewById(R.id.language_link_cross_delete);
deleteButton.setOnClickListener(this);
convertView.setTag(holder);
deleteButton.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.lang.setText(mLanguages.get(position));
return convertView;
}
I later attempt to retrieve the deleted element's position by grabbing the tag, but it's always the wrong position in the list. There is no noticeable pattern to the position given here, it always seems random.
// The delete button's listener
public void onClick(View v) {
ViewHolder deleteHolder = (ViewHolder) v.getTag();
int pos = deleteHolder.position;
...
...
...
}
I would be quite happy to just delete the item from the ArrayList and have the ListView update itself, but the position I'm getting is incorrect so I can't do that.
Please note that I did, at first, have the deleteButton clickListener inside the getView method, and used 'position' to delete the value, but I had the same problem.
Any suggestions appreciated, this is really irritating me.
You have to set the position each time. Your implementation only sets the position on the creation of the view. However when the view is recycled (when convertView is not null), the position will not be set to the correct value.
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.language_link_row, null);
holder = new ViewHolder();
holder.lang = (TextView)convertView.findViewById(R.id.language_link_text);
final ImageView deleteButton = (ImageView)
convertView.findViewById(R.id.language_link_cross_delete);
deleteButton.setOnClickListener(this);
convertView.setTag(holder);
deleteButton.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.lang.setText(mLanguages.get(position));
holder.position = position;
return convertView;
}
you need to implement OnItemClickListener interface, and delete the item in the onItemClick method, one parameter of the method is the position.
My final solution was to use the accepted answer by Greg and the following:
Store the holders in a HashMap, with the item positions as the keys (this is initialised as empty in the constructor)
private HashMap mHolders;
Use this as the onClickListener method:
public void onClick(View v) {
ViewHolder deleteHolder = (ViewHolder) v.getTag();
int pos = deleteHolder.position;
mHolders.remove(pos);
ViewHolder currentHolder;
// Shift 'position' of remaining languages
// down since 'pos' was deleted
for(int i=pos+1; i<getCount(); i++){
currentHolder = mHolders.get(i);
currentHolder.position = i-1;
}
mLanguages.remove(pos);
notifyDataSetChanged();
}
[Please excuse the weird formatting. The code embedding isn't working properly]

Categories

Resources