Git Product home page Git Product logo

constraintlayout's Introduction

Android Jetpack

Revved up by Develocity

Jetpack is a suite of libraries, tools, and guidance to help developers write high-quality apps easier. These components help you follow best practices, free you from writing boilerplate code, and simplify complex tasks, so you can focus on the code you care about.

Jetpack comprises the androidx.* package libraries, unbundled from the platform APIs. This means that it offers backward compatibility and is updated more frequently than the Android platform, making sure you always have access to the latest and greatest versions of the Jetpack components.

Our official AARs and JARs binaries are distributed through Google Maven.

You can learn more about using it from Android Jetpack landing page.

Contribution Guide

For contributions via GitHub, see the GitHub Contribution Guide.

Note: The contributions workflow via GitHub is currently experimental - only contributions to the following projects are being accepted at this time:

Code Review Etiquette

When contributing to Jetpack, follow the code review etiquette.

Accepted Types of Contributions

  • Bug fixes - needs a corresponding bug report in the Android Issue Tracker
  • Each bug fix is expected to come with tests
  • Fixing spelling errors
  • Updating documentation
  • Adding new tests to the area that is not currently covered by tests
  • New features to existing libraries if the feature request bug has been approved by an AndroidX team member.

We are not currently accepting new modules.

Checking Out the Code

Head over to the onboarding docs to learn more about getting set up and the development workflow!

Continuous integration

Our continuous integration system builds all in progress (and potentially unstable) libraries as new changes are merged. You can manually download these AARs and JARs for your experimentation.

Password and Contributor Agreement before making a change

Before uploading your first contribution, you will need setup a password and agree to the contribution agreement:

Generate a HTTPS password: https://android-review.googlesource.com/new-password

Agree to the Google Contributor Licenses Agreement: https://android-review.googlesource.com/settings/new-agreement

