ConstrainLayout ConstraintSet - 无法正常使用开始/结束约束

时间:2018-03-12 10:07:07

标签: android android-constraintlayout

ConstraintSet看起来很难应对Start/End约束。

此示例摘自 Google示例。 Github:android-ConstraintLayoutExamples


当您替换Left&正确约束Start& End,ConstraintSet - 无法正常工作,仅适用于Left/Right约束。
例如替换 layout_constraintStart_toStartOf with layout_constraintLeft_toLeftOf&更换 layout_constraintEnd_toEndOf with layout_constraintRight_toRightOf

以下文件:
constraintset_example_main.xml
constraintset_example_big.xml

行为:

onClick of image:

private ConstraintSet mConstraintSetNormal = new ConstraintSet();

    private ConstraintSet mConstraintSetBig = new ConstraintSet();

 public void toggleMode(View v) {
        TransitionManager.beginDelayedTransition(mRootLayout);
        mShowBigImage = !mShowBigImage;
        applyConfig();
    }

    private void applyConfig() {
        if (mShowBigImage) {
            mConstraintSetBig.applyTo(mRootLayout);
        } else {
            mConstraintSetNormal.applyTo(mRootLayout);
        }
    }

默认情况下,Android工作室使用start / end约束,因此我想了解根本原因和可能的修复方法。
或者这是ConstrainSet本身的错误吗?

3 个答案:

答案 0 :(得分:4)

这看起来像ConstraintSet的问题,但让我们看看。以下分析基于sample project以及您提供的链接。

在示例项目中,我已将ConstraintLayout更新为最新版本:

compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'

我是这样做的,以防我们试图追查已经解决过的问题。我还更新了布局constraintset_example_big并用开始/结束约束替换了所有左/右约束,如下所示:

<强> constraintset_example_big.xml

<android.support.constraint.ConstraintLayout 
    android:id="@+id/activity_constraintset_example"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginEnd="24dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="24dp"
        android:onClick="toggleMode"
        android:scaleType="centerCrop"
        android:src="@drawable/lake"
        app:layout_constraintDimensionRatio="h,16:9"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:contentDescription="@string/lake_tahoe_image" />

    <TextView
        android:id="@+id/textView9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lake_tahoe_title"
        android:textSize="30sp"
        app:layout_constraintStart_toStartOf="@+id/imageView"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/imageView" />

    <TextView
        android:id="@+id/textView11"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="@string/lake_discription"
        app:layout_constraintStart_toStartOf="@+id/textView9"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/textView9"
        app:layout_constraintEnd_toEndOf="@+id/imageView"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="16dp"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintVertical_bias="0.0" />

</android.support.constraint.ConstraintLayout>

有了这些变化,这就是我们所看到的。

enter image description here

这显然不对。转换后它应该看起来像this

经过一些调试后,我在ConstraintSetExampleActivity.java

中将问题跟踪到这一行
mConstraintSetBig.load(this, R.layout.constraintset_example_big);

ConstraintSet#load()似乎很简单,但是如果我们用布局的显式膨胀替换上面的代码,然后在膨胀的布局上克隆ConstraintSet,如下所示:

// mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintLayout cl = (ConstraintLayout) getLayoutInflater().inflate(R.layout.constraintset_example_big,null);
mConstraintSetBig.clone(cl);

我们在应用中看到这种行为要好得多。

enter image description here

所以我的看法是ConstraintSet#load()在开始/结束约束方面存在问题。解决方法是膨胀ConstraintLayout然后进行克隆。

<强> ConstraintSetExampleActivity#的onCreate()

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.constraintset_example_main);

    mRootLayout = (ConstraintLayout) findViewById(R.id.activity_constraintset_example);
    // Note that this can also be achieved by calling
    // `mConstraintSetNormal.load(this, R.layout.constraintset_example_main);`
    // Since we already have an inflated ConstraintLayout in `mRootLayout`, clone() is
    // faster and considered the best practice.
    mConstraintSetNormal.clone(mRootLayout);
    // Load the constraints from the layout where ImageView is enlarged.

    // Toggle the comment status on the following three lines to fix/break.
    // mConstraintSetBig.load(this, R.layout.constraintset_example_big);
    ConstraintLayout cl = (ConstraintLayout) getLayoutInflater().inflate(R.layout.constraintset_example_big,null);
    mConstraintSetBig.clone(cl);

    if (savedInstanceState != null) {
        boolean previous = savedInstanceState.getBoolean(SHOW_BIG_IMAGE);
        if (previous != mShowBigImage) {
            mShowBigImage = previous;
            applyConfig();
        }
    }
}

答案 1 :(得分:1)

此问题已知,将在1.1 beta 6版本中修复

https://issuetracker.google.com/issues/74253269

答案 2 :(得分:0)

对于那些面临约束集克隆等问题无法正常工作的人,我在api调用后调用clone和applyTo方法时,布局没有更新为新约束,这是由于更改之前显示的加载对话框导致了错误。