MotionLayout添加3个及以上CustomAttribute时抛出ArrayIndexOutOfBoundsException
I ran into a frustrating issue while working with MotionLayout in Android: adding a 3rd customColorValue, customIntegerValue, or customFloatValue in a MotionScene triggers an ArrayIndexOutOfBoundsException from the MotionController. Here's everything you need to know to reproduce and understand the problem:
Problem Overview
When defining 3 or more custom attributes with color/integer/float values in a ConstraintSet within a MotionScene, the app crashes immediately. The exception indicates the array length is 2 but we're trying to access index 2, and it happens during the MotionController.setup() call when MotionLayout is initializing.
Reproducible Code
Layout File
<androidx.constraintlayout.motion.widget.MotionLayout android:layout_width="wrap_content" android:layout_height="wrap_content" app:layoutDescription="@xml/motion_scene"> <com.spruce.messenger.composer.MessageTypeButton android:id="@+id/messageType" style="@style/messageTypeSelectionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Message" /> </androidx.constraintlayout.motion.widget.MotionLayout>
MotionScene File
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetEnd="@+id/end" motion:constraintSetStart="@+id/start" motion:duration="100" motion:motionInterpolator="linear"> <OnSwipe motion:dragDirection="dragRight" motion:maxAcceleration="18" motion:onTouchUp="autoComplete" motion:touchAnchorId="@+id/messageType" motion:touchAnchorSide="left" motion:touchRegionId="@+id/messageType" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/messageType"> <CustomAttribute motion:attributeName="StrokeTintColor" motion:customColorValue="#D68739" /> <CustomAttribute motion:attributeName="TextColor" motion:customColorValue="#2D70FF" /> <CustomAttribute motion:attributeName="BackgroundTint" motion:customColorValue="#F1F6FF" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@id/messageType"> <CustomAttribute motion:attributeName="StrokeTintColor" motion:customColorValue="#D68739" /> <CustomAttribute motion:attributeName="TextColor" motion:customColorValue="#D68739" /> <CustomAttribute motion:attributeName="BackgroundTint" motion:customColorValue="#FFFCF3" /> </Constraint> </ConstraintSet> </MotionScene>
Crash Log
java.lang.ArrayIndexOutOfBoundsException: length=2; index=2 at androidx.constraintlayout.motion.widget.MotionController.setup(MotionController.java:592) at androidx.constraintlayout.motion.widget.MotionLayout.setupMotionViews(MotionLayout.java:1196) at androidx.constraintlayout.motion.widget.MotionLayout.access$700(MotionLayout.java:820) at androidx.constraintlayout.motion.widget.MotionLayout$Model.reEvaluateState(MotionLayout.java:1850) at androidx.constraintlayout.motion.widget.MotionLayout.onMeasure(MotionLayout.java:1977) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535) at android.widget.LinearLayout.measureVertical(LinearLayout.java:825) at android.widget.LinearLayout.onMeasure(LinearLayout.java:704) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535) at android.widget.LinearLayout.measureVertical(LinearLayout.java:825) at android.widget.LinearLayout.onMeasure(LinearLayout.java:704) at android.view.View.measure(View.java:23169) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at com.android.internal.policy.DecorView.onMeasure(DecorView.java:716) at android.view.View.measure(View.java:23169) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2718) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1572) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1855) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949) at android.view.Choreographer.doCallbacks(Choreographer.java:761) at android.view.Choreographer.doFrame(Choreographer.java:696) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Update
I've already filed this issue with the Android ConstraintLayout team for further investigation.
内容的提问来源于stack exchange,提问作者M-Wajeeh

