27

A picture tells more than a lengthy speech : enter image description here

I want to align vertically the center of the red part with the middle of the black part. I have no constraint of container (RelativeLayout, FrameLayout, LinearLayout oO ).

I tried a View with height of 0dp aligned to the bottom of the black view and alignBaseline of red view to it, but it doesn't work...

Thanks for your help !

SamPutnam
  • 1,129
  • 7
  • 7
JosselinTD
  • 611
  • 1
  • 8
  • 17
  • 1
    Use FrameLayout as a parent and then set gravity to bottom. In the child set top margin to child height / 2 – vilpe89 Jul 29 '15 at 10:08

7 Answers7

49

This is also possible using the ConstraintLayout. Similar to how aligning the start/end of a view to the parent centers it within the parent, we can use that concept to center along the edge of a View.

The key to this layout is two constraints on our bottom view:

app:layout_constraintTop_toBottomOf="@id/top_view"
app:layout_constraintBottom_toBottomOf="@id/top_view"

By constraining both the top/bottom of the lower view to the bottom of the upper view, the layout will adjust to center it along that bottom. Here is the full code and screenshot of the blueprint:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/top_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/green"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/bottom_view"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:background="@color/red"
        app:layout_constraintBottom_toBottomOf="@id/top_view"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/top_view" />

</android.support.constraint.ConstraintLayout>

enter image description here

AdamMc331
  • 16,492
  • 10
  • 71
  • 133
28

Android now supports layout anchors with the CoordinatorLayout:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/black_view"
        android:layout_width="match_parent" android:layout_height="@dimen/black_height"/>

    <View android:id="@+id/red_view"
        android:layout_width="@dimen/red_width" android:layout_height="@dimen/red_height"
        app:layout_anchor="@id/black_view" app:layout_anchorGravity="bottom|center"/>

</android.support.design.widget.CoordinatorLayout>

If you change the size of the views in your Java code, the anchor will persist as well.

Bryan
  • 14,756
  • 10
  • 70
  • 125
  • 2
    This is really the best answer. CoordinatorLayout allows the exact placement of views that JosselinTD is trying to achieve. – Luke Jun 07 '16 at 18:20
  • Thanks a lot! `CoordinatorLayout` rocks! :) – Minas Mina Sep 16 '17 at 18:23
  • life saver. Thanks – RATHI Sep 18 '17 at 00:01
  • 2
    not working!! it aligns the red view to the bottom of the blackview, but it overlaps 100%, not just 50% as needed! – avlacatus Dec 14 '17 at 09:54
  • @avlacatus Strange; the use case described above is the default behavior of the `CoordinatorLayout` anchor. I suggest you post another question with your code to figure out what could be causing the issue. – Bryan Dec 14 '17 at 16:56
  • 1
    Meta question: Why has this great answer not bubbled to the top? I almost moved on before finding it. – Dan May 19 '18 at 20:36
  • @Dan It should be at the top if your sort order is set to [active](https://stackoverflow.com/questions/31697099/android-align-view-center-to-bottom-of-other-view?answertab=active#tab-top) or [votes](https://stackoverflow.com/questions/31697099/android-align-view-center-to-bottom-of-other-view?answertab=votes#tab-top) (and not oldest). Talking from experience; I've made this mistake more than once. – Bryan May 21 '18 at 12:58
3

Finally, I use a more programmatic way to solve this problem, because the size of Views are not fixed.

Here the solution :

The layout :

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

            <View
                android:id="@+id/black"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"/>

            <View
                android:id="@+id/red"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true">
        </RelativeLayout>

The code :

            red.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    red.getViewTreeObserver().removeOnGlobalLayoutListener(this);

                    LayoutParams params = new LayoutParams(
                            LayoutParams.MATCH_PARENT,      
                            LayoutParams.WRAP_CONTENT
                            );
                    params.setMargins(0, 0, 0, red.getHeight()/2);
                    black.setLayoutParams(params);
                }
            });

Thanks for your help ! It helps me found this !

JosselinTD
  • 611
  • 1
  • 8
  • 17
  • Amazing!! I have been struggling since months to center an image(marker) to the map, this solution helped me achieve it! – Ishaan Nov 07 '17 at 09:29
1
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="25dp"
    android:background="#EEFFFFFF"
    android:orientation="vertical">
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_alignParentBottom="true" />
Nivedh
  • 971
  • 1
  • 8
  • 19
0

try 2 views in a relative laytout. put 1 below other (using below property). also make them both layout_centerHorizontal=true.

u can make a negative padding to the bottom one to lift it over the upper one.

good luck :)

Wops
  • 983
  • 9
  • 23
0

Here I am using two different View as black and red.

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

    <View
        android:layout_width="match_parent"
        android:layout_height="300dp" 
        android:background="@android:color/black"
        android:id="@+id/blackContainer" />

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@android:color/holo_red_light"
        android:layout_below="@+id/blackContainer"
        android:layout_marginTop="-50dp"/>

</RelativeLayout>

The trick is I have put the red container below the black container and set its marginTop to negative half of its height. So the center of red container is at the bottom of black container.

Azim Ansari
  • 1,378
  • 11
  • 20
0

Try doing the opposite. Anchor the smaller view first and place the other view accordingly. Something like this:

<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<View
    android:layout_width="100dp"
    android:layout_height="200dp"
    android:layout_centerHorizontal="true"
    android:layout_alignBottom="@+id/anchor"
    android:background="@color/black" />

<View
    android:layout_width="80dp"
    android:layout_height="50dp"
    android:layout_centerInParent="true"
    android:background="@color/light_grey"/>

<View
    android:id="@+id/anchor"
    android:layout_centerInParent="true"
    android:layout_width="0dp"
    android:layout_height="0dp"/>

</RelativeLayout>
Andro
  • 952
  • 9
  • 19