动画时 TextInputLayout 崩溃测量和焦点 (MotionLayout)

TextInputLayout crash measure and focus when animating (MotionLayout)

有MotionLayout,里面有很多ConstraintLayout,有的ConstraintLayout有TextInputLayout。

1-使用 android studio XML 设计预览时: 在启动器“ideal/landing”状态下没有错误,当我开始为 ConstraintLayout(开始显示视图)制作动画时,里面有 TextInputLayout,出现视图崩溃和渲染问题,并出现 onMeasure 错误(详细信息:java.lang.NullPointerException )

2-当我 运行 应用程序(真实设备)时: 动画工作正常,没有错误,但问题是:TextInputLayout 不(完全)关注 tap/click 并且键盘正常显示,当我尝试像垃圾邮件一样强制关注时 taps/clicks 没有任何反应,但是当我使用键盘写一些文本,文本出现在 TextInputLayout 中但根本没有焦点,之后如果我再次 tap/click(在写了一些文本之后),TextInputLayout 获得焦点。

片段XMl文件:

<androidx.constraintlayout.motion.widget.MotionLayout
    android:id="@+id/secondProfileLayout"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginTop="@dimen/my25dp"
    app:layoutDescription="@xml/fragment_dashboard_profile_scene"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_chainStyle="spread"
    app:layout_constraintTop_toBottomOf="@id/user_access">


    <androidx.constraintlayout.widget.ConstraintLayout
    >
      this ConstraintLayout 1
   
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
    >
     this ConstraintLayout 2

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout 
    >

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/my35dp"
            android:layout_marginTop="@dimen/my10dp"
            android:layout_marginEnd="@dimen/my35dp"
            android:hint="@string/worker_code"
            app:errorContentDescription="@string/wrong_code"
            app:errorEnabled="false"
            app:hintAnimationEnabled="true"
            app:hintEnabled="true"


           layout_constraint...
            >

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:imeOptions="actionDone"
                android:importantForAutofill="auto"
                android:inputType="text" />

        </com.google.android.material.textfield.TextInputLayout>


    </androidx.constraintlayout.widget.ConstraintLayout>

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

Java代码: 没意思,只有这两行: 1- bind.motionLayout.transitionToEnd(); 2- bind.textLayoutInput.getEditText().getText().toString();

注意:当我从 TextLayoutInput 中删除 TextInputEditText 时(留空),没有出现错误(没有渲染问题),可能是与 TextInputEditText 相关的问题。

注意 2:如果我从 TextLayoutInput 中删除此属性:

app:errorContentDescription="@string/wrong_code"
app:errorEnabled="false"
app:hintAnimationEnabled="true"
app:hintEnabled="true"

此问题出现,此外,测量错误呈现问题:

java.lang.NullPointerException
at android.content.res.Resources_Delegate.getResourceInfo(Resources_Delegate.java:144)
at android.content.res.Resources_Delegate.getResourceName(Resources_Delegate.java:743)
at android.content.res.Resources.getResourceName(Resources.java:2064)
at androidx.constraintlayout.widget.ConstraintLayout.setChildrenConstraints(ConstraintLayout.java:1170)
at androidx.constraintlayout.widget.ConstraintLayout.updateHierarchy(ConstraintLayout.java:1143)
at androidx.constraintlayout.widget.ConstraintLayout.onMeasure_Original(ConstraintLayout.java:1703)
at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java)
at android.view.View.measure_Original(View.java:24552)
at android.view.View_Delegate.measure(View_Delegate.java:80)
at android.view.View.measure(View.java:24516)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure_Original(View.java:24552)
at android.view.View_Delegate.measure(View_Delegate.java:80)
at android.view.View.measure(View.java:24516)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:735)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:481)
at android.view.View.measure_Original(View.java:24552)
at android.view.View_Delegate.measure(View_Delegate.java:80)
at android.view.View.measure(View.java:24516)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure_Original(View.java:24552)
at android.view.View_Delegate.measure(View_Delegate.java:80)
at android.view.View.measure(View.java:24516)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.measureView(RenderSessionImpl.java:638)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.doLayout(RenderSessionImpl.java:406)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.renderAndBuildResult(RenderSessionImpl.java:546)
at com.android.layoutlib.bridge.impl.RenderSessionImpl.render(RenderSessionImpl.java:449)
at com.android.layoutlib.bridge.BridgeRenderSession.render(BridgeRenderSession.java:123)
at com.android.ide.common.rendering.api.RenderSession.render(RenderSession.java:143)
at com.android.ide.common.rendering.api.RenderSession.render(RenderSession.java:125)
at com.android.tools.idea.rendering.RenderTask.lambda$null(RenderTask.java:966)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1604)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

图片: after animation end and I tap/click the TextInputEditText one time

