1

I have a multicolumn_listview. Some rows repeat in listview. i looked at all solution about this problem.

listview items image

  1. Listview height not wrap_content
  2. My holder class static
  3. I created all views in if(convertView==null) block in getview method.

but the problem hasn't solved yet.. please help me..

here is my adapter class;

public class ListViewAdapterCurrentList extends BaseAdapter
{
    public ArrayList<HashMap<String, String>> list;
    boolean isDetail = false;
    private String currentNo;
    private String currentCode;
    private String currentName;
    private String date;
    private String status;
    private Activity activity;
    private Boolean isPlan = true;

    public ListViewAdapterCurrentList(Activity activity, ArrayList<HashMap<String, String>> list, boolean isPlan) {
        super();
        this.activity = activity;
        this.list = list;
        this.isPlan = isPlan;
    }

    @Override
    public int getCount()
    {
        return list.size();
    }

    @Override
    public Object getItem(int position)
    {
        return list.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return 0;
    }

    static class ViewHolder
    {
        ImageView currentDetail;
        TextView currentNo;
        TextView currentCode;
        TextView currentName;
        TextView date;
        TextView durum;
        LinearLayout linearLayoutCurrentBase;
        LinearLayout linearLayoutCurrentDetail;
        TextView currentAddress;
        TextView currentPhone;
        TextView currentManager;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        final ViewHolder holder;
        LayoutInflater inflater = activity.getLayoutInflater();
        final HashMap<String, String> map = list.get(position);

        if (convertView==null)
        {
            Log.d("CL:getView()", "Fetching Row: " + position);
            convertView = inflater.inflate(R.layout.currentlistitems, parent, false);
            holder = new ViewHolder();
            holder.currentDetail = (ImageView) convertView.findViewById(R.id.imageViewCurrentListDetail);
            holder.currentNo = (TextView) convertView.findViewById(R.id.textViewCurrentListNo);
            holder.currentCode = (TextView) convertView.findViewById(R.id.textViewCurrentListCode);
            holder.currentName = (TextView) convertView.findViewById(R.id.textViewCurrentListName);
            holder.date = (TextView) convertView.findViewById(R.id.textViewCurrentListDate);
            holder.durum = (TextView) convertView.findViewById(R.id.textViewCurrentListStatus);
            holder.linearLayoutCurrentBase = (LinearLayout) convertView.findViewById(R.id.layoutBaseCurrentList);
            holder.linearLayoutCurrentDetail = (LinearLayout) convertView.findViewById(R.id.layoutDetailCurrentList);
            holder.currentAddress = (TextView) convertView.findViewById(R.id.textViewCurrentAddress);
            holder.currentPhone = (TextView) convertView.findViewById(R.id.textViewCurrentPhone);
            holder.currentManager = (TextView) convertView.findViewById(R.id.textViewCurrentManager);
            convertView.setTag(holder);
        } else
        {
            holder = (ViewHolder) convertView.getTag();
        }
        currentNo = map.get("CariNo");
        currentCode = map.get("CariKod");
        currentName = map.get("CariUnvan");
        date = map.get("Tarih");
        status = map.get("Durum");
        holder.currentDetail.setBackgroundResource(R.drawable.box_plus);
        holder.currentNo.setText(currentNo);
        holder.currentCode.setText(currentCode);
        holder.currentName.setText(currentName);
        holder.date.setText(date);
        holder.durum.setText(status);
        if (!isPlan)
        {
            holder.durum.setVisibility(View.GONE);
            holder.date.setVisibility(View.GONE);
            holder.currentName.setWidth(300);
        }
        initDetailInfo(holder.currentAddress, holder.currentPhone, holder.currentManager, currentNo);

        holder.currentDetail.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if (!isDetail)
                {
                    holder.linearLayoutCurrentDetail.setVisibility(View.VISIBLE);
                    holder.currentDetail.setBackgroundResource(R.drawable.box_delete_expand);
                    isDetail = true;
                } else
                {
                    holder.linearLayoutCurrentDetail.setVisibility(View.GONE);
                    holder.currentDetail.setBackgroundResource(R.drawable.box_plus);
                    isDetail = false;
                }
            }
        });

        return convertView;
    }
babeyh
  • 659
  • 2
  • 7
  • 19
  • what does your initDetailInfo() method do? – Philipp Jahoda Aug 12 '13 at 15:32
  • unrelated question : why do you use a baseadapter when you are re-writing half of arrayadapter methods? – njzk2 Aug 12 '13 at 15:42
  • I would tend to think that the final holder may be related, but not sure. also, why don't you use a onItemClickListener on the listview? – njzk2 Aug 12 '13 at 15:45
  • are you sure of the content of your arraylist ? – njzk2 Aug 12 '13 at 16:05
  • phil, initDetailinfo() for only bring some sql queries,so i don't need to write it in question... – babeyh Aug 13 '13 at 06:01
  • when i add the row that "holder.linear...Visibility()..." ,eclipse warn me to make holder to final... My arraylist content come from database, sql query works right, only listview show duplicate some rows. – babeyh Aug 13 '13 at 06:05

1 Answers1

0

Edited since it apparently wasn't clear:

