Android Base Adapter - android

I am adding multiple UI elements like SeekBar,ImageView,TextView dynamically to the ListView.But Whenever I try to get the reference to these elements,I am always getting reference to the last element only.
e.g I have multiple SeekBar.When i press play button that SeekBar should update.But the problem is when i press any number of play button only SeekBar at last position is getting updated.
I tried
seekbar.setTag(position);
But of no use.

Finally the solution is, I made my ViewHolder class's object local inside getView() method and assigned it to a global ViewHolder class's object on play button's OnClickListener.This change solved my problem like a miracle.

The tag you are setting should be instance of your ViewHolder class.
Your code can be like this -
public class YourTeamAdapter extends BaseAdapter {
private static Context context;
private ArrayList<TopDataModel> mList;
public YourTeamAdapter(Context c, ArrayList<TopDataModel> list) {
mList = list;
context = c;
}
#Override
public int getCount() {
return mList.size();
}
// get item at givin position
#Override
public TopDataModel getItem(int position) {
return mList.get(position);
}
// get itemID at givin position
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.activity_team_status_list_item, null, true);
holder = new Holder(convertView);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.tvName.setText(getItem(position).getName());
holder.tvRank.setText(getItem(position).getRank());
try {
if (getItem(position).getImage() != null &&
!getItem(position).getImage().equalsIgnoreCase("")) {
holder.imageView.setImageBitmap(SharedHelper.decodeBase64(getItem(position).getImage()));
}
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
private static class Holder {
TextView tvName;
TextView tvRank;
CircularImageView imageView;
public Holder(View convertView) {
this.tvName = (TextView) convertView.findViewById(R.id.name);
this.tvRank = (TextView) convertView.findViewById(R.id.rank);
this.imageView = (CircularImageView) convertView.findViewById(R.id.image);
}
}
}

Related

Android Listview is repeating items when scrolled

I have looked at other threads and I cannot see what is wrong with my listadapter. I have the view holder pattern and I am setting all the values for the list item outside of the convertview null check statement. Im not sure what other things would cause it to repeat the items.
public class ScheduledJobListAdapter extends BaseAdapter {
private static LayoutInflater inflater = null;
private ArrayList<Job> jobList;
private Context context;
public ScheduledJobListAdapter(Context context, ArrayList<Job> jobList) {
this.context = context;
this.jobList = jobList;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() { return jobList.size(); }
#Override
public Job getItem(int position) { return jobList.get(position); }
#Override
public long getItemId(int position) { return 0; }
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ScheduledViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item_scheduled_job,null);
holder = new ScheduledViewHolder();
holder.job = getItem(position);
holder.container = convertView.findViewById(R.id.scheduled_job_layout);
holder.routeOrder = convertView.findViewById(R.id.route_order_textview);
holder.location = convertView.findViewById(R.id.location_textview);
holder.jobRef = convertView.findViewById(R.id.job_ref_textview);
holder.statusIndicator = convertView.findViewById(R.id.status_indicator);
convertView.setTag(holder);
} else {
holder = (ScheduledViewHolder) convertView.getTag();
}
holder.routeOrder.setText(holder.job.getRouteOrder() + "");
holder.location.setText(holder.job.getLocation());
holder.jobRef.setText(holder.job.getJobReference());
return convertView;
}
}
class ScheduledViewHolder {
Job job;
LinearLayout container;
TextView routeOrder;
TextView location;
TextView jobRef;
ImageView statusIndicator;
}
Here's the problem:
holder.job = getItem(position);
Remember the views may be recycled as you scroll, and the job assigned maybe used unintentionally for other positions if you assigned it that way. To fix it, simply assign the job after the if-else condition:
if (convertView == null) {
// ...
} else {
// ...
}
holder.job = getItem(position); // Update the job by position
holder.routeOrder.setText(holder.job.getRouteOrder() + "");
holder.location.setText(holder.job.getLocation());
holder.jobRef.setText(holder.job.getJobReference());

