setVisibility(GONE) view becomes invisible but still occupies space

41,933

Solution 1

This is an Android bug in my opinion, we just fix this issue doing this:

<FrameLayout android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout android:id="@+id/layout_to_hide"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content">
         //Put here your views
    </LinearLayout>
</FrameLayout>

Just hide LinearLayout with id LAYOUT_TO_HIDE with Visible.GONE and then root FrameLayout will collapse its height giving you a "hidden" with non-blank-space header.

Solution 2

set layout_width and layout_height to 0 where you want to hide item, by doing this

//if item's parent layout is LinearLayout, change according to your item xml
holder.itemView.setLayoutParams(new LinearLayout.LayoutParams(0,0));

Solution 3

All replies in this thread are suggesting a new wrapper view, which comes at a cost. The correct way of hiding a view completely is to set margins to 0 while setting visibility to GONE. In this code sample, cardView is the view I am trying to hide. The direct parent of cardView is RecyclerView, that's why we are using RecyclerView.LayoutParams - remember to replace with the right layout params.

if (cardView.getVisibility() != GONE) {
    cardView.setVisibility(GONE);
    RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) cardView.getLayoutParams();
    layoutParams.setMargins(0, 0, 0, 0);
    cardView.setLayoutParams(layoutParams);
}

Solution 4

If this is stil needed, there is a great way to deal with it:

parentView.removeView(childView);

here an example:

final WhatEverLayout parentView, childView;
parentView = (WhatEverLayout)findViewById(R.id.parentView_xml);
childView =(WhatEverLayout)findViewById(R.id.childView_xml);
parentView.removeView(childView);

Solution 5

This is my solution. Create a new layout file with name "special.xml", copy the code to the file.

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

</LinearLayout>

Use condition to inflate the empty layout inside the newview. Don't Use the view.setVisibility(View.GONE);.

if(true){
  view=mInflater.inflate ( R.layout.special,parent, false );
}else{
  view=mInflater.inflate(R.layout.normal,parent,false);
  // The view that you want to be visible
}
Share:
41,933
Denys
Author by

Denys

I do Data Engineering in Berlin (and worldwide).

Updated on November 06, 2021

Comments

  • Denys
    Denys over 2 years

    I've got a view that is effectively is a button. Here is its XML layout (add_new.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="match_parent"
        android:orientation="horizontal">
        <Button
            android:id="@+id/buttonNew"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/bText" 
            android:onClick="addNew"/>
    </LinearLayout>
    

    When I set its visibility to GONE like this

    v = getActivity().getLayoutInflater().inflate(R.layout.add_new, null);
    v.setVisibility(View.GONE);
    

    it disappears but still occupies space. Like this: enter image description here

    This button is a header in the ListView, which is defined by this xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/porno" >
    
        <ImageView
            android:id="@+id/icon"
            android:layout_width="30dp"
            android:layout_height="40dp"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="4dp"
            android:src="@drawable/ic_launcher">
        </ImageView>
    
        <TextView
            android:id="@+id/label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@+id/label"
            android:textSize="20dp" >
        </TextView>
    
    </LinearLayout> 
    

    And I dont want it to occupy an additional list item when its visibility is set to GONE. As it is stated in the documentation.

    GONE - This view is invisible, and it doesn't take any space for layout purposes.

    Any ideas on how to make it NOT occupy space?

    Thanks, Dennis xx

    P.S. My listview is inside of a FoldersFragment ListFragmentand here is the xml of my MainActivity where FoldersFragment is presented

    <?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="match_parent"
        android:orientation="horizontal" >
    
        <fragment
            android:id="@+id/foldersFragment"
            android:layout_width="200dip"
            android:layout_height="match_parent"
            class="com.example.fragments.FoldersFragment" >
        </fragment>
    
        <fragment
            android:id="@+id/detailFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            class="com.example.fragments.DetailFragment" >
        </fragment>
    
    </LinearLayout>
    
  • Szymon
    Szymon over 10 years
    Please provide some example.
  • Jayo2k
    Jayo2k over 10 years
    Let take my example for instance. I had to show a seek bar if the item was an audio file, if not, then no seekbar. So I set the seekbar in the xml as wrap content (height and width) meaning the layout will occupy the space of the showed element. And when the seekbar is "GONE", the space is not used since the view wrap a content that is not there. If I could I would have showed a screen capture but the trick is pretty simple.
  • Online98
    Online98 about 9 years
    Hi there. Do you still have not found a better solution? Is this a bug really? I'm having the same problem
  • Swift
    Swift almost 9 years
  • Ealhad
    Ealhad over 8 years
    OP actually wants the empty space to disappear, but GONE doesn't seem to work.
  • Roberto
    Roberto over 7 years
    display is not an android attribute
  • Miha_x64
    Miha_x64 over 5 years
    This is irrelevant for ListView.
  • Miha_x64
    Miha_x64 over 5 years
    All addView and removeView methods throw UnsupportedOperationException in AdapterView.
  • dev
    dev over 5 years
    @Miha_x64 Can you please explain why? ListView should behave the same as any other view.
  • Miha_x64
    Miha_x64 over 5 years
    The author of the question already tried GONE and then created this question. Another answer says that GONE doesn't work correctly inside ListView: stackoverflow.com/a/20786397/3050249
  • dev
    dev over 5 years
    My answer clearly states the additional step required since GONE is not enough. Your comment ignores the main part of my answer and the drawback associated with your linked answer.
  • Miha_x64
    Miha_x64 over 5 years
    Margins are not specified explicitly in the question. This means that they are (0, 0, 0, 0).
  • dev
    dev over 5 years
    If you have tried this solution and it did not work, let me know here. If you want to know why setting margins to 0 works, I don't know - perhaps it is/was a platform bug when the answer was written.
  • hasanghaforian
    hasanghaforian about 5 years
    I prefer this way because it does not need to change the layout
  • user1491604
    user1491604 over 3 years
    Well... I was just using "display" as an example here and v.setVisibility(View.GONE) worked in my case - the same did disappear.
  • DIRTY DAVE
    DIRTY DAVE over 2 years
    how is this still a problem in 2021
  • Karan_Rana
    Karan_Rana over 2 years
    I am also facing this issue in 2021.. any update on this?
  • Admin
    Admin almost 2 years
    worked for me, tks