user1788084
user1788084

Reputation:

Hiding items in listview properly

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.

Upvotes: 9

Views: 15514

Answers (3)

Buzzy
Buzzy

Reputation: 1924

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!

Upvotes: -1

kravemir
kravemir

Reputation: 11006

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!

Upvotes: 1

user1788084
user1788084

Reputation:

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.

Upvotes: 5

Related Questions