CustomListAdapter not working in some devices?

I have created a customized list adapter to show items in a listview. But this list adapter not working in certain devices. when I tried to log whether data is reaching the adapter, it is reaching there. Folowing is the code of my list adapter.
Please help:
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Schedule> ScheduleItems;
public CustomListAdapter(Activity activity, List<Schedule> ScheduleItems) {
this.activity = activity;
this.ScheduleItems = ScheduleItems;
}
#Override
public int getCount() {
return ScheduleItems.size();
}
#Override
public Object getItem(int location) {
return ScheduleItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
if(convertView==null){
// inflate the layout
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.listvehtemplate, null);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
// viewHolder.status= (ImageView) convertView.findViewById(R.id.cusid);
viewHolder.textViewName=(TextView) convertView.findViewById(R.id.cusname);
// viewHolder.textViewAddress=(TextView) convertView.findViewById(R.id.cusdesc);
//
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// getting Schedule data for the row
Schedule m = ScheduleItems.get(position);
if(m != null) {
viewHolder.textViewName.setText(String.valueOf(m.getcustomername()));
Log.d("log",viewHolder.textViewName.getText().toString());
if(m.getcusid().equals("Finished")){
viewHolder.textViewName.setTextColor(Color.GREEN);
}
else{
viewHolder.textViewName.setTextColor(Color.RED);
// viewHolder.status.setImageResource(R.drawable.xmark);
}
// viewHolder.textViewAddress.setText(String.valueOf(m.getcustomeraddress()));
}
return convertView;
}
static class ViewHolderItem {
// ImageView status;
TextView textViewName;
// TextView textViewAddress;
}
}

boolean variable unavailable in getView()

I never understand the getView() method fully. Here is a case:
Here I have isNoticeRead which is false you can see. But the line gets executed! And when the line in the if statement is executing, isNoticeRead is not found anywhere! If I even place my cursor over it, nothing happens (no tooltip). And it happens for the first item of the ListView. Can you please tell me what am I missing?
My full Adapter
public class NoticesListViewAdapter extends BaseAdapter{
Context context;
ArrayList<NoticeModel> items;
String[] readNotices;
public NoticesListViewAdapter(Context context, ArrayList<NoticeModel> items) {
this.context = context;
this.items = items;
readNotices = SharedPrefUtils.getMarkedNotices(context).split(SharedPrefUtils.SEPARATOR_READ_NOTICE);
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Holder holder;
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.list_item_notices, null);
holder = new Holder();
holder.noticeID = (TextView) convertView.findViewById(R.id.noticeID);
holder.tvNotice = (TextView) convertView.findViewById(R.id.tvNotice);
holder.tvDateTime = (TextView) convertView.findViewById(R.id.tvDateTime);
holder.tvNoticeRead = (TextView) convertView.findViewById(R.id.tvNoticeRead);
convertView.setTag(holder);
}else{
holder = (Holder) convertView.getTag();
}
try {
String str = items.get(position).getId() + "";
holder.noticeID.setText(str);
holder.tvNotice.setText(items.get(position).getText());
holder.tvDateTime.setText(DateTimeUtils.changeDateTimeFormat(items.get(position).getDateTime(), DateTimeUtils.FORMAT8, DateTimeUtils.FORMAT3));
final boolean isNoticeRead = items.get(position).isRead();
if (isNoticeRead) {
holder.tvNoticeRead.setVisibility(View.VISIBLE);
}
// for(String s : readNotices) {
// if (s.equals(str)) {
// holder.tvNoticeRead.setVisibility(View.VISIBLE);
//// break;
// }
// }
}catch (Exception e){e.printStackTrace();}
return convertView;
}
class Holder{
TextView tvNotice, tvDateTime, noticeID, tvNoticeRead;
}
}
The views of your holder are being re-used by the List. Thus you may have an instance which is initialized with VISIBLE, but when the view is reused and filled, you don't reset its state - so it is still visible.
if (isNoticeRead) {
holder.tvNoticeRead.setVisibility(View.VISIBLE);
} else {
holder.tvNoticeRead.setVisibility(View.INVISIBLE);
}
when you make variable final then it's means unable to assigned value during execute because you make it final remove final or define isNoticeRead as field.
then it may be work fine for you..

