setVisibility(GONE) view becomes invisible but still occupies space
AndroidAndroid ListviewAndroid ViewAndroid 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:
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 ListFragment
and 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
.