ConstraintLayout ConstraintSet - 无法正常使用 Start/End 约束
ConstrainLayout ConstraintSet - not working properly with Start/End constrains
看起来 ConstraintSet
很难应付 Start/End
的限制。
此示例取自 Google 个示例。
Github: android-ConstraintLayoutExamples
当您将左右约束替换为 Start
和 End
时,ConstraintSet - 无法正常工作,它仅适用于 Left/Right
约束。
例如替换
layout_constraintStart_toStartOf 替换为 layout_constraintLeft_toLeftOf
layout_constraintEnd_toEndOf 和 layout_constraintRight_toRightOf
在以下文件中:
constraintset_example_main.xml
constraintset_example_big.xml
行为:
点击图片:
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
本身的错误?
这看起来像是 ConstraintSet
的问题,但让我们看看。以下分析基于 sample project
和您提供的 link。
在示例项目中,我已将 ConstraintLayout
更新到最新版本:
compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
我这样做是为了防止我们试图追踪已经解决的问题。我还更新了布局 constraintset_example_big
并将所有 left/right 约束替换为 start/end 约束,如下所示:
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>
有了这些变化,这就是我们所看到的。
这显然是不对的。过渡后应该看起来像 this
。
经过一些调试,我将问题追踪到 ConstraintSetExampleActivity.java
中的这一行:
mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintSet#load()
看起来很简单,但是如果我们用布局的显式 inflation 替换上面的代码,然后在膨胀布局上克隆 ConstraintSet
如下:
// mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintLayout cl = (ConstraintLayout) getLayoutInflater().inflate(R.layout.constraintset_example_big,null);
mConstraintSetBig.clone(cl);
我们在应用程序中看到这种行为要好得多。
所以我的结论是 ConstraintSet#load()
在 start/end 约束方面存在问题。解决方法是膨胀 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 beta 6 版本中修复
对于那些面临约束集克隆无法正常工作等问题的人,当我在 api 调用后调用 clone 和 applyTo 方法时,我的布局没有更新到新的约束,事实证明这是由于加载我在导致错误的更改之前显示的对话框。
看起来 ConstraintSet
很难应付 Start/End
的限制。
此示例取自 Google 个示例。 Github: android-ConstraintLayoutExamples
当您将左右约束替换为 Start
和 End
时,ConstraintSet - 无法正常工作,它仅适用于 Left/Right
约束。
例如替换
layout_constraintStart_toStartOf 替换为 layout_constraintLeft_toLeftOf
layout_constraintEnd_toEndOf 和 layout_constraintRight_toRightOf
在以下文件中:
constraintset_example_main.xml
constraintset_example_big.xml
行为:
点击图片:
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
本身的错误?
这看起来像是 ConstraintSet
的问题,但让我们看看。以下分析基于 sample project
和您提供的 link。
在示例项目中,我已将 ConstraintLayout
更新到最新版本:
compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
我这样做是为了防止我们试图追踪已经解决的问题。我还更新了布局 constraintset_example_big
并将所有 left/right 约束替换为 start/end 约束,如下所示:
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>
有了这些变化,这就是我们所看到的。
这显然是不对的。过渡后应该看起来像 this
。
经过一些调试,我将问题追踪到 ConstraintSetExampleActivity.java
中的这一行:
mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintSet#load()
看起来很简单,但是如果我们用布局的显式 inflation 替换上面的代码,然后在膨胀布局上克隆 ConstraintSet
如下:
// mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintLayout cl = (ConstraintLayout) getLayoutInflater().inflate(R.layout.constraintset_example_big,null);
mConstraintSetBig.clone(cl);
我们在应用程序中看到这种行为要好得多。
所以我的结论是 ConstraintSet#load()
在 start/end 约束方面存在问题。解决方法是膨胀 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 beta 6 版本中修复
对于那些面临约束集克隆无法正常工作等问题的人,当我在 api 调用后调用 clone 和 applyTo 方法时,我的布局没有更新到新的约束,事实证明这是由于加载我在导致错误的更改之前显示的对话框。