setVisibility(GONE) view becomes invisible but still occupies space

AndroidAndroid ListviewAndroid View

Android Problem Overview


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>

Android Solutions


Solution 1 - Android

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 - Android

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 - Android

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 - Android

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 - Android

What you can do is set an if statement, whenever the condition to set the visibility to "GONE", set the view as wrap content and your space will be free, I did it and it worked for a seekbar

Solution 6 - Android

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
}

Solution 7 - Android

header_layout.xml:

<?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">
        <LinearLayout
            android:id="@+id/mHeaderView"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:id="@+id/mNoHelpLayout"
                android:layout_width="match_parent"
                android:layout_height="176dip"
                android:background="#ffffffff"
                android:gravity="center"
             />
       </LinearLayout>
   </LinearLayout>

java code:

LayoutInflater mInflater =(LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View outerView =  mInflater.inflate(R.layout.header_layout, null);
mHeaderView = (LinearLayout) outerView.findViewById(R.id.mHeaderView);

use mHeaderView.setVisiable() to control visiable not the outerView.setVisiable(). it works for me.

Solution 8 - Android

If you want to show itemView 

if (ItemBean.isShow()) 
{
   holder.itemView.setVisibility(View.VISIBLE);
   holder.itemView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
 } else
 {
     holder.itemView.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
     holder.itemView.setVisibility(View.GONE);
 }

Solution 9 - Android

I had similar issue when using TransitionManager.beginDelayedTransition(), in the Layout Inspector tool I see that the view is Gone, but it still taking space, I think it is bug in Android, a workaround is to execute the visibility block with View.post(Runnable action)

Solution 10 - Android

For me, it worked if I did the showing/hiding on the next run loop.

parentView.post { 
   childViewToHide.visibility = View.GONE
}

Solution 11 - Android

Simplest way is to force the parent view to remeasure its own height after children visibility changed.
Try something like this :

parentView.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));

in this case parent view is a LinearLayout.

Solution 12 - Android

You can use : viewToHide?.postDelayed({ viewToHide?.visibility = View.GONE }, durationInMillis)

Solution 13 - Android

> A generic and easy solution is to avoid all thuse heck of code:

You need to add a Container Layout or a Parent Layout over your set of views that you want to hide. It can be anything like CardView or FrameLayout or etc.

Just it has to be a parent for that view that you want to hide. And you wont get all those white spaces. Coz it will consider the entire container to hide instead of considering individual views to HIDE thus, avoiding the white spaces.

Solution 14 - Android

Setting view padding and margins to 0 and then set view visibility to gone solved my problem.

Solution 15 - Android

In my case I was using an animation and in my anim, I had the flag

android:fillAfter="true"

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <translate
        android:duration="300"
        android:fromYDelta="100%"
        android:toYDelta="0%" />

    
    <alpha
        android:duration="150"
        android:fromAlpha="0"
        android:toAlpha="1" />
</set>

This caused the view to be set as invisible even when it was being set to GONE.

After removing android:fillAfter="true" I had no more issues and the view was then properly being set to GONE.

Solution 16 - Android

I don't think this is a bug.. Just use GONE to make the empty space disappear. CSS does the same thing. Try display: block vs visibility: hidden.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDenysView Question on Stackoverflow
Solution 1 - AndroidnoniView Answer on Stackoverflow
Solution 2 - AndroidAsadView Answer on Stackoverflow
Solution 3 - AndroiddevView Answer on Stackoverflow
Solution 4 - AndroidJayo2kView Answer on Stackoverflow
Solution 5 - AndroidJayo2kView Answer on Stackoverflow
Solution 6 - AndroidkyorilysView Answer on Stackoverflow
Solution 7 - AndroidwanglugaoView Answer on Stackoverflow
Solution 8 - Androidmurugan maniView Answer on Stackoverflow
Solution 9 - AndroidPavel PoleyView Answer on Stackoverflow
Solution 10 - AndroidWesty92View Answer on Stackoverflow
Solution 11 - AndroiducMediaView Answer on Stackoverflow
Solution 12 - AndroidMudit KhandelwalView Answer on Stackoverflow
Solution 13 - AndroidPrajwal WaingankarView Answer on Stackoverflow
Solution 14 - AndroidHosseinView Answer on Stackoverflow
Solution 15 - AndroidDIRTY DAVEView Answer on Stackoverflow
Solution 16 - Androiduser1491604View Answer on Stackoverflow