How to header in Gridview? - android

I have a gridview as you can see in the 1st picture . Now I want to add header to some specific part of the gridview as in 2nd picture. I am struggling to achieve this.
May I get any idea on how to achieve this view.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
holder = null;
Product productItem = (Product) productList.get(position);
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(R.layout.products_grid_item_layout, parent, false);
holder = new ViewHolder();
holder.productImage = (ImageView) row.findViewById(R.id.productImage);
holder.productImageClone = (ImageView) row.findViewById(R.id.productImageClone);
holder.detailsIcon = (ImageView) row.findViewById(R.id.detailsIcon);
holder.productTitle = (TextView) row.findViewById(R.id.productTitle);
holder.productSubTitle = (TextView) row.findViewById(R.id.productSubTitle);
holder.productQuantity = (TextView) row.findViewById(R.id.productQuantity);
holder.priceDollar = (TextView) row.findViewById(R.id.priceDollar);
holder.priceCent = (TextView) row.findViewById(R.id.priceCent);
holder.productCount = (TextView) row.findViewById(R.id.productCount);
holder.productGridLayout = (RelativeLayout) row.findViewById(R.id.productGridLayout);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
String price = productItem.getPrice().toString();
String[] pricearray;
pricearray = price.split("\\.");
holder.productTitle.setText(productItem.getTitle().toString());
holder.productSubTitle.setText(productItem.getSubtitle().toString());
holder.productQuantity.setText(productItem.getVolume().toString());
holder.priceDollar.setText(pricearray[0]+".");
holder.priceCent.setText(pricearray[1]);
if(productItem.getInCart()) {
holder.productCount.setVisibility(View.VISIBLE);
holder.productCount.setText(productItem.getVolume());
}
Picasso.with(context)
.load(productItem.getImageUrl())
.placeholder(R.drawable.favourites)
.error(R.drawable.favourites)
.into(holder.productImage);
Picasso.with(context)
.load(productItem.getImageUrl())
.placeholder(R.drawable.favourites)
.error(R.drawable.favourites)
.into(holder.productImageClone);
urlSlug = productItem.getUrlSlug();
holder.detailsIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final int position = currentGridView.getPositionForView(v);
Log.e("grid position", position+"");
Intent productDetailIntent = new Intent(context,ProductDetailActivity.class);
productDetailIntent.putExtra("url_slug", productList.get(position).getUrlSlug());
context.startActivity(productDetailIntent);
}
});
return row;
}