notifyDatasetChanged is not working inside the getView() method for Custom Adapter In Android

I am basically trying hide and show a text in the list row when I am clicking a button in the list row. I have added the onClick() for the button inside getView() method and then calling the notifyDataSetChanged(). But it is not working. No change in the text visibility. Here is my custom Adapter code:
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
boolean flag = false;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
}
#Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return mListQuestion.size();
}
#Override
#SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (flag == false)
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
flag = true;
}
else if (flag == true)
{
Logger.d("arrow clicked when flag is true");
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
flag = false;
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
Can someone please tell what I am doing wrong here.
Thanks in Advance.
-Arindam.
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
private List<Boolean> textViewVisibileState;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
this.textViewVisibileState=new ArrayList<>(Arrays.asList(new Boolean[getCount()]));
Collections.fill(this.textViewVisibileState,false);
}
#Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return mListQuestion.size();
}
#Override
#SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
if(textViewVisibileState.get(position))
{
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
}
else
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
}
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (textViewVisibileState.get(position))
{
textViewVisibileState.set(position,false);
}
else
{
textViewVisibileState.set(position,true);
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
This will work.
The variable flag is not context sensitive to object holder. So flag is always = false in your case. How about setVisibility(View.GONE) initially? And then setVisibility(View.VISIBLE) ONLY when ivArrow is clicked upon.
Calling notifyDataSetChanged() causes ListView to rebuild everything. It will remove its child views, call getView() for all the items that are visible, and thus you will rebind all the data for those items.
But your data hasn't actually changed. You haven't modified anything in the questions list, so binding the data again is meaningless. Instead you have tried to change something in your ViewHolder object, but there's no guarantee that the convertView you get after a notifyDataSetChanged() is for the same position as before, so it's possible that some other item has been affected (or perhaps none at all?).
Try removing the call to notifyDataSetChanged() from the OnClickListener. A visibility change should cause a re-layout of the view hierarchy, but as long as you haven't told ListView that the data has changed, it should keep all its current children.
Create an instance of the adapter, e.g Adapter myAdapter = new Adapter, set it to a listview or recyclerview e.g listview.setAdapter(mydapter) and everytime you add new data to it call adapter.notifyDataSetChanged()

Android Listview with Image and Text

So I have a listview that has both text and images in it.
Everything about it works except when I am presented with the top row not having an image assigned to it.
rather than it using the placeholder image I have for rows that have no image assigned it takes the image of the current user.
The current user in this image is number 3, but his picture is also being shown for user 1.
here is my code for the CustomListAdapter, it grabs the PlayerItem which has players name and image url.
public class CustomListAdapter extends BaseAdapter {
private ArrayList<PlayerItem> listData;
private LayoutInflater layoutInflater;
public CustomListAdapter(Context context, ArrayList<PlayerItem> listData) {
this.listData = listData;
layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.rosterrow, null);
holder = new ViewHolder();
holder.playerNameView = (TextView) convertView.findViewById(R.id.title);
holder.imageView = (ImageView) convertView.findViewById(R.id.thumbImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
PlayerItem playerItem = (PlayerItem) listData.get(position);
holder.playerNameView.setText(playerItem.getplayerName());
if ((holder.imageView != null) && (playerItem.getUrl() != null)) {
Picasso.with(null).load(playerItem.getUrl()).into(holder.imageView);
}
return convertView;
}
static class ViewHolder {
TextView playerNameView;
ImageView imageView;
}
}
Fixed it by adding
else {
holder.imageView.setImageResource(R.drawable.list_placeholder);
}

Categories

Resources