Getting reviewed

  • After you run repo upload, open r.android.com
  • Sign in into your account (or create one if you do not have one yet)
  • Add an appropriate reviewer (use git log to find who did most modifications on the file you are fixing or check the OWNERS file in the project's directory)

Handling binary dependencies

AndroidX uses git to store all the binary Gradle dependencies. They are stored in prebuilts/androidx/internal and prebuilts/androidx/external directories in your checkout. All the dependencies in these directories are also available from google(), or mavenCentral(). We store copies of these dependencies to have hermetic builds. You can pull in a new dependency using our importMaven tool.

constraintlayout's People

Contributors

aquagray avatar bastionkid avatar bentrengrove avatar camaelon avatar chao2zhang avatar dsteve595 avatar dtvc87 avatar gbenroscience avatar h6ah4i avatar hament9193 avatar himamis avatar hopewm avatar jafu888 avatar jineshfrancs avatar jswong65 avatar kaeawc avatar lrnrzg avatar melix avatar mihaipopa12 avatar mlykotom avatar onebone avatar oscar-ad avatar pfmaggi avatar pratikbutani avatar rodrigomartind avatar romanofranz avatar tikurahul avatar vanniktech avatar zacsweers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

constraintlayout's Issues

2.0.0-beta6 and higher - autoTransition="animateToStart" not work

when I click 'trigger' and MotionLayout finish start to end, expect it can back to start. unfortunately, animateToStar not working.

I find some differ in MotionLayout. there is the condition that this.mCurrentTransition == transition in MotionScene#autoTransition(...), can u explain what's the meaning of it?

[Bug] Flow error calculating next line after match_parent size

Hi folks!

First of all, thanks for your awesome contribution 🙌

I found what i think is an issue:
In Flow with wrapMode=chain if I set maxElementsWrap=2 and all elements have width=0 I see:

image

But, if I set the first element to match_parent to take all the line space, I see:

image

The second line should be shared with the third element and the last element should take the third entire line. Shouldn't it?

Flow looks like:

<androidx.constraintlayout.helper.widget.Flow
        android:id="@+id/flow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="itemStepsContainer, itemJourneysContainer, itemPromoAcceptanceContainer, itemPromoZonesContainer"
        app:flow_horizontalGap="@dimen/element_margin"
        app:flow_maxElementsWrap="2"
        app:flow_verticalGap="@dimen/element_margin"
        app:flow_wrapMode="chain"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/separator" />

MotionLayout performs unexpected transition when clicked inner RecyclerView

Hi. I found a bug in MotionLayout which causes an unexpected transition when clicking the scrollable content.

Setup

  • A RecyclerView placed in a MotionLayout
  • OnSwipe transition is configured to show/hide the RecyclerView
    (NestedScrollView also affects the bug, but more difficult to reproduce.)

Demo video

  • 🙆‍♂️ Expected behavior:
    • no transition occurs when clicking the RecyclerView area
  • 🙅‍♂️ What happens instead:
    • The RecyclerView closes without swipe down action
motionlayout.mp4

Repro code

https://github.com/h6ah4i/MotionLayoutWithRecyclerView

[Bug] Flow cannot layout the second line of items correctly

ConstraintLayout version: Both 2.0.4 & 2.1.0-alpha2 can reproduce this problem

See the screenshot, the bug is very obvious and straightforward:

Full repro-GIF:

The reproducible XML source:

<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:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:paddingStart="20dp"
  android:paddingTop="16dp"
  android:paddingEnd="16dp"
  android:paddingBottom="16dp">

  <ImageView
    android:id="@+id/icon"
    android:layout_width="24dp"
    android:layout_height="24dp"
    android:importantForAccessibility="no"
    android:scaleType="centerInside"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

  <TextView
    android:id="@+id/title"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="20dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@id/icon"
    app:layout_constraintTop_toTopOf="@id/icon" />

  <TextView
    android:id="@+id/summary"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="4dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="@id/title"
    app:layout_constraintTop_toBottomOf="@id/title" />

  <androidx.constraintlayout.helper.widget.Flow
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="4dp"
    app:constraint_referenced_ids="button1,button2,button3"
    app:flow_horizontalBias="0"
    app:flow_horizontalGap="4dp"
    app:flow_horizontalStyle="packed"
    app:flow_wrapMode="chain"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="@id/title"
    app:layout_constraintTop_toBottomOf="@id/summary" />

  <Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="123123123123123123"
    tools:ignore="MissingConstraints" />

  <Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="123123"
    tools:ignore="MissingConstraints" />

  <Button
    android:id="@+id/button3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="123"
    tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>

any plan about MotionLayout implements NestedScrollingChild3 ?

Some touch event has consumed by MothionLayout when it nested RecyclerView(some class implements NestedScrollingChild3), due to MotionLayout implements NestedScrollingParent3. when some class nested MothionLayout and need touch event, it's a problem.

Saving/Restoring Transition states

Hello,
I am using the latest stable version of the library (2.0.4) for implementing a complex layout similar to the player/"up next" animations in YouTube Music with a MotionLayout as a root. I've setup the scene files for different configurations with scene files with 4 transitions, everything works like a charm, but I cannot manage to have the MotionLayout keep the screen state after orientation changes. It either does not pick the correct transition, or goes into meaningless [state A]->[state A] transitions. I've tried using MotionLayout.getTransitionState/MotionLayout.setTransitionState() as it seemed to store all needed data (start,end, progress, animation direction and speed).

I've searched through the documentation, went through videos from conferences but cannot seem to find more information on how to save restore state on the layout?

Is the transitionState property meant for the purpose, or we should be doing something else, or let individual view states be handled by the system? I care about having the same screen state after an configuration change (provided the states exist in both before/after configurations).

Thank you.

How do I specify that the constraints in a certain direction are size provision or position constraints?

How do I specify that the constraints in a certain direction are size provision or position constraints, if there are constraints on the horizontal and vertical axes of a certain view?

For example, a view has two axis constraints, but one is a position constraint and the other is a size constraint, that is, the height or width of the view is provided by the size ratio.

At this time, how do I specify that the constraints in a certain direction are size supply or location constraints?

[Bug / Question] Duration of global transition

ConstraintLayout 2.0.4

I'm not sure whether I'm reporting a bug or it's desired behavior, but:

Preconditions:

  • I'm in the middle of whatever transition
  • I want to run "global" transition via transitionToState() (transition which doesn't have constraintSetStart set, but has only End)

The duration of the global transition is not applied and duration of currently running transition is applied instead.
I guess the reason for that is, that duration is first taken from scene and then transition is applied

See MotionLayout lines 2095-2097

method public void transitionToState(int id, int screenWidth, int screenHeight)
image

I guess the same would happen with regular transition - which has start+end constraints
I'm not sure whether there's some reason why it's this way or if it's a bug 🤷🏻‍♂️

Thanks!

WRAP_CONTENT behavior as minimum along a dimension

Unless I'm missing something, it's difficult or impossible to have a constraint layout child view match constraints but use its own content size as a minimum for a given dimension. I think this concept is missing in view groups in general, but it seems most applicable in constraint layout.

We appear to have the ability to request the opposite, that a view wrap content but also honor constraints if the constraints would prevent the view from increasing it's dimension to wrap the content (squeezing it if there isn't room) using layout_="wrap_content" coupled with layout_constrained="true|false", but the opposite could come in handy as well. Allow the view to expand to match its parent, but to request not to compress less than its measured content.

Different behaviour when I scroll RecyclerView inside MotionLayout

I am using a RecyclerView inside a ViewPager which is inside a MotionLayout ( fragment_detail ):

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

        <variable
            name="tmdbItem"
            type="com.sample.android.tmdb.domain.TmdbItem" />

        <variable
            name="vm"
            type="com.sample.android.tmdb.ui.detail.DetailViewModel" />
    </data>

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/details_motion"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene_show_details">

        <ImageView
            android:id="@+id/details_backdrop"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:imageUrl="@{@string/base_backdrop_path(tmdbItem.backdropPath)}"
            tools:ignore="ContentDescription" />

        <View
            android:id="@+id/details_backdrop_scrim"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@id/details_backdrop"
            app:layout_constraintEnd_toEndOf="@id/details_backdrop"
            app:layout_constraintStart_toStartOf="@id/details_backdrop"
            app:layout_constraintTop_toTopOf="@id/details_backdrop" />

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/details_poster"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/placeholder"
            android:scaleType="centerCrop"
            android:transformPivotX="0px"
            android:transformPivotY="0px"
            android:transitionName="@string/view_name_header_image"
            app:imageUrl="@{@string/base_poster_path(tmdbItem.posterPath)}" />

        <View
            android:id="@+id/details_gap_filler"
            android:layout_width="match_parent"
            android:layout_height="2px"
            android:background="@color/window_background"
            app:layout_constraintBottom_toTopOf="@id/details_rv"
            tools:ignore="PxUsage" />

        <com.sample.android.tmdb.widget.TopLeftCutoutBackgroundView
            android:id="@+id/details_appbar_background"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:backgroundColor="@color/window_background"
            app:topLeftCutSize="@dimen/details_corner_cutout" />

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/details_title"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:ellipsize="end"
            android:text="@{tmdbItem.name}"
            android:textAppearance="@style/TextAppearance.AppCompat.Title"
            android:transitionName="@string/view_name_header_title" />

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/details_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="?attr/actionBarSize"
            app:theme="@style/Toolbar" />

        <androidx.core.widget.NestedScrollView
            android:id="@+id/details_rv"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@color/window_background"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/details_appbar_background">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <TextView
                    style="@style/TmdbMargin.Small"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/padding_normal"
                    android:text="@{@string/release_date(tmdbItem.releaseDate)}"
                    app:toVisibility="@{!tmdbItem.releaseDate.empty &amp; tmdbItem.releaseDate!=null}" />

                <TextView
                    style="@style/TmdbMargin.Small"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{@string/rating(tmdbItem.voteAverage)}"
                    app:toVisibility="@{tmdbItem.voteAverage!=0.0}" />

                <TextView
                    android:id="@+id/summary_label"
                    style="@style/TmdbMargin.Title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/summary" />

                <TextView
                    android:id="@+id/summary"
                    style="@style/TmdbMargin.Body"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{tmdbItem.overview}" />

                <include
                    layout="@layout/trailers"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="@dimen/padding_normal"
                    android:layout_marginTop="@dimen/padding_large"
                    app:vm="@{vm}"
                    tools:ignore="RtlHardcoded" />

                <com.google.android.material.tabs.TabLayout
                    android:id="@+id/tab_layout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:tabSelectedTextColor="@color/colorAccent"
                    app:tabTextColor="@android:color/white" />

                <androidx.viewpager2.widget.ViewPager2
                    android:id="@+id/pager"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

            </LinearLayout>

        </androidx.core.widget.NestedScrollView>

        <View
            android:id="@+id/details_status_bar_anchor"
            android:layout_width="match_parent"
            android:layout_height="24dp"
            android:background="@color/status_bar_scrim_translucent_dark" />

    </androidx.constraintlayout.motion.widget.MotionLayout>

</layout>

And here is RecyclerView which I use in ViewPager2 ( fragment_credit ) :

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/credit_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="12dp"
    app:layoutManager="GridLayoutManager"
    app:spanCount="@integer/no_of_columns" />

Sometimes when I scroll in MotionLayout, it scroll in whole page.

But sometimes it scrolls just in RecyclerView under ViewPager and not whole page.

You can find the code at : https://github.com/Ali-Rezaei/TMDb-Paging

Upgrade 1.1.3 to 2.0.* fails. AAPT: error: duplicate value for resource

I am trying to upgrade from 1.1.3 to 2.0.* but keeps getting those errors. Have tried with multiple versions but only 1.1.3 seems to compile.
First/main error seems to be this:

AAPT: error: duplicate value for resource 'attr/defaultState' with config ''

It relates to this line in values.xml:
<declare-styleable name="StateSet"><attr format="reference" name="defaultState"/></declare-styleable>

> Task :app:mergeDevelopmentResources
AGPBI: {"kind":"error","text":"Android resource compilation failed","sources":[{"file":"C:\\Users\\xxx\\.gradle\\caches\\transforms-2\\files-2.1\\ac7a3722485ab8c9a6b5e513552ba699\\constraintlayout-2.0.4\\res\\values\\values.xml","position":{"startLine":340,"startColumn":4,"startOffset":35314,"endColumn":105,"endOffset":35415}}],"original":"C:\\Users\\xxx\\.gradle\\caches\\transforms-2\\files-2.1\\ac7a3722485ab8c9a6b5e513552ba699\\constraintlayout-2.0.4\\res\\values\\values.xml:341:5-106: AAPT: error: duplicate value for resource 'attr/defaultState' with config ''.\n    ","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource compilation failed","sources":[{"file":"C:\\Users\\xxx\\.gradle\\caches\\transforms-2\\files-2.1\\ac7a3722485ab8c9a6b5e513552ba699\\constraintlayout-2.0.4\\res\\values\\values.xml","position":{"startLine":340,"startColumn":4,"startOffset":35314,"endColumn":105,"endOffset":35415}}],"original":"C:\\Users\\xxx\\.gradle\\caches\\transforms-2\\files-2.1\\ac7a3722485ab8c9a6b5e513552ba699\\constraintlayout-2.0.4\\res\\values\\values.xml:341:5-106: AAPT: error: resource previously defined here.\n    ","tool":"AAPT"}
AGPBI: {"kind":"error","text":"Android resource compilation failed","sources":[{"file":"C:\\Code\\xxx\\app\\build\\intermediates\\incremental\\mergeDevelopmentResources\\merged.dir\\values\\values.xml"}],"original":"C:\\Code\\xxx\\app\\build\\intermediates\\incremental\\mergeDevelopmentResources\\merged.dir\\values\\values.xml: AAPT: error: file failed to compile.\n    ","tool":"AAPT"}

Any one that could see what could cause this issue?
It could seem to be some kind of denpendency versions conflict, but still can't get why this would end up in something like this.

Edit:
I found out that the material dependency is part of the problem:

implementation 'com.google.android.material:material:1.2.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

When ever I either upgrade that material to latest version or constraintlayout to 2.0.* it results in the above error, also if both are upgraded. Only with the versions above does it work. How could this be?

Current item of carousel

There is no way of getting current state of Carousel. It should contain getter of current state (which view is currently displayed/centered). Other option is to make a possibility to insert listener, what should be done, when view is displayed/centered.

When calling some of the Layer.setXXX() methods before setting some valid rotation via Layer.setRotation() causes the Layer's referenced Views to disappear

Layer.setScaleX(float scaleX), Layer.setScaleY(float scaleY), Layer.setTranslationX(float dx), Layer.setTranslationY(float dy)

All the above method calls don't work as expected when called before setting some valid rotation via Layer.setRotation() .

It seems the issue lies at the usage of default value of mGroupRotateAngle in Layer.transform() method which is NaN as seen in below attached images.
image

image

Having below check in Layer.transform() method should resolve the issue.

if (!Float.isNaN(this.mGroupRotateAngle)) {
    view.setRotation(this.mGroupRotateAngle);
}

layout_constraintWidth_max ignored when layout_constraintWidth_percent also specified

In constraintlayout version 1.1.3 the following layout specification used to work:

    android:layout_width="0dp"
    app:layout_constraintWidth_max="200dp"
    app:layout_constraintWidth_percent="0.5"

It set the width to 50% but it would max out at 200dp. Specifying layout_constraintWidth_max="wrap" was also possible, it resulted in 50% of the available width as long as it did not exceed the component's natural width.

As of constraintlayout version 2.0.0 layout_constraintWidth_max seems to be completely ignored and the component's width is set to 50% unconditionally. The same is probably true for the corresponding height attributes.

I believe the previous behavior was quite useful.

ConstraintSet.clone() does not keep the visibility of views in a Flow

<?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"
    android:id="@+id/clRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/txtGone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This should not be visible"
        android:visibility="gone" />

    <TextView
        android:id="@+id/txtVisible"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This should be visible" />

    <androidx.constraintlayout.helper.widget.Flow
        android:id="@+id/flow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:flow_horizontalGap="8dp"
        app:constraint_referenced_ids="txtGone,txtVisible"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_flow_visibility)

        val clRoot = findViewById<ConstraintLayout>(R.id.clRoot)
        val constraintSet = ConstraintSet()
        constraintSet.clone(clRoot)
        constraintSet.applyTo(clRoot)
    }
}