Try this way to add header
public class ListAsGridExampleAdapter extends ListAsGridBaseAdapter {
Integer[] mArray = new Integer[] {1,2,3,4,5,6,7,8,9,10,11,12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
private LayoutInflater mInflater;
public ListAsGridExampleAdapter(Context context) {
super(context);
mInflater = LayoutInflater.from(context);
}
#Override
public Integer getItem(int position) {
return mArray[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
return mArray.length;
}
#Override
protected View getItemView(int position, View view, ViewGroup parent) {
if (view == null) {
view = mInflater.inflate(R.layout.simple_list_item, null);
}
TextView tv = (TextView) view.findViewById(R.id.text);
tv.setText(String.valueOf(getItem(position)));
return view;
}
}
https://android.googlesource.com/platform/packages/apps/Gallery2/+/idea133/src/com/android/photos/views/HeaderGridView.java
https://github.com/liaohuqiu/android-GridViewWithHeaderAndFooter
Grid With Header and Footer
You can also Use StickyHeader

Related

Get data from Async for Retrofit 2.0

I am using retrofit 2.0 and This code is part of my fragment and adapter. I don't get values from this method because of asyn. Values are date, soup, maindinner, thirdkind, fourtkind, fifthkind. I want to add them in mylistview. How can I get this values. I want to show them on listview.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_dining, container, false);
rowItemDinings = new ArrayList<RowItemDining>();
DiningInterface diningInterface = RetroClient.getClient().create(DiningInterface.class);
Call<Dining[]> call = diningInterface.getJsonValues();
call.enqueue(new Callback<Dining[]>()
{
#Override
public void onResponse(Call<Dining[]> call, Response<Dining[]> response)
{
dinings = Arrays.asList(response.body());
cacheVersion = dinings.get(0).cacheVersion;
for(int i=0; i<dinings.size(); i++)
{
date.add(dinings.get(i).date);
soup.add(dinings.get(i).soup);
mainDinner.add(dinings.get(i).mainDinner);
thirdKind.add(dinings.get(i).thirdKind);
fourthKind.add(dinings.get(i).fourthKind);
fifthKind.add(dinings.get(i).fifthKind);
RowItemDining item = new RowItemDining(date.get(i), soup.get(i), mainDinner.get(i), thirdKind.get(i), fourthKind.get(i), fifthKind.get(i));
rowItemDinings.add(item);
}
//Toast.makeText(getActivity(), "This is my date! " + soup.get(0) + "" + soup.get(4)+ "" + soup.get(5) + soup.get(6)+ "" + soup.get(7), Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<Dining[]> call, Throwable t)
{
Log.e(TAG, "Error: " + t.toString());
}
});
mylistview = (ListView) getView().findViewById(R.id.dining_list);
CustomAdapterDining adapter = new CustomAdapterDining(getActivity(), rowItemDinings);
mylistview.setAdapter(adapter);
return view;
}
CustomAdapterDining.java
public class CustomAdapterDining extends BaseAdapter
{
Context context;
List<RowItemDining> rowItemDinings;
List<RowItemDining> data;
public ListView mylistview;
public CustomAdapterDining( List<RowItemDining> rowItemDinings)
{
this.rowItemDinings = rowItemDinings;
}
public CustomAdapterDining(Context context, List<RowItemDining> rowItemDinings)
{
this.context = context;
this.rowItemDinings = rowItemDinings;
}
#Override
public int getCount()
{
return rowItemDinings.size();
}
#Override
public Object getItem(int position)
{
return rowItemDinings.get(position);
}
#Override
public long getItemId(int position)
{
return rowItemDinings.indexOf(getItem(position));
}
/* private view holder class */
private class ViewHolder
{
TextView date;
TextView soup;
TextView mainDinner;
TextView thirdKind;
TextView fourthKind;
TextView fifthKind;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_row_dining, null);
holder = new ViewHolder();
holder.date = (TextView) convertView.findViewById(R.id.date);
holder.soup = (TextView) convertView.findViewById(R.id.soup);
holder.mainDinner = (TextView) convertView.findViewById(R.id.main_dinner);
holder.thirdKind = (TextView) convertView.findViewById(R.id.third_kind);
holder.fourthKind = (TextView) convertView.findViewById(R.id.fourth_kind);
holder.fifthKind = (TextView) convertView.findViewById(R.id.fifth_kind);
RowItemDining row_pos = rowItemDinings.get(position);
holder.date.setText(row_pos.getDate());
holder.soup.setText(row_pos.getSoup());
holder.mainDinner.setText(row_pos.getMainDinner());
holder.thirdKind.setText(row_pos.getThirdKind());
holder.fourthKind.setText(row_pos.getFourthKind());
holder.fifthKind.setText(row_pos.getFifthKind());
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
return convertView;
because the request turn in background and the response will be after the Adapter initialisation so you need to add in your adapter a setter for data example :
in Adapter
void setData(List<RowItemDining> data){
this.data=data;
notifyDataSetChanged();
}
in fragment :
mylistview = (ListView) view.findViewById(R.id.dining_list);
CustomAdapterDining adapter = new CustomAdapterDining(getActivity(), rowItemDinings);
mylistview.setAdapter(adapter);
call.enqueue(new Callback<Dining[]>()
{
#Override
public void onResponse(Call<Dining[]> call, Response<Dining[]> response)
{
dinings = Arrays.asList(response.body());
cacheVersion = dinings.get(0).cacheVersion;
for(int i=0; i<dinings.size(); i++)
{
[...]
}
adapter.setData(rowItemDinings);
}
UPDATE : Add adapter changes
#Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder = null;
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_row_dining, null);
holder = new ViewHolder();
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.date = (TextView) convertView.findViewById(R.id.date);
holder.soup = (TextView) convertView.findViewById(R.id.soup);
holder.mainDinner = (TextView) convertView.findViewById(R.id.main_dinner);
holder.thirdKind = (TextView) convertView.findViewById(R.id.third_kind);
holder.fourthKind = (TextView) convertView.findViewById(R.id.fourth_kind);
holder.fifthKind = (TextView) convertView.findViewById(R.id.fifth_kind);
RowItemDining row_pos = rowItemDinings.get(position);
holder.date.setText(row_pos.getDate());
holder.soup.setText(row_pos.getSoup());
holder.mainDinner.setText(row_pos.getMainDinner());
holder.thirdKind.setText(row_pos.getThirdKind());
holder.fourthKind.setText(row_pos.getFourthKind());
holder.fifthKind.setText(row_pos.getFifthKind());
return convertView;
}

Android Problems with onClickListener in Adapter

I've spent hours searching for a solution but everything I've tried doesn't work, it simply yields the same results as the code below does.
I am trying to have an onClickListener change the visibility of a TextView but this code always sets the one I click and then another one below.
class EventiAdapter extends ArrayAdapter<CustomEventi> {
List<CustomEventi> customEventi;
LayoutInflater inflater;
EventiAdapter(#NonNull Context context, #LayoutRes int resource, List<CustomEventi> objects) {
super(context, resource, objects);
customEventi = objects;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
final EventiViewHolder eventiViewHolder;
if(view == null) {
eventiViewHolder = new EventiViewHolder();
view = inflater.inflate(R.layout.eventi_list, parent, false);
eventiViewHolder.imageTV = (ImageView) view.findViewById(R.id.image);
eventiViewHolder.nameTV = (TextView) view.findViewById(R.id.name);
eventiViewHolder.categoryTV = (TextView) view.findViewById(R.id.category);
eventiViewHolder.latLngTV = (TextView) view.findViewById(R.id.latLng);
eventiViewHolder.placeTV = (TextView) view.findViewById(R.id.place);
eventiViewHolder.dateTV = (TextView) view.findViewById(R.id.date);
eventiViewHolder.timeTV = (TextView) view.findViewById(R.id.time);;
eventiViewHolder.viewInfo = (Button) view.findViewById(R.id.viewInfo);
eventiViewHolder.informationTV = (TextView) view.findViewById(R.id.information);
eventiViewHolder.mapImage = (ImageView) view.findViewById(R.id.mapImage);
view.setTag(eventiViewHolder);
} else {
eventiViewHolder = (EventiViewHolder) view.getTag();
}
eventiViewHolder.viewInfo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(eventiViewHolder.informationTV.getVisibility() == View.VISIBLE) {
eventiViewHolder.informationTV.setVisibility(View.GONE);
eventiViewHolder.mapImage.setVisibility(View.GONE);
eventiViewHolder.viewInfo.setText("VISUALIZZA INFORMAZIONI");
}
else {
eventiViewHolder.informationTV.setVisibility(View.VISIBLE);
eventiViewHolder.mapImage.setVisibility(View.VISIBLE);
eventiViewHolder.viewInfo.setText("NASCONDI INFORMAZIONI");
}
}
});
System.out.println("POSITION: "+position);
CustomEventi cstEventi = customEventi.get(position);
eventiViewHolder.setDataIntoViewHolder(cstEventi);
return view;
}
}
Thank you in advance to anyone who'll try to help me.
Try
1. Add a boolean field visible to CustomEventi class
private boolean visible;
public boolean isVisible { return visible; }
public void setVisible(boolean visible) { this.visible = visible; }
2. Replace your adapter code with this one:
class EventiAdapter extends ArrayAdapter<CustomEventi> {
List<CustomEventi> customEventi;
LayoutInflater inflater;
EventiAdapter(#NonNull Context context, #LayoutRes int resource, List<CustomEventi> objects) {
super(context, resource, objects);
customEventi = objects;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
final EventiViewHolder eventiViewHolder;
System.out.println("POSITION: "+position);
CustomEventi cstEventi = customEventi.get(position);
if(view == null) {
eventiViewHolder = new EventiViewHolder();
view = inflater.inflate(R.layout.eventi_list, parent, false);
eventiViewHolder.imageTV = (ImageView) view.findViewById(R.id.image);
eventiViewHolder.nameTV = (TextView) view.findViewById(R.id.name);
eventiViewHolder.categoryTV = (TextView) view.findViewById(R.id.category);
eventiViewHolder.latLngTV = (TextView) view.findViewById(R.id.latLng);
eventiViewHolder.placeTV = (TextView) view.findViewById(R.id.place);
eventiViewHolder.dateTV = (TextView) view.findViewById(R.id.date);
eventiViewHolder.timeTV = (TextView) view.findViewById(R.id.time);;
eventiViewHolder.viewInfo = (Button) view.findViewById(R.id.viewInfo);
eventiViewHolder.informationTV = (TextView) view.findViewById(R.id.information);
eventiViewHolder.mapImage = (ImageView) view.findViewById(R.id.mapImage);
view.setTag(eventiViewHolder);
} else {
eventiViewHolder = (EventiViewHolder) view.getTag();
}
eventiViewHolder.informationTV.setVisibility(cstEventi.isVisible() ? View.VISIBLE : GONE);
eventiViewHolder.mapImage.setVisibility(cstEventi.isVisible() ? View.VISIBLE : View.GONE);
eventiViewHolder.viewInfo.setText(cstEventi.isVisible() ? "NASCONDI INFORMAZIONI": "VISUALIZZA INFORMAZIONI");
eventiViewHolder.viewInfo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean isVisible = customEventi.isVisible();
customEventi.setVisible(!isVisible);
notifyDataSetChanged();
}
});
eventiViewHolder.setDataIntoViewHolder(cstEventi);
return view;
}
}
Try this one....
public View getView(final int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if(view == null) {
view = inflater.inflate(R.layout.eventi_list, parent,false);
imageTV = (ImageView) view.findViewById(R.id.image);
nameTV = (TextView) view.findViewById(R.id.name);
categoryTV = (TextView) view.findViewById(R.id.category);
latLngTV = (TextView) view.findViewById(R.id.latLng);
placeTV = (TextView) view.findViewById(R.id.place);
dateTV = (TextView) view.findViewById(R.id.date);
timeTV = (TextView) view.findViewById(R.id.time);;
viewInfo = (Button) view.findViewById(R.id.viewInfo);
informationTV = (TextView) view.findViewById(R.id.information);
mapImage = (ImageView) view.findViewById(R.id.mapImage);
viewInfo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(informationTV.getVisibility() == View.VISIBLE) {
informationTV.setVisibility(View.GONE);
mapImage.setVisibility(View.GONE);
viewInfo.setText("VISUALIZZA INFORMAZIONI");
}
else {
informationTV.setVisibility(View.VISIBLE);
mapImage.setVisibility(View.VISIBLE);
viewInfo.setText("NASCONDI INFORMAZIONI");
}
}
});
System.out.println("POSITION: "+position);
CustomEventi cstEventi = customEventi.get(position);
setDataIntoViewHolder(cstEventi);
return view;
}