after one tap, I try to force write with no focus but the text is written

after some text is written, I tap again and I get focus

if I delete the text, focus lose and we back to the start of the problem

更新

经过一些测试和尝试找出解决方案,找到了渲染错误“onmeasure()”的解决方案,但它并不有效(如果我使用旧代码,则存在崩溃窃取),但 TextInputLayout 没有收到完全专注。

注意:TextinputLayout 是 ID 为 'second_layout'

的 ConstraintLayout 的子项

动画很简单,从左到右过渡,这是我的旧 MotionLayout 布局描述如下:

    <Transition
    android:id="@+id/transition_a_to_b"
    motion:constraintSetEnd="@id/b_end"
    motion:constraintSetStart="@id/b_start"
    motion:duration="200" />

<ConstraintSet android:id="@+id/b_start">
    <Constraint
        android:id="@id/first_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />


    <Constraint
        android:id="@id/second_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintEnd_toStartOf="parent"
        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />
</ConstraintSet>

<ConstraintSet android:id="@+id/b_end">
    <Constraint
        android:id="@id/first_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintStart_toEndOf="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />

   
    <Constraint
        android:id="@id/second_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintStart_toStartof="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />
</ConstraintSet>

解决方案是将过渡从左到右更改为从右到左,所以我只是将代码更改为:

   <Transition
    android:id="@+id/transition_a_to_b"
    motion:constraintSetEnd="@id/b_end"
    motion:constraintSetStart="@id/b_start"
    motion:duration="200" />

<ConstraintSet android:id="@+id/b_start">
    <Constraint
        android:id="@id/first_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />


    <Constraint
        android:id="@id/second_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintStart_toEndOf="parent"
        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />
</ConstraintSet>

<ConstraintSet android:id="@+id/b_end">
    <Constraint
        android:id="@id/first_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintEnd_toStartOf="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />

   
    <Constraint
        android:id="@id/second_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintStart_toStartof="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />
</ConstraintSet>

经过数小时的尝试解决此问题(崩溃)后,问题是由 TextInputEditText 产生的,因为如果我将其从 TextInputLayout 中删除,旧动画将正常工作。

最后,我正在使用最新版本的 androidX、material 设计和约束布局

问题

TextInputLayout 会绘制不正常所以得不到焦点,原因是他的parent的Constraint(Constraint of ConstraintSet of Transition)。

注意:我的动画是in-animation,secound_layout是TextInputLayout的父类

// This Constraint is child of ConstraintSet of end transition
<Constraint
    android:id="@id/second_layout"

    // attrs are correct but the problem generated by them
    // this is attrs are the problem of bad drawn
    ​
   ​android:layout_width="0dp"
   ​android:layout_height="0dp"

   ​motion:layout_constraintStart_toStartof="parent"
   ​
   ​// this is attrs are the problem of bad drawn
   ​motion:layout_constraintHeight_default="percent"
   ​motion:layout_constraintHeight_percent="1"        
   ​motion:layout_constraintWidth_default="percent"
   ​motion:layout_constraintWidth_percent="1" />

解决方案

使用:

android:layout_width="match_parent
android:layout_height="match_parent"

在 TextInputLayout 的父 Constraint 中,在转换的开始或结束 ConstraintSet 中(取决于您的情况)。

所以如果你的动画是“IN”,在结尾的ConstraintSet中设置父宽度和高度的Constraint为“match_parent”,或者如果动画是“OUT”,设置父宽度的Constraint & height to "match_parent" in ConstraintSet of start.

在我的情况下,TextInputLayout的parent是“second_layout”,动画是“IN”,所以end的ConstraintSet中“second_layout”的宽高Constraint应该是设置为“match_parent”。 代码将是:

    <Transition
    android:id="@+id/transition_a_to_b"
    motion:constraintSetEnd="@id/b_end"
    motion:constraintSetStart="@id/b_start"
    motion:duration="200" />

<ConstraintSet android:id="@+id/b_start">
    <Constraint
        android:id="@id/first_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />


    <Constraint
        android:id="@id/second_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintStart_toEndOf="parent"
        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1" />
</ConstraintSet>

<ConstraintSet android:id="@+id/b_end">
    <Constraint
        android:id="@id/first_layout"
android:layout_width="0dp"
        android:layout_height="0dp"

        motion:layout_constraintHeight_default="percent"
        motion:layout_constraintHeight_percent="1"
        motion:layout_constraintEnd_toStartof="parent"
        motion:layout_constraintWidth_default="percent"
        motion:layout_constraintWidth_percent="1"
        
    />

   
    <Constraint
        android:id="@id/second_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</ConstraintSet>

应将此问题告知 Material 设计团队,因为该问题存在于其他实现中。