Executing the above code with 2.0.0-beta6 or higher will cause txtGone to become visible, even though its visibility is set to GONE. The visibility is correctly retained when it's not in the Flow.

Detect inconsistent constraints and cause error

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/test1"
        android:layout_width="100dp"
        android:layout_height="10dp"
        android:layout_marginBottom="32dp"
        android:background="#ff0000"
        app:layout_constraintBottom_toTopOf="@id/test2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/test2"
        android:layout_width="100dp"
        android:layout_height="10dp"
        android:layout_marginBottom="64dp"
        android:background="#00ff00"
        app:layout_constraintBottom_toTopOf="@+id/test3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/test1" />

    <View
        android:id="@+id/test3"
        android:layout_width="100dp"
        android:layout_height="10dp"
        android:background="#0000ff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/test2" />
</androidx.constraintlayout.widget.ConstraintLayout>

example

In this sample, android:layout_marginBottom is not working correctly. (margin is more than 32dp/64dp)
Can you detect a inconsistent constraint and cause error

Suggestion

  • Cause error when there are inconsistent constraints.
  • Show warnings that tell inconsistency of a layout.
  • Require chainStyle constraint when some elements are chained.

TextView does not resize during transition with MotionLayout

If a TextVIew is being resizing during a transition, and the layout_width or layout_height was set to wrap_content, then the widget is not resized well, most of the time the widget flick showing only a part of the component
Tested with constraintlayout v2.0.1