getting wrong data after scrolling listview in android

I am getting wrong data after scrolling listview,after scrolling images are show on another listitem.
public class ContactListAdapter extends BaseAdapter {
private List<ContactBean> contactDataList;
private ArrayList<ContactBean> arraylist;
Context context;
ViewHolder v;
public ContactListAdapter(List<ContactBean> contactBeans, Context context) {
contactDataList = contactBeans;
this.context = context;
this.arraylist = new ArrayList<ContactBean>();
this.arraylist.addAll(contactDataList);
}
#Override
public int getCount() {
return contactDataList.size();
}
#Override
public Object getItem(int i) {
return contactDataList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
View view = convertView;
if (view == null) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.contact_list_item, null);
Log.e("Inside", "here--------------------------- In view1");
} else {
view = convertView;
Log.e("Inside", "here--------------------------- In view2");
}
v = new ViewHolder();
v.title = (TextView) view.findViewById(R.id.name);
v.phone = (TextView) view.findViewById(R.id.no);
v.imageView = (RoundedImageView) view.findViewById(R.id.pic);
v.firstChar = (TextView) view.findViewById(R.id.tv_firstChae);
final ContactBean data = contactDataList.get(i);
v.title.setText(contactDataList.get(i).getName());
v.phone.setText(contactDataList.get(i).getPhone());
// Set image if exists
try {
if (contactDataList.get(i).getThumb() != null) {
v.firstChar.setVisibility(View.GONE);
v.imageView.setVisibility(View.VISIBLE);
v.imageView.setImageBitmap(data.getThumb());
} else {
v.imageView.setVisibility(View.GONE);
String headerChar = (String) contactDataList.get(i).getName().subSequence(0, 1);
v.firstChar.setText(headerChar);
}
} catch (OutOfMemoryError e) {
// Add default picture
// v.imageView.setImageDrawable(this.context.getDrawable(R.mipmap.ic_launcher));
e.printStackTrace();
}
Log.e("Image Thumb", "--------------" + contactDataList.get(i).getThumb());
view.setTag(data);
return view;
}
static class ViewHolder {
RoundedImageView imageView;
TextView title, phone, firstChar;
}
}
in my contact list some contacts having image and which one not having a image thst show the first letter of initialletter of contact name
enter image description here
run the app i am geting this but scroool the listview the we getenter image description here
Try this:
UPD:
public class ContactListAdapter extends BaseAdapter {
private List<ContactBean> contactBeans;
private Context context;
public ContactListAdapter(List<ContactBean> contactBeans, Context context) {
this.context = context;
this.contactBeans = contactBeans;
}
#Override
public int getCount() {
return contactBeans.size();
}
#Override
public Object getItem(int i) {
return contactBeans.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
ViewHolder v;
View view = convertView;
if (view == null) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.contact_list_item, viewGroup, false);
v = new ViewHolder();
v.title = (TextView) view.findViewById(R.id.name);
v.phone = (TextView) view.findViewById(R.id.no);
v.imageView = (RoundedImageView) view.findViewById(R.id.pic);
v.firstChar = (TextView) view.findViewById(R.id.tv_firstChae);
view.setTag(v);
}
v = (ViewHolder)view.getTag();
final ContactBean data = contactBeans.get(i);
v.title.setText(data.getName());
v.phone.setText(data.getPhone());
// Set image if exists
try {
if (data.getThumb() != null) {
v.firstChar.setVisibility(View.GONE);
v.imageView.setVisibility(View.VISIBLE);
v.imageView.setImageBitmap(data.getThumb());
} else {
v.imageView.setVisibility(View.GONE);
String headerChar = (String) data.getName().subSequence(0, 1);
v.firstChar.setText(headerChar);
}
} catch (OutOfMemoryError e) {
// Add default picture
// v.imageView.setImageDrawable(this.context.getDrawable(R.mipmap.ic_launcher));
e.printStackTrace();
}
Log.e("Image Thumb", "--------------" + data.getThumb());
return view;
}
static class ViewHolder {
RoundedImageView imageView;
TextView title, phone, firstChar;
}
}
You should only initialize your viewHolder once, and thats when your convertView is null. Place this:
if (convertView == null) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.contact_list_item, null);
v = new ViewHolder();
convertView.setTag(v);
} else {
v = convertView.getTag();
}
Check this link for better understanding. It's from Google. Starts at about minute 6:00
https://www.youtube.com/watch?v=wDBM6wVEO70
Remove the global ViewHolder
ViewHolder v;
The scope of ViewHolder instance have to be inside the getView method only not whole adapter.
Replace the
v = new ViewHolder();
with
ViewHolder v = new ViewHolder();
here i cannot find any use of viewHolder actually,
you can simply try like this
public View getView(int i, View convertView, ViewGroup viewGroup) {
View view = convertView;
if (view == null) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.contact_list_item, null);
Log.e("Inside", "here--------------------------- In view1");
TextView title = (TextView) view.findViewById(R.id.name);
TextView phone = (TextView) view.findViewById(R.id.no);
RoundedImageView imageView = (RoundedImageView) view.findViewById(R.id.pic);
TextView firstChar = (TextView) view.findViewById(R.id.tv_firstChae);
final ContactBean data = contactDataList.get(i);
title.setText(contactDataList.get(i).getName());
phone.setText(contactDataList.get(i).getPhone());
// Set image if exists
try {
if (contactDataList.get(i).getThumb() != null) {
firstChar.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageView.setImageBitmap(data.getThumb());
} else {
imageView.setVisibility(View.GONE);
String headerChar = (String) contactDataList.get(i).getName().subSequence(0, 1);
firstChar.setText(headerChar);
}
} catch (OutOfMemoryError e) {
// Add default picture
// v.imageView.setImageDrawable(this.context.getDrawable(R.mipmap.ic_launcher));
e.printStackTrace();
}
Log.e("Image Thumb", "--------------" + contactDataList.get(i).getThumb());
} else {
view = convertView;
Log.e("Inside", "here--------------------------- In view2");
}
return view;
}
Your simply missing to set the character visible, due to it possibly being invisible from being recycled.
The correct code (containing Ricardo Barroca's improvment):
public class ContactListAdapter extends BaseAdapter {
private List<ContactBean> contactDataList;
private ArrayList<ContactBean> arraylist;
Context context;
ViewHolder v;
public ContactListAdapter(List<ContactBean> contactBeans, Context context) {
contactDataList = contactBeans;
this.context = context;
this.arraylist = new ArrayList<ContactBean>();
this.arraylist.addAll(contactDataList);
}
#Override
public int getCount() {
return contactDataList.size();
}
#Override
public Object getItem(int i) {
return contactDataList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
ViewHolder v;
if (convertView == null) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.contact_list_item, null);
v = new ViewHolder();
convertView.setTag(v);
} else {
v = convertView.getTag();
}
View view = convertView;
v.title = (TextView) view.findViewById(R.id.name);
v.phone = (TextView) view.findViewById(R.id.no);
v.imageView = (RoundedImageView) view.findViewById(R.id.pic);
v.firstChar = (TextView) view.findViewById(R.id.tv_firstChae);
final ContactBean data = contactDataList.get(i);
v.title.setText(contactDataList.get(i).getName());
v.phone.setText(contactDataList.get(i).getPhone());
// Set image if exists
try {
if (contactDataList.get(i).getThumb() != null) {
v.firstChar.setVisibility(View.GONE);
v.imageView.setVisibility(View.VISIBLE);
v.imageView.setImageBitmap(data.getThumb());
} else {
v.imageView.setVisibility(View.GONE);
String headerChar = (String) contactDataList.get(i).getName().subSequence(0, 1);
v.firstChar.setVisibility(View.VISIBLE);
v.firstChar.setText(headerChar);
}
} catch (OutOfMemoryError e) {
// Add default picture
// v.imageView.setImageDrawable(this.context.getDrawable(R.mipmap.ic_launcher));
e.printStackTrace();
}
Log.e("Image Thumb", "--------------" + contactDataList.get(i).getThumb());
view.setTag(data);
return view;
}
static class ViewHolder {
RoundedImageView imageView;
TextView title, phone, firstChar;
}
}

