Android: How to hide a ListView Item

33,033

Solution 1

Ressurecting an old question, but I just had this issue where I wanted to hide list items temporarily based upon criteria outside of the list data. What I ended up doing was creating a "null item" layout in xml and returned that based upon my criteria instead of the convert view in getView()...

instead of returning the convertView, I returned my null_item...

return inflater.inflate(R.layout.null_item, null);

null_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

</LinearLayout>

Solution 2

if you want to hide the item like this:

convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,1));
convertView.setVisibility(View.GONE);

can't be AbsListView.LayoutParams(-1,0);

if convertview are reused you should add this below to set it height back:

if(convertView.getVisibility() == View.GONE) {
    convertView.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
    convertView.setVisibility(View.VISIBLE);
}

Solution 3

When it comes to ListView, to make it efficient, we use ViewHolder pattern. The way to use ViewHolder Pattern and R.layout.row_null of the following xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</LinearLayout>

is to use with getViewTypeCount() and getItemViewType(int position) as follow.

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int position) {
        return (hideStatusCheck(position)) ? 1 : 0;
    }

    @Override
    public View getView(int pos, View convertView, ViewGroup parent) {
        View rowView = convertView;

        if (hideStatusCheck(pos)) {
            if (rowView == null || rowView.getTag() != null) {
                LayoutInflater inflater = mActivity.getLayoutInflater();
                rowView = inflater.inflate(R.layout.row_null, parent, false);
            }
        } else {
            if (rowView == null) {
                rowView = inflateNormalView(parent);
            } else if (rowView.getTag() == null) {
                rowView = inflateNormalView(parent);
            } else {
                ViewHolder holderToCheck = (ViewHolder) rowView.getTag();
                Integer storedPos = (Integer) holderToCheck.getTag(POSITION);
                if (storedPos == null || storedPos != pos)
                    rowView = inflateNormalView(parent);
            }
            ViewHolder holder = (ViewHolder) rowView.getTag();
            holder.setTag(POSITION,pos);
                        /*
                        Populate data
                        */
            return rowView;
    }

    private View inflateNormalView(ViewGroup parent) {
                    View rowView;
        LayoutInflater inflater = mActivity.getLayoutInflater();
        rowView = inflater.inflate(R.layout.normal_item, parent, false);
        ViewHolder viewHolder = new ViewHolder();
        assert rowView != null;
                    /* Initiate normal findViewById thing*/
        rowView.setTag(viewHolder);
        return rowView;
    }

We do the checking of the item's View type and if it meets the hide check, it will return 1, otherwise 0. The ListView knows that there will be 2 types of View from getViewTypeCount. Now, the getView will return the approriate View depending on the hideStatusCheck. To make a robust ListView, we want to use the ViewHolder pattern. We don't need to use ViewHolder when it is hidden. We simply inflate the R.layout.row_null and return it. We will use the ViewHolder for the R.layout.normal_item. Here is the tricky part assuming the hiding check is not static. The first check of rowView==null is standard. The second check of rowView.getTag()==null is to see if the View is coming back to normal from hiding. The third check in the last else clause is to check if the ViewHolder retained in the tag is the right ViewHolder. If these conditions are met, we always inflate the view again. Yes, it is true that, the ViewHolder pattern is not used throughout but it uses to certain extends. It is better than nothing.

Solution 4

I have look at source code. And there is only one way to hide item without notifyDataSetChanged(). You must set visibility GONE for all inner views and remove background image and paddings for item's view.

Note: Row with such invisible element will be selectable.

P.S: This is very usefull for ExpandableListView if you want to hide group view it self.

Solution 5

I did some tinkering with a drag and drop list from here. When an item is popped out of the list to be moved around the cell space it occupied has it's height set to 1px (see line 238) so it appears "gone". I couldn't find a way to handle this better as setting height to 0 fails as does visibility GONE.

That said, If you really want to get rid of a row less temporarily, it might be a good idea to change the backing of the Adapter and call notifyDataSetChanged() on it.

Share:
33,033

Related videos on Youtube

Tawani
Author by

Tawani

Updated on July 09, 2022

Comments

  • Tawani
    Tawani almost 2 years

    How can you hide an item in a ListView or at least set its height to zero?

    I have tried setting the visibility of the View to GONE but it still maintains the item's space (height).

  • Ahmed Sabry
    Ahmed Sabry over 9 years
    This is the correct answer I was going to write it :)
  • mdelolmo
    mdelolmo over 9 years
    Why not to just return a new View object? This way you would not add the overhead of inflating view.
  • Sufian
    Sufian over 9 years
    @tawani didn't this proposed solution worked for you? Please mark this as answer.
  • Tony Chan
    Tony Chan over 9 years
    @mdelolmo's method works. I just tested it and it saves you the need for extra xml files and inflation. You don't even need to set layout parameters, just return new View(context);
  • Tony Chan
    Tony Chan over 9 years
    Also don't forget to check the convertView for the type of View it is if you are recycling them. If items can change back and forth from hidden states you'll have to create a new layout for the item when the item becomes visible again. Otherwise you might end up trying to use an empty View object as your standard item layout, which could lead to crashes.
  • Tonithy
    Tonithy over 8 years
    @mdelolmo Didn't think of that. If it works fine, edit the answer to include that as an option.