88

I've a RelativeLayout thus:

<RelativeLayout>
<TextView1/>
<TextView2/> // <-- View.VISIBLE OR View.GONE
<TextView3/>
<TextView4/>
</RelativeLayout>

Each TextView is anchored below the previous TextView with android:layout_below.

The problem is that TextView2 may or may not be there (either View.VISIBLE or View.GONE); if it's View.VISIBLE, then all is fine, but if it's View.GONE, then TextView3 ends up being rendered on top of TextView1.

I've tried various ways to fix this, but each time am caught out by RelativeLayout's 'you cannot reference an id before it's defined' rule.

I'm hoping that I'm missing something obvious here.

Onik
  • 19,396
  • 14
  • 68
  • 91
James
  • 3,729
  • 3
  • 20
  • 16
  • `RelativeLayout` has an embedded mechanism for finding closest non-GONE anchor view. I've checked down to Gingerbread and it's present even there: https://github.com/aosp-mirror/platform_frameworks_base/blob/gingerbread-release/core/java/android/widget/RelativeLayout.java#L852 – Miha_x64 Jan 30 '19 at 15:02

9 Answers9

227

You can use this tag:

android:layout_alignWithParentIfMissing="true"

From the docs:

If set to true, the parent will be used as the anchor when the anchor cannot be be found for layout_toLeftOf, layout_toRightOf, etc.

Ben Clayton
  • 80,996
  • 26
  • 120
  • 129
ininprsr
  • 2,472
  • 2
  • 14
  • 9
  • 28
    This works only when alignment with parent is desired, but the question was about how to align with previous view, not the parent. – dimsuz Jun 01 '15 at 13:15
  • @dismuz, this will be very useful in managing dynamic layouts and avoids any surprises in unforeseen corner cases. – ininprsr Dec 07 '18 at 07:34
44

You can place textview 2 and 3 in the LinearLayout and keep the linear layout below textview 1.

Karan
  • 12,724
  • 6
  • 40
  • 33
  • 14
    Adding hierarchy to a layout file is always a bad idea especially if it is a RelativeLayout. The more you add the more Android will create Objects to represent your layout. You should use something like android:layout_alignWithParentIfMissing="true" instead. You might also consider using other layouts like TableLayout for example. – Francois Dermu Mar 02 '16 at 23:48
12

why not update the below attribute of TextView3 when you update the visibility of TextView2? (I assume you do this in code)

something like

TextView tv = (TextView) findViewById(R.id.textview3);
RelativeLayout.LayoutParams lp =
    (RelativeLayout.LayoutParams) tv.getLayoutParams();
lp.addRule(RelativeLayout.BELOW, R.id.textview1);
((TextView) view).setLayoutParams(lp);
slup
  • 5,484
  • 4
  • 19
  • 14
8

This answer does not solve your specific problem, but does solve a similar one, so hopefully this will help somebody.

I had a situation where my relative layout did not have the equivalent of your TextView1. So, in my situation, if TextView2 was GONE, then I wanted TextView3 to be aligned with the parent's top. I solved that by adding to TextView3 the attribute android:layout_alignWithParentIfMissing="true". See http://developer.android.com/resources/articles/layout-tricks-efficiency.html.

Unfortunately, I do not see a way to specify an alternate alignment anchor unless it is the parent.

Samuel Yang
  • 81
  • 1
  • 2
7

Forget about INVISIBLE or GONE, use this instead:

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();

params.height = 0;

params.setMargins(0,0,0,0);

view.setLayoutParams(params);
Flexo
  • 87,323
  • 22
  • 191
  • 272
user925799
  • 87
  • 1
  • 2
6

you can do this

<RelativeLayout>
<TextView1/>
<FrameLayout>
  <TextView2/>  // <-- View.VISIBLE OR View.GONE
</FrameLayout>
<TextView3/>
<TextView4/>
</RelativeLayout>

let TextView3 below this FrameLayout which has no background, so if TextView2 is Gone ,it doesn't occupy space.

Alittle927
  • 61
  • 1
  • 2
1

place all textViews under LinearLayout with vertical orientation.

<LinearLayout>
<TextView/>
<TextView/>
<TextView/>
<TextView/>
<TextView/>
<TextView/>
</LinearLayout>
Ashwini
  • 653
  • 6
  • 7
0

Use ConstraintLayout, it doesn't break if a referenced view becomes GONE, instead it works as if the size of the hidden view became zero.

https://developer.android.com/reference/androidx/constraintlayout/widget/ConstraintLayout#VisibilityBehavior

Dmitry K
  • 85
  • 1
  • 9
-3

A simple hack for this is to play with alpha 0/1. and also disable the onClickListener if there is any

Taldroid
  • 382
  • 1
  • 8