[Bug] Cannot nest Flows in version 2.0.4

ConstraintLayout version: Both 2.0.4 & 2.1.0-alpha2 can reproduce this problem.
I have views that nest Flow's, i.e. one Flow is referenced in constraint_referenced_ids of another Flow. This was possible in 2.0.1.

Expected (Actual for 2.0.1):

Actual (The red box can be seen a bit in the top):

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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/view1"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_blue_dark" />

    <View
        android:id="@+id/view2"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_red_dark" />

    <View
        android:id="@+id/view31"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_orange_light" />

    <View
        android:id="@+id/view32"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@android:color/holo_orange_dark" />

    <androidx.constraintlayout.helper.widget.Flow
        android:id="@+id/flow3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:constraint_referenced_ids="view31,view32"
        app:flow_maxElementsWrap="2" />

    <androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:constraint_referenced_ids="view1,view2,flow3"
        app:flow_maxElementsWrap="1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Crash when resizing Calculator experiment

Stack trace:

    Process: androidx.constraintlayout.experiments.calculator, PID: 25980
    java.lang.RuntimeException: Unable to start activity ComponentInfo{androidx.constraintlayout.experiments.calculator/android.support.constraint.calc.MainActivity}: java.lang.NumberFormatException: For input string: "Hi Jamila - the app just notified me that you're done"
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3431)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5451)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5357)
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7660)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.NumberFormatException: For input string: "Hi Jamila - the app just notified me that you're done"
        at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
        at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
        at java.lang.Double.parseDouble(Double.java:538)
        at java.lang.Double.valueOf(Double.java:502)
        at android.support.constraint.calc.CalcEngine.deserializeString(CalcEngine.java:186)
        at android.support.constraint.calc.CalcEngine.deserializeString(CalcEngine.java:178)
        at android.support.constraint.calc.MainActivity.regester_for_clipboard(MainActivity.java:310)
        at android.support.constraint.calc.MainActivity.onCreate(MainActivity.java:98)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595) 
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5451) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5357) 
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7660) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
2021-01-17 12:27:51.652 26271-26271/androidx.constraintlayout.experiments.calculator E/AndroidRuntime: FATAL EXCEPTION: main
    Process: androidx.constraintlayout.experiments.calculator, PID: 26271
    java.lang.RuntimeException: Unable to start activity ComponentInfo{androidx.constraintlayout.experiments.calculator/android.support.constraint.calc.MainActivity}: java.lang.NumberFormatException: For input string: "Hi Jamila - the app just notified me that you're done"
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3431)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5451)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5357)
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7660)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.NumberFormatException: For input string: "Hi Jamila - the app just notified me that you're done"
        at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
        at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
        at java.lang.Double.parseDouble(Double.java:538)
        at java.lang.Double.valueOf(Double.java:502)
        at android.support.constraint.calc.CalcEngine.deserializeString(CalcEngine.java:186)
        at android.support.constraint.calc.CalcEngine.deserializeString(CalcEngine.java:178)
        at android.support.constraint.calc.MainActivity.regester_for_clipboard(MainActivity.java:310)
        at android.support.constraint.calc.MainActivity.onCreate(MainActivity.java:98)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595) 
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5451) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5357) 
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7660) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

