Hiding items in listview properly
Asked Answered
O

3

9

I would like to show/hide items in my listview. Currently I am doing this by iterating through adapter's data. If item at certain index matches some condition, this line is called:

listView.getChildAt(index).setVisibility(View.GONE);

Item is not visible, but blank space remains (surprisingly View.GONE and View.INVISIBLE acts the same in this case). I would like to achieve the same effect as if item was deleted from adapter and notifyDataSetChanged() was called, but I don't want to modify underlying data, just hide the item.

Oily answered 18/7, 2013 at 10:29 Comment(2)
Filter the data first in adapter and never add it to the listview. It's so simple.Finbar
possible duplicate of Android: How to hide a ListView ItemConfuse
O
5

I have achieved this as Tonithy suggests here. Added an if clause at the begining of getView method in adapter, which checks if item matches condition to hide. If it does getView returns "null layout".

When I want to hide an item, I set a condition and call .invalidateViews() on my listview.

Oily answered 18/7, 2013 at 11:49 Comment(1)
The worst practice I have ever seen.Fridlund
F
1

Do not return different views based on internal property without letting listview know about it, you should reuse views! Otherwise you make very slow apps. For example, take look at this tutorial with benchmark.

  • getView(...) - reuse convertView!, hide it conditionaly!
  • use Holder classes, make them "listen" to your adapter signals/evens and change their visual conditionally

Alternative: You can use multiple types of list items within single list:

  • define list item types (shown, hidden), override getViewTypeCount(): return 2
  • override getItemViewType(...),
    • is shown -> 0
    • is not shown -> 1
  • more complex getView(...)
    • get item view type or check if it's shown
    • dispatch view creation based on type, don't forget, that convertView argument is view for current item type, you should reuse it, if not null!
  • on change call notifyDataSetChanged()

I have tested approached like this for different stable types, but it should work even when type for item changes and you let observer know about it. This approach will be a lot of faster than one you have posted, because, you reuse views, don't need to always inflate new one!

Fridlund answered 17/4, 2015 at 8:41 Comment(0)
I
-1

Call .setVisibility(View.GONE) in override getView method of your CustomeListAdapter for all UI elements of your custom_list_item.

For Example:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    Holder holder = new Holder();
    View rowView;

    rowView = inflater.inflate(R.layout.custom_list_item, null);

    holder.tvName = (TextView) rowView.findViewById(R.id.textViewName);
    holder.img = (ImageView) rowView.findViewById(R.id.imageView1);

    if (items[position].NeedForCollapsed){
        System.out.println("set Visibility.Gone");
        holder.tvName.setVisibility(View.GONE);
        holder.img.setVisibility(View.GONE);

        return rowView;
    }

    //new values
    holder.tvName.setText(items[position].name);
    holder.img.setImageResource(GetImageID(items[position]));

    return rowView;
}

public class Holder
{
    TextView tvName;
    ImageView img;
}

Or call .setVisibility(View.GONE) for your root container like a LinearLayout. good luck!

Interloper answered 18/1, 2016 at 18:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.