Android: How to hide a ListView Item
Asked Answered
S

8

22

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).

Sensuality answered 14/4, 2010 at 14:25 Comment(2)
Are you sure about your comment on View.GONE?Famish
See #5041999Delatorre
B
25

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>
Bertsche answered 29/5, 2013 at 2:17 Comment(5)
Why not to just return a new View object? This way you would not add the overhead of inflating view.Affect
@tawani didn't this proposed solution worked for you? Please mark this as answer.Junker
@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);Scaler
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.Scaler
@Affect Didn't think of that. If it works fine, edit the answer to include that as an option.Bertsche
T
12

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);
}
Tesler answered 6/1, 2015 at 2:52 Comment(0)
C
9

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.

Copyhold answered 24/1, 2014 at 1:54 Comment(0)
P
2

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.

Philhellene answered 14/4, 2010 at 16:50 Comment(0)
F
2

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.

Fluidextract answered 29/11, 2010 at 9:9 Comment(0)
A
0

add to your ListView object: android:dividerHeight="0px" android:divider="#FFFFFF"

Divider color doesn't matter only setting dividerHeight doesn't work

This does remove the divider though...

Ambala answered 24/7, 2010 at 14:35 Comment(0)
G
0

I think I have a much easier / safer solution: you just have to "embed" your item in a Layout, and change the visibility of this parent layout.

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

    <!-- Embed ListView Item into a "parent" Layout -->
    <LinearLayout
        android:id="@+id/parentLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <!-- This is the normal content of your ListView Item -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="World" />

    </LinearLayout>
</LinearLayout>

Then in your code just do:

public View getView(int position, View view, ViewGroup parent) {
    if (view == null) {
        LayoutInflater li = mActivity.getLayoutInflater();
        view = li.inflate(R.layout.my_listview_item, null);
    }
    LinearLayout parentLayout = (LinearLayout) view.findViewById(R.id.parentLayout);
    if (shouldDisplayItem(position)) {
        parentLayout.setVisibility(View.VISIBLE);
    } else {
        parentLayout.setVisibility(View.GONE);
    }
    return view;
}

This way you always use/reuse the same item, and just hide/show it.

Goolsby answered 13/5, 2014 at 13:59 Comment(1)
This is the correct answer I was going to write it :)Bloemfontein
C
0

To Hide whole raw from listview in android:-

RelativeLayout parentLayout = (RelativeLayout) view.findViewById(R.id.relative);
if (productPojoList.get(position).getSERSERVICETYPE().toString().equals("Group|Promotional")){
    view.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,1));
    view.setVisibility(View.GONE);
} else {
    if(view.getVisibility() == View.GONE) {
        view.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
        view.setVisibility(View.VISIBLE);
    }
}
Contented answered 26/11, 2019 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.