Redundant check?

Does these checks differs? seems like bug:

https://github.com/androidx/constraintlayout/blob/main/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/motion/widget/MotionScene.java#L287-L294

RectF region = transition.mTouchResponse.getTouchRegion(mMotionLayout, cache);
if (region != null && mLastTouchDown != null && (!region.contains(mLastTouchDown.getX(), mLastTouchDown.getY()))) {
    continue;
}
region = transition.mTouchResponse.getTouchRegion(mMotionLayout, cache);
if (region != null && mLastTouchDown != null && (!region.contains(mLastTouchDown.getX(), mLastTouchDown.getY()))) {
    continue;
}

Attribute "android:alpha" has already been defined

compile with 'androidx.constraintlayout:constraintlayout:2.0.4'

runs error:

Attribute "android:alpha" has already been defined
Attribute "android:translationX" has already been defined
Attribute "android:translationY" has already been defined
Attribute "android:translationZ" has already been defined

[Small Question] Does Flow support flex_start and flexWrap?

Can ConstraintLayout's Flow meet the following requirement?

Snip20210104_17

This can be achieved by the following config for Google's flexbox-layout:

<com.google.android.flexbox.FlexboxLayout
  app:alignContent="flex_start"
  app:alignItems="flex_start"
  app:flexWrap="wrap"> ...

image

Does ConstraintLayout's Flow also support or plan to support it?

Thanks!

show error when add android:fitsSystemWindows="true"

`<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:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
tools:ignore="MergeRootFrame">

<ImageView
    android:id="@+id/iv_activity_bg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:background="@android:color/holo_green_dark" />

<FrameLayout
    android:id="@+id/fl_temp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true"
    app:layout_constraintTop_toTopOf="parent">

    <include
        android:id="@+id/title_bar"
        layout="@layout/title_bar_style1" />
</FrameLayout>

<LinearLayout
    android:id="@+id/loading_empty_view"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/fl_temp">
` it work error ,loading_empty_view Not enough space has been reserved for fl_temp when add android:fitsSystemWindows="true"

When I rotate the device ViewPager items under MotionLayout does not scroll properly

I have following Layout includes MotionLayout :

<data>

    <variable
        name="tmdbItem"
        type="com.sample.android.tmdb.domain.TmdbItem" />

    <variable
        name="vm"
        type="com.sample.android.tmdb.ui.detail.DetailViewModel" />
</data>