if (convertView==null)
{
    Log.d("CL:getView()", "Fetching Row: " + position);
    convertView = inflater.inflate(R.layout.currentlistitems, parent, false);
    holder = new ViewHolder();
    holder.currentDetail = (ImageView) convertView.findViewById(R.id.imageViewCurrentListDetail);
    holder.currentNo = (TextView) convertView.findViewById(R.id.textViewCurrentListNo);
    holder.currentCode = (TextView) convertView.findViewById(R.id.textViewCurrentListCode);
    holder.currentName = (TextView) convertView.findViewById(R.id.textViewCurrentListName);
    holder.date = (TextView) convertView.findViewById(R.id.textViewCurrentListDate);
    holder.durum = (TextView) convertView.findViewById(R.id.textViewCurrentListStatus);
    holder.linearLayoutCurrentBase = (LinearLayout) convertView.findViewById(R.id.layoutBaseCurrentList);
    holder.linearLayoutCurrentDetail = (LinearLayout) convertView.findViewById(R.id.layoutDetailCurrentList);
    holder.currentAddress = (TextView) convertView.findViewById(R.id.textViewCurrentAddress);
    holder.currentPhone = (TextView) convertView.findViewById(R.id.textViewCurrentPhone);
    holder.currentManager = (TextView) convertView.findViewById(R.id.textViewCurrentManager);
    convertView.setTag(holder);
} else
{
    holder = (ViewHolder) convertView.getTag();
}

right under the above before any work is done to them like adding children to the LinearLayouts:

holder.linearLayoutCurrentBase.removeAllViews();
holder.linearLayoutCurrentDetail.removeAllViews();

My guess is since you aren't doing that with the Viewgroups it never replaces the children. Let me know if that helps.

EDIT:

I just edited the answer for hopefully the last time. I do apologize for using the wrong method for removing the children of the ViewGroups. Now it should make sense. Look at my comment to understand why it duplicates your Views.

Andy
  • 10,553
  • 21
  • 75
  • 125
  • i don't understand your answer – njzk2 Aug 12 '13 at 15:44
  • I don't understand what is the point of doing this. the whole idea of the view holder is simply to not have to search for the views all over again. – njzk2 Aug 12 '13 at 16:04
  • @njzk2 that was my mistake but the above code will work. Since the user is never nullifying whats inside the ViewGroups it remains there when the Views are recycled. Of course it only happens to the ViewGroups. Leaving it in the if statement was my mistake. If done right after it before any work with the views themselves it will ensure they are null for use. – Andy Aug 12 '13 at 16:08
  • I apologize babeyh for not being clear. The above code should solve your problem of duplicating those Views. – Andy Aug 12 '13 at 16:14
  • `it remains there` that's the whole point of the viewholder pattern (and don't see why it would happen only to the viewgroups.). The SO is not using those until the click, anyway. – njzk2 Aug 12 '13 at 16:15
  • no need to apologize, it is me who fails to comprehend what you are doing. – njzk2 Aug 12 '13 at 16:16
  • Haha. @njzk2 Its not an easy thing to understand quickly. Took me a long time to really understand how ListView works. As for what I am doing, ListView recycles Views. So when it checks if `convertView` is null, its really saying, "Ok, I won't inflate another view if it isn't necessary. Instead, I will recycle and use another View." Problem is that when it recycles it doesn't erase what you put in it before. Hence you have to proactively do this. I don't see the SO do this, hence it is his problem. – Andy Aug 12 '13 at 16:22
  • i don't see how setting to null effectively erases anything? – njzk2 Aug 12 '13 at 16:24
  • @njzk2 Damn. No wonder you were confused. I was doing it all wrong. I just realized lmao. Ok now it should make more sense. – Andy Aug 12 '13 at 16:28
  • @Andy sorry, but i don't understant what did you do above answer? Where can i add the codes that you write 'exactly'? – babeyh Aug 13 '13 at 06:13
  • @Andy : ok. and then do you add the views back ? – njzk2 Aug 13 '13 at 07:52
  • @babeyh take the short two line code block and put it right under where I say in the answer. As for you @njzk2, yes, you have to add it again. Think of it this way; when its first inflated its empty. babeyh keeps getting duplicates in some views because they aren't being emptied since the code assumes it "empty". In the `TextView` stuff it doesn't duplicate it because they are just overridden with the new Strings, but the layouts are a different story. – Andy Aug 13 '13 at 19:30
  • Last comment before I abandon this question: http://stackoverflow.com/questions/11945563/how-listviews-recycling-mechanism-works Thats a link to one of my older questions on ListView recycling mechanism. The reason I know this problem so well is because I spent a lot of time on it. Hopefully this will help clear things up. There is also a link to a great ListView video by google. – Andy Aug 13 '13 at 19:36
  • i put the code where exactly you said, and didn't work!! when i run the app, all rows came empty! – babeyh Aug 14 '13 at 05:59
  • Where is exactly where I said? It doesn't make any sense that ALL rows are empty if only the `LinearLayout` is emptied. Under your post, add an edit and show me how you did it. At minimum what I told you to do should only affect the LinearLayout and not all rows. and While your at it show us your `R.layout.currentlistitems` xml please. – Andy Aug 14 '13 at 13:59