ListView - Wrong Recycling behavior with ViewHolder Design

Description:
I'm currently implementing a custom ListViewAdapter using the ViewHolder design pattern. The adapter is using a layout with a button that toggles the visibility of a RelativeLayout.
Problem:
When I click the button and the RelativeLayout is shown, everything seems to work fine until I scroll down. When I scroll down, I see that other listitems have been effected by the previous button click, so the RelativeLayout is visible on other (wrong) items. The item that is effected by the button click seems to be the one that is recycled when I scroll down. Please note that everything else works correct, texts etc. are set at the correct position.
Code:
CustomListAdapter
public class ItemsListAdapter extends ArrayAdapter<Item> {
private Context mContext;
private List<Item> mItems;
public ItemsListAdapter(Context context, int resource, List<Item> objects) {
super(context, resource);
mContext = context;
mItems = objects;
}
static class ViewHolder {
View mView;
boolean mExpanded;
public ViewHolder(View view, boolean expanded)
{
mView = view;
mExpanded = expanded;
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
final Item item = getItem(position);
final ViewHolder holder;
if (v == null) {
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
v = mInflater.inflate(R.layout.custom_list_item, null);
holder = new ViewHolder(v, false);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
if(item != null)
{
TextView tvName = (TextView) holder.mView.findViewById(R.id.tv_name);
tvName.setText(item.getName());
RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
if(holder.mExpanded) {
rlExpand.setVisibility(View.VISIBLE);
}
else {
rlExpand.setVisibility(View.GONE);
}
TextView tvDescription = (TextView) holder.mView.findViewById(R.id.tv_description);
if(tvDescription != null)
tvDescription.setText(item.getDescription());
final ImageButton ibExpand = (ImageButton) holder.mView.findViewById(R.id.ib_expand);
ibExpand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
if (rlExpand.getVisibility() == View.GONE) {
v.setVisibility(View.INVISIBLE);
rlExpand.setVisibility(View.VISIBLE);
holder.mExpanded = true;
}
}
});
ImageButton ibCollapse = (ImageButton) holder.mView.findViewById(R.id.ib_collapse);
ibCollapse.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
ibExpand.setVisibility(View.VISIBLE);
rlExpand.setVisibility(View.GONE);
holder.mExpanded = false;
}
});
}
return v;
}
#Override
public int getCount() {
return mItems.size();
}
#Override
public Truism getItem(int position) {
return mItems.get(position);
}
Any help is highly appreciated! Thank you in advance!
Try to change:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
final Item item = getItem(position);
final ViewHolder holder;
if (v == null) {
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
v = mInflater.inflate(R.layout.custom_list_item, null);
holder = new ViewHolder(v, false);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
if(item != null)
{
TextView tvName = (TextView) holder.mView.findViewById(R.id.tv_name);
tvName.setText(item.getName());
RelativeLayout rlExpand = (RelativeLayout) holder.mView.findViewById(R.id.rl_expand);
if(item.isExpanded) {
rlExpand.setVisibility(View.VISIBLE);
}
else {
rlExpand.setVisibility(View.GONE);
}
TextView tvDescription = (TextView) holder.mView.findViewById(R.id.tv_description);
if(tvDescription != null)
tvDescription.setText(item.getDescription());
[...]
}
return v;
}
Change holder.mExpanded to item.isExpanded

