Search code examples
androidandroid-constraintlayout

ConstraintLayout Placeholder is not laying out as expected


As I try to write the layout according to the article ConstraintLayout Placeholder preview the page on the screen is not shown as I expect. What I only changed was to replace the ImageButton with Button. As you can see, Button A's text is not laying out as center_vertical as I expected which I define in the styles.xml.

Is there anyone who can explain the reason, and tell me how to fix it?

thank you.

Here is my layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.PlaceHolderExampleActivity">

    <ImageView
        android:id="@+id/top_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/ic_launcher_background"
        android:src="@drawable/ic_launcher_foreground"
        tools:ignore="MissingConstraints" />

    <androidx.constraintlayout.widget.Placeholder
        android:id="@+id/template_main_image"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="50dp"
        app:content="@+id/top_image"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Placeholder
        android:id="@+id/template_action"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginEnd="24dp"
        android:background="#3F51B5"
        app:content="@+id/A"
        app:layout_constraintBottom_toBottomOf="@+id/template_main_image"
        app:layout_constraintEnd_toEndOf="@+id/template_main_image"
        app:layout_constraintTop_toBottomOf="@+id/template_main_image" />

    <Button
        android:id="@+id/A"
        style="@style/text_style"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginBottom="16dp"
        android:text="A"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/B"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toStartOf="parent" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

Here is style.xml

 <style name="text_style">
        <item name="android:background">#E91E63</item>
        <item name="android:textColor">@color/white</item>
        <item name="android:textSize">16sp</item>
        <item name="android:gravity">center</item>
    </style>

Here is the preview image: enter image description here


Solution

  • I would not expect what you are seeing. It appears that the gravity of the button is being ignored when it is part of the Placeholder. (Gravity is something of an odd beast anyway.) This looks like a bug to me. If you are so inclined, you might want to consider reporting it in the issue tracker. (That is, if you agree.)

    In the meantime, here is a workaround that is not too involved. Wrap you button in a FrameLayout something like the following. You will need to reference the FrameLayout in the Placeholder instead of the button.

    <FrameLayout
        android:id="@+id/frameForA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    
        <Button
            android:id="@+id/A"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:gravity="center"
            android:text="A"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </FrameLayout>
    

    The FrameLayout is pretty lightweight. The layout looks like this on an emulator with this change made:

    enter image description here

    I simplified the button's definition for this answer. You can, of course, reintroduce your style and reinstate anything else I changed with respect to the button.