<androidx.constraintlayout.motion.widget.MotionLayout
    android:id="@+id/details_motion"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_show_details">

    <ImageView
        android:id="@+id/details_backdrop"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        app:imageUrl="@{@string/base_backdrop_path(tmdbItem.backdropPath)}"
        tools:ignore="ContentDescription" />

    <View
        android:id="@+id/details_backdrop_scrim"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@id/details_backdrop"
        app:layout_constraintEnd_toEndOf="@id/details_backdrop"
        app:layout_constraintStart_toStartOf="@id/details_backdrop"
        app:layout_constraintTop_toTopOf="@id/details_backdrop" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/details_poster"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/placeholder"
        android:scaleType="centerCrop"
        android:transformPivotX="0px"
        android:transformPivotY="0px"
        android:transitionName="@string/view_name_header_image"
        app:imageUrl="@{@string/base_poster_path(tmdbItem.posterPath)}" />

    <View
        android:id="@+id/details_gap_filler"
        android:layout_width="match_parent"
        android:layout_height="2px"
        android:background="@color/window_background"
        app:layout_constraintBottom_toTopOf="@id/details_rv"
        tools:ignore="PxUsage" />

    <com.sample.android.tmdb.widget.TopLeftCutoutBackgroundView
        android:id="@+id/details_appbar_background"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:backgroundColor="@color/window_background"
        app:topLeftCutSize="@dimen/details_corner_cutout" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/details_title"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:ellipsize="end"
        android:text="@{tmdbItem.name}"
        android:textAppearance="@style/TextAppearance.AppCompat.Title"
        android:transitionName="@string/view_name_header_title" />

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/details_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?attr/actionBarSize"
        app:theme="@style/Toolbar" />

    <androidx.core.widget.NestedScrollView
        android:id="@+id/details_rv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/window_background"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/details_appbar_background">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                style="@style/TmdbMargin.Small"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/padding_normal"
                android:text="@{@string/release_date(tmdbItem.releaseDate)}"
                app:toVisibility="@{!tmdbItem.releaseDate.empty &amp; tmdbItem.releaseDate!=null}" />

            <TextView
                style="@style/TmdbMargin.Small"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{@string/rating(tmdbItem.voteAverage)}"
                app:toVisibility="@{tmdbItem.voteAverage!=0.0}" />

            <TextView
                android:id="@+id/summary_label"
                style="@style/TmdbMargin.Title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/summary" />

            <TextView
                android:id="@+id/summary"
                style="@style/TmdbMargin.Body"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{tmdbItem.overview}" />

            <include
                layout="@layout/trailers"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/padding_normal"
                android:layout_marginTop="@dimen/padding_large"
                app:vm="@{vm}"
                tools:ignore="RtlHardcoded" />

            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:tabSelectedTextColor="@color/colorAccent"
                app:tabTextColor="@android:color/white" />

            <androidx.viewpager2.widget.ViewPager2
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

        </LinearLayout>

    </androidx.core.widget.NestedScrollView>

    <View
        android:id="@+id/details_status_bar_anchor"
        android:layout_width="match_parent"
        android:layout_height="24dp"
        android:background="@color/status_bar_scrim_translucent_dark" />

</androidx.constraintlayout.motion.widget.MotionLayout>

When I rotate the device, ViewPager2 items does not scroll as expected. I tried to present the expected behaviour here : https://drive.google.com/file/d/16Gw9ld8XLr42IYPkx2fAWfttpQ16eiLM/view?usp=sharing

I expect that when I scroll the ViewPager items, it get scrolled in the whole page which most of the times does not happen when I rotate the device as shown in the recorded screen.

Programmatic view creation and VISIBILITY_MODE_IGNORE

I'm creating views programmatically in onCreate and add them to CostraintLayout, also i set ConstraintSet.VISIBILITY_MODE_IGNORE, cuz some of newly created views should be gone/invisible, but

constraintSet.applyTo(..)

applies in next frame, so visibility changes from onCreate has no effect and all views is VIEW.VISIBLE

Currently i'm using following dirty hack:

    private fun gone(view: View, constraintSet: ConstraintSet) {
        if (isFirstRender) {
            constraintSet.setVisibility(view.id, View.GONE)
        } else {
            view.visibility = View.GONE
        }
    }

Is it bug? Can i achieve more elegant solution?

Update to 2.0.4 from 2.0.0-alpha2 displays different behaviour for a TextView

Here you can find my layout : https://github.com/Ali-Rezaei/TMDb-Paging/blob/master/app/src/main/res/layout/fragment_detail.xml

There is a AppCompatTextView in the above layout :

<androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/details_title"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:ellipsize="end"
            android:text="@{tmdbItem.name}"
            android:textAppearance="@style/TextAppearance.AppCompat.Title"
            android:transitionName="@string/view_name_header_title" />

When I have 2.0.0-alpha2 textView animated from bottom to top in the detail screen as shown in this video : https://drive.google.com/file/d/13c1W83DRq-vO3Efi3TRVdb0nsWHO8NSw/view?usp=sharing

I updated to latest stable version (2.0.4) and you can see different behaviour for TextView : https://drive.google.com/file/d/13elngfi6Hh0cbhSiLARbAOlkAxxxLPa6/view?usp=sharing

Here you can find layoutDescription : https://github.com/Ali-Rezaei/TMDb-Paging/blob/master/app/src/main/res/xml/scene_show_details.xml

Here is the start :

<Constraint
            android:id="@id/details_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="24dp"
            app:layout_constraintBottom_toTopOf="@id/details_appbar_background"
            app:layout_constraintEnd_toEndOf="@id/details_appbar_background"
            app:layout_constraintStart_toEndOf="@id/details_poster"
            app:layout_constraintTop_toBottomOf="@id/details_appbar_background" />

Here is the end :

<ConstraintSet android:id="@+id/end">

<Constraint
            android:id="@id/details_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="48dp"
            android:layout_marginStart="64dp"
            android:elevation="@dimen/z_app_bar"
            app:layout_constraintBottom_toBottomOf="@id/details_appbar_background"
            app:layout_constraintEnd_toEndOf="@id/details_appbar_background"
            app:layout_constraintStart_toStartOf="@id/details_appbar_background"
            app:layout_constraintTop_toTopOf="@id/details_appbar_background" />

visibilityMode attr doesn't work for a view inside a Flow

I noticed this bug (or maybe intended behavior?) that appeared for the first time in 2.0.0-beta05. That's why the app I am working on is still stuck in 2.0.0:beta04

MotionLayout respects visibilityMode=ignore for a view that is not referenced in a Flow widget but it doesn't if this view is referenced within a Flow widget. Setting 'visibility'=gone to the view within the flow is ignored. I have attached a zip file with a sample project that reproduces this issue. Setting the ConstraintLayout to version 2.0.0:beta04 in app's build.gradle fixes the issue.