Android: OnClick ImageView not change correct Image

I am creating an app where there are images in a custom Listview. The database put a picture or another. Clicking the image has to change. But when I click the image is not changed at the correct ImageView. It changes other ImageView.
I need any help. thanks
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
final MonumentosHolder holder = new MonumentosHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
holder.position = position;
final MonumentosObj p = monumentosLista.get(position);
holder.texto.setText(p.getNombre());
if (p.getVisto().equals("n")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
}
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(holder.position);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(holder.position);
}
});
imageLoader.displayImage(imageUrls[position], holder.imagen, options, animateFirstListener);
return v;
}
EDIT
Onclick not change the correct image. But when I scroll the listview to below and and return to top, the correct image has changed...
I think that bit of code maybe wrong :
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
private int pos = position;
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(pos);
Try to store position inside holder object and when assigning it in onClick Listener instead
private int pos = position;
do
private int pos = holder.getPosition()
Remember that android ListViews are not loading all items at one time it just loads thats what is visible and few items beyond that,
Also remember that positions of your items in your Arrays doesn't change you may use it somehow :)
try to change
holder.imagenVisto.setOnClickListener(new View.OnClickListener()
by
holder.imagenVisto.setOnClickListener(new OnClickListener()
I think your click listener affect early items in your list!
do this:
put a long item in your viewHolder:
class MonumentosHolder {
.
.
.
long position;
}
and then in your getView, set the holder positon:
View v = convertView;
--EDITED--
final MonumentosHolder holder = new MonumentosHolder();
--END EDITED--
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
**holder.postion = position;**
and then click listener would be like this:
EDITED
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(**holder.position**);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(holder.position);
}
});
EDIT 4
remove the final modifier from holder, define another MonumentosHolder named finalHolder like this:
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
MonumentosHolder holder = new MonumentosHolder();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.listview_row, null);
TextView tv = (TextView) v.findViewById(R.id.textoListviewNombre);
ImageView img3 = (ImageView) v.findViewById(R.id.imagenVisto);
holder.texto = tv;
holder.imagenVisto = img3;
v.setTag(holder);
}
else {
holder = (MonumentosHolder) v.getTag();
}
holder.position = position;
final MonumentosObj p = monumentosLista.get(position);
holder.texto.setText(p.getNombre());
if (p.getVisto().equals("n")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
}
final MonumentosHolder finalHolder = holder;
holder.imagenVisto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MonumentosObj p1 = monumentosLista.get(finalHolder.position);
if (p1.getVisto().equals("s")) {
holder.imagenVisto.setImageResource(R.drawable.vistorojo);
p1.setVisto("n");
} else {
holder.imagenVisto.setImageResource(R.drawable.vistoverde);
p1.setVisto("s");
}
MonumentosAdapter.updateMonumentos(p1);
MonumentosObj p = monumentosLista.get(finalHolder.position);
}
});
imageLoader.displayImage(imageUrls[position], holder.imagen, options, animateFirstListener);
return v;
}

Categories

Resources