Giter Site home page Giter Site logo

androidx / constraintlayout Goto Github PK

View Code? Open in Web Editor NEW
1.1K 36.0 177.0 35.62 MB

ConstraintLayout is an Android layout component which allows you to position and size widgets in a flexible way

License: Apache License 2.0

Java 78.10% Shell 0.02% Kotlin 21.88%

constraintlayout's Introduction

ConstraintLayout 🗜️📏

Sample Code

core GitHub license

ConstraintLayout is a layout manager for Android which allows you to position and size widgets in a flexible way. It's available for both the Android view system and Jetpack Compose.

This repository contains the core Java engine, Android library, validation tools, and experiments.

Android Reference Docs

Reference Docs for Compose

Have a question that isn't answered here? Try StackOverflow for ConstraintLayout or MotionLayout.

Using ConstraintLayout

⬇️ Installation

Add the Gradle dependency:

You need to make sure you have the Google repository included in the build.gradle file in the root of your project:

repositories {
    google()
}

Next add a dependency in the build.gradle file of your Gradle module.

If using ConstraintLayout with the Android View system, add:

dependencies {

    implementation("androidx.constraintlayout:constraintlayout:2.1.4")

}

If using ConstraintLayout with Jetpack Compose, add:

dependencies {

    implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")

}

Additionally, for MotionLayout with Jetpack Compose, you require to opt-in to ExprimentalMotionApi:

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    kotlinOptions {
        // For Kotlin 1.6.0+
        freeCompilerArgs += "-opt-in=androidx.constraintlayout.compose.ExperimentalMotionApi"
        
        // For older than Kotlin 1.6.0
        freeCompilerArgs += "-Xopt-in=androidx.constraintlayout.compose.ExperimentalMotionApi"
    }
}

🎒🥾 Requirements

  • AndroidX (Your gradle.properties must include android.useAndroidX=true)
  • Min SDK 14+
  • Java 8+

✨🤩📱 Key Features

Hello World

<?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"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

📐 Aspect Ratio defines one dimension of a widget as a ratio of the other one. If both width and height are set to 0dp the system sets the largest dimensions that satisfy all constraints while maintaining the aspect ratio.

<ImageView
    android:id="@+id/image_1"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintDimensionRatio="1:1"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    tools:src="@tools:sample/avatars" />

⛓️ Chains provide group-like behavior in a single axis (horizontally or vertically). The other axis can be constrained independently.

🦮 Guidelines allow reactive layout behavior with fixed or percentage based positioning for multiple widgets.

<androidx.constraintlayout.widget.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/guideline"
    app:layout_constraintGuide_begin="100dp"
    android:orientation="vertical"/>

🚧 Barrier references multiple widgets to create a virtual guideline based on the most extreme widget on the specified side.

<androidx.constraintlayout.widget.Barrier
    android:id="@+id/barrier"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierDirection="start"
    app:constraint_referenced_ids="button1,button2" />

☂️ Group controls the visibility of a set of referenced widgets.

<androidx.constraintlayout.widget.Group
    android:id="@+id/group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="visible"
    app:constraint_referenced_ids="button4,button9" />

💫 MotionLayout a subclass of ConstraintLayout that supports transitions between constraint sets defined in MotionScenes. See projects/MotionLayoutExperiments for examples.

🌊 Flow is a VirtualLayout that allows positioning of referenced widgets horizontally or vertically similar to a Chain. If the referenced elements do not fit within the given bounds it has the ability to wrap them and create multiple chains. See projects/CalculatorExperiments for examples.

🌀 CircularFlow is a VirtualLayout that easily organize objects in a circular pattern. See projects/CarouselExperiments for basic examples and projects/MotionLayoutVerification for examples with MotionLayout.

<androidx.constraintlayout.helper.widget.CircularFlow
   android:id="@+id/circularFlow"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:circularflow_angles="0,40,80,120"
   app:circularflow_radiusInDP="90,100,110,120"
   app:circularflow_viewCenter="@+id/view1"
   app:constraint_referenced_ids="view2,view3,view4,view5" />

📚👩‍🏫 Learning Materials

🤝 Contributing

If you'd like to get involved and contribute please read CONTRIBUTING for details on our code of conduct, and the process for submitting pull requests to us.

💻 Authors

  • John Hoford : MotionLayout (jafu888)
  • Nicolas Roard : ConstraintLayout (camaelon)

See also the list of contributors who participated in this project.

🔖 License

This project is licensed under the Apache 2.0 License - see the LICENSE file for details

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

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.

[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!

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.

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?

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.

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

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"

[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" />

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.

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!

[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>

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.

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

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.

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.

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

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.

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

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.

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] 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>

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.

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.

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.

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>

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)

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)

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;
}

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) 

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

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?

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?

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" />

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?

[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!

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);
}

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?

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

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.

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.