MotionLayoutFlowBug.zip

Bug ➤ Barrier

The barrier is not positioned correctly below the two specified components and breaks the view.

Expected v.1.1.3 Current v.2.0.4
drawing drawing

⚠️ I want to place the barrier below the subtitle and the blue image since the visibility of blue image can be GONE. I also want to center the blue image between the red image and the bottom edge of the parent.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="wrap_content"
    android:layout_margin="6dp"
    app:cardUseCompatPadding="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/clContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="My Title!"
            android:textColor="@android:color/black"
            android:textSize="18sp"
            app:layout_constraintEnd_toStartOf="@id/ivIcon"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/ivIcon"
            android:layout_width="50dp"
            android:layout_height="30dp"
            android:background="@android:color/holo_red_dark"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <View
            android:id="@+id/viewSeparator"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:layout_marginEnd="16dp"
            android:background="@android:color/black"
            app:layout_constraintEnd_toStartOf="@id/ivIcon"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tvTitle" />

        <TextView
            android:id="@+id/tvSubtitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="My Subtitle!!"
            app:layout_constraintEnd_toStartOf="@id/ivIcon"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/viewSeparator" />

        <ImageView
            android:id="@+id/ivOptions"
            android:layout_width="50dp"
            android:layout_height="20dp"
            android:background="@android:color/holo_blue_dark"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/ivIcon" />

        <!-- This one works but when I add other id (ivOptions) view it breaks -->
        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="tvSubtitle" />
        <!--
            app:constraint_referenced_ids="tvSubtitle, ivOptions" />-->

        <TextView
            android:id="@+id/tvFooter"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:background="@android:color/darker_gray"
            android:gravity="center"
            android:text="Footer"
            app:layout_constraintEnd_toStartOf="@id/ivIcon"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/barrier" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

Test suite and changelog

I am trying to find a problem with a layout that works on 2.0.1 but doesn't work anymore on 2.0.2, 2.0.3 and 2.0.4.

In order to zoom in on the problem, i was trying to find a change log, but couldn't find it.

Further, I was wondering if there is a test suite that is being executed before new versions are released, since i was wondering if a test case similar to my layout exists, that could point me in a direction how to fix the layout.

FeatureRequest: add percent size mode for ViratualLayouts

Currently size depends on real parent's size i.e. ConstraintLayout. Sometimes it's useful to calculate size depending on virtualLayout's size e.g. flow. Also would be nice to have some adjustments for including/ignoring flow's gaps during final size calculation.

FeatureRequest : Generalize goneMargin

When views orders are like these and all are optional.

View1
(10dp margin between 1-2)
View2
(20dp margin between 2-3)
View3

If I set view3's layout_marginTop=20dp and layout_goneMarginTop=10dp(if view2 is gone)
but then it can't handle the case that both view1 and view2 are gone.

To satisfy the design specification, I wish I can specify each margin and anchor combination.
for View3
layout_constraintTop_toBottomWithMargin="@id/view2 20dp" // if view2 is visible
layout_constraintGoneMarginTop1="@id/view1 10dp" // if view2 is gone
layout_constraintGoneMarginTop2="parent 0dp" // if view1&2 is gone

Specifying margin and anchor(=constraint) together makes sense because
in ConstraintLayout, marginTop is no use without constraintTop.

I added number suffix Top1, Top2, ... because xml doesn't allow dupicate attribute.
and I know specifying reference and dimension together is against the rule and require 'string' type.
I think there would be better format than this.

Feature request: duplicateParentState via ConstraintHelper

ConstraintLayout encourages "flatten style", so we missing duplicateParentState feature, cuz widgets are sliblings now.
Would be nice to have ConstraintHelper that will share state between referenced views (e.g. state of first view in list on the rest ones).
Seems like it isn't possible to implement this feature without changes to framework or without extending views, cuz there is no listeners for View#onCreateDrawableState nor Drawable#onStateChange.

MotionLayout - Jump to state

Am I missing something or is there no direct way to jump to specific state without animation that doesn't involve manipulating progress?

I tried using setState which seems to do nothing or transitionToState(state, duration) but neither of those seem to work properly for this case (0 duration is just a hint instead of skipping animation which is rather misleading in my opinion).

I find the process quite confusing for something that should be a basic operation especially when there are multiple transitions. I'm currently using a workaround by extending MotionLayout:

class MotionLayoutWithJump : MotionLayout {
    // (... constructors etc)

    private var pendingJump = -1

    fun jumpToState(state: Int) {
            if(!isAttachedToWindow) {
                pendingJump = state
                return
            }
            val target = when (state) {
                startState -> 0f
                endState -> 1.0f
                else -> {
                    // need to alter current transition to perform progress jump
                    val t = definedTransitions.find {
                        it.startConstraintSetId == state || it.endConstraintSetId == state
                    } ?: throw IllegalArgumentException("Provided state is not defined for any transition")
                    setTransition(t)
                    if (state == t.endConstraintSetId) 1.0f else 0f
                }
            }
            super.setProgress(target)
            updateState(state, getConstraintSet(state))
            pendingJump = -1
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if(pendingJump != -1){
            jumpToState(pendingJump)
        }
    }
}

