Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
340 views
in Technique[技术] by (71.8m points)

android - Using <include> with <merge> in ConstraintLayout

I am having trouble using tags <include> and <merge> inside a ConstraintLayout.

I want to create a flat view hierarchy (hence Constraints) but still have elements that are reusable. So I use <include> in my layout and <merge> in the included layouts to avoid having nested layouts (especially avoiding nested ConstraintLayouts)

So I wrote this: Parent layout

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/review_1"
        layout="@layout/view_movie_note"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/review_2"/>

    <include
        layout="@layout/view_movie_note"
        android:id="@+id/review_2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginLeft="7dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/review_1"
        app:layout_constraintRight_toRightOf="parent"
        />

</android.support.constraint.ConstraintLayout>

and this view_movie_note :

<merge>

    <TextView
        android:id="@+id/note_origin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="15dp"
        android:layout_marginStart="5dp"
        app:layout_constraintStart_toStartOf="@+id/cardView2"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="5dp" />


    <android.support.v7.widget.CardView
        android:id="@+id/five_star_view_container"
        android:layout_width="0dp"
        android:layout_height="52dp"
        android:layout_marginBottom="8dp"
        android:layout_marginTop="10dp"
        android:elevation="3dp"
        app:cardUseCompatPadding="true"
        app:contentPaddingTop="22dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_min="52dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/note_origin">

        <FiveStarsView
            android:id="@+id/five_star_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal" />

    </android.support.v7.widget.CardView>

    <android.support.v7.widget.CardView
        android:id="@+id/cardView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        app:cardBackgroundColor="@color/colorPrimary"
        app:contentPaddingLeft="15dp"
        app:contentPaddingRight="15dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/note_origin">

        <TextView
            android:id="@+id/grade"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12sp" />

    </android.support.v7.widget.CardView>


</merge>

I am expecting this

I am expecting this

Instead I got this

Instead I get this

Clearly the constraints that I put in the <include> tag are overriden by the constraints in the included layout.

Is this the expected behaviour ? If yes, how are we supposed to keep a flat layout using <include> and ConstraintLayout ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Short answer

The best move will be replacing <merge> block with a (nested) ConstraintLayout rather than using redundant layout structure.




ConstraintLayout is great but it doesn't work well with composition and separation of responsibilities of each piece

That is wrong. ConstraintLayout does work well with reusing layouts. Any layout in which all child views are laid out according to relationships between sibling views and the parent layout, behaves exactly like this. This is true even for RelativeLayout.


Then, where is the problem?

Let's take a closer look at what <merge> is.

The doc says

The <merge/> tag helps eliminate redundant view groups in your view hierarchy when including one layout within another.

It will have the same effect as replacing the <include> element with the contents of <merge> block. In other words, the views in the <merge/> block is directly placed to the parent layout without an intermediate view group. Therefore, the constraints of the <include> element is completely ignored.

In this particular example, the views in the including layout is added two times to the parent as the second one on top of another.


Conclusion

Layout resource files are intended to be used independently. To qualify the term reusable, it should not depend on it's parent (The view group in which it will be added in future). It would be looking okay if you had to include the layout only one time. But </merge> won't be a good idea in that case too because you can't place it in any different layout in a different position.

Obviously, flat layout hierarchies have better performance. However, sometimes we may have to sacrifice it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...