It's not perfect of course because it will conflict with any animated transitions that are called while view is detached and I have not tested how it behaves with nested scrolling either.

So the request is self explanatory: can we get a native jump to state method that will skip all animations?

Switch delay change state when set checked in MotionLayout

  • ConstraintLayout version: 2.0.2
  • Device: Xiaomi Redmi Note 8 Pro
  • OS: Android 10

When I build animation by MotionLayout. I change switch's state by:

<Constraint
    android:id="@id/switchDemo">
    <CustomAttribute
        motion:attributeName="checked"
        motion:customBoolean="true" />
</Constraint>

I have tested both SwitchCompat and Switch. But the switch just change color to positive, the circle not move to right immediately. That circle only move to right when end of all animation.
Please check help me. Thank you so much!

Some of the Layer.setXXX() methods doesn't work when called before updatePostLayout() is executed

Layer.setScaleX(float scaleX), Layer.setScaleY(float scaleY), Layer.setTranslationX(float dx), Layer.setTranslationY(float dy)

All the above method calls don't work on Layer class when called before Layer.updatePostLayout() is called.

It seems like values being set using above mentioned methods are not handled in the Layer.updatePostLayout() . But mGroupRotateAngle field value is properly handled. Check the attached screenshot for reference where we can see that mGroupRotateAngle is handled in Line 170-172.

image

So my current workaround is to always call Layer.setRotation(0f) in case I'm sure that Layer.updatePostLayout() won't be called before I call above mentioned methods which are not handled.

Allow Flow to limit size of children with wrap_content

Version: 2.0.4

Children with wrap_content don't fit inside the Flow when Flow's size doesn't match with parent ConstraintLayout. The Flow itself has correct size and position. Looks like max size of the children is the same as parent ConstraintLayout, instead of the Flow. That kind of makes sense, but I'd expect that the Flow would take over being parent, when computing size of its children.

When I use android:layout_width="0dp" on the children, then they all get squeezed on the first line.

I can get the expected behavior by setting child.maxWidth = flow.width on children at runtime but it's pretty cumbersome to get right. Maybe a new xml attribute on the Flow would be nice, if this is not a bug.

Example:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.helper.widget.Flow
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="64dp"
        android:layout_marginEnd="32dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:flow_wrapMode="chain"
        app:flow_horizontalBias="1"
        app:constraint_referenced_ids="text1,text2,text3" />

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:text="Super loooooooooooooooooooooooooooooooooooooooooooooooooong text" />

    <TextView
        android:id="@+id/text2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:text="Short text" />

    <TextView
        android:id="@+id/text3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:text="Super loooooooooooooooooooooooooooooooooooooooooooooooooong text" />

</androidx.constraintlayout.widget.ConstraintLayout>

Screenshot 2021-01-13 at 14 02 04

Expected: (mocked with LinearLayout)

Screenshot 2021-01-13 at 14 03 27

(screenshots from AS but it's the same at runtime)

Included layout disappears since version 2.0.2

Description: Using included ConstraintLayout inside a ConstraintLayout causes views to dissapear under certain circumstances (see below for sample project).

This does not happen with version 2.0.1 and 2.1.0-alpha2. But with the stable releases 2.0.2 - 2.0.4.

I already created an initial issue ticket some month ago over here: https://issuetracker.google.com/issues/170293243

In the last days I found some time to set up a minimal project to reproduce this issue: https://github.com/G00fY2/ConstraintLayoutIssue/blob/master/README.md

androidx.constraintlayout.motion.widget.MotionScene.mCurrentTransition' on a null object reference

On version 2.0.1 working is good.

On 2.0.2 crash log:

2020-10-12 16:25:10.202 24740-24740/com.crone.skineditorforminecraftpe E/AndroidRuntime: FATAL EXCEPTION: main Process: com.crone.skineditorforminecraftpe, PID: 24740 java.lang.NullPointerException: Attempt to read from field 'androidx.constraintlayout.motion.widget.MotionScene$Transition androidx.constraintlayout.motion.widget.MotionScene.mCurrentTransition' on a null object reference at androidx.constraintlayout.motion.widget.MotionLayout.onAttachedToWindow(MotionLayout.java:3486) at android.view.View.dispatchAttachedToWindow(View.java:21304) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4239) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4246) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2571) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2225) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9126) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:999) at android.view.Choreographer.doCallbacks(Choreographer.java:797) at android.view.Choreographer.doFrame(Choreographer.java:732) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:984) at android.os.Handler.handleCallback(Handler.java:883) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loop(Looper.java:237) at android.app.ActivityThread.main(ActivityThread.java:8167) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

TextView didn't ellipsize with layout_constraintWidth_max and layout_constraintHeight_max

Hi
I need a TextView with max width and height. In case the text is to long I expect dotted at the end (ellipsize="end").
This didn't work.

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SecondFragment">

<TextView
        android:id="@+id/textview_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"

        android:text="Text sf asd fasd fas dfasd fasd fasd fas dfas dfas dfg sdfg sdfg  sdfgs fdg sdfa sdfas dfa sdfa sdfa fsaas dfas dfa sdfasd fa sdf asdf asdfasdf "

        android:maxWidth="100dp"
        android:maxHeight="100dp"
        app:layout_constraintWidth_max="100dp"
        app:layout_constraintHeight_max="100dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Removing maxWidth and maxHeight didn't help.

Bildschirmfoto 2021-02-09 um 08 37 10

Regards
Stephan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.