Constraint Layout [Animations | Dynamic Constraints | UI by Java] ( What the hell is this )[Part3]

大家好,希望每个人身体健康。在part1part2部分对于Constraint Layout我们已经了解了很多新的知识。现在是时候学习Constraint Lyaout的剩余部分了,很有可能这是关于Constraint Layout 的最后一部分。

动机:

今天的学习动机和在part1部分是一样的,不过在这篇文章中我们只要集中在Constraint Layout 的动画上。不好的消息是Android给出文档中并不能给予我们太多帮助。在开始这篇文章之前我要先向各位道歉,因为我对某些概念的理解是有错误的;但是,在最后我会给你100%的保证,根据我的概念你在使用Constraint Layout 的动画时会很享受,很舒服。

对于这个主题的名字我很困惑,最有决定使用三个名词( Constraint Layout Animations, Constraint Layout Dynamic Constraints and Constraint Layout UI by Java)来作为这篇文章的名字,在文章的最后,你就会理解我为什么使用这个三个名词。

这次我不会直接解释Constraint Layout 动画API介绍的功能,而是和你分享你在实现过程中可能遇到的问题。那就开始吧:)。

我们必须下载2.3版本的AndroidStudio,之前版本对Visual Editor支持不是很好,在Design Tab会提示一下错误信息。因为下载最新的2.3版本是十分必要的,在我写这篇文章时2.3beta版已经可以使用了。

简介:

在这篇文章中我们主要使用java编程,但在开始之前我要解释一下这篇文章的内容是如何运行的。
屏幕截图

在这篇文章中我将使用上面这个app。我使用了一个Constraint Layout,并且在这个布局里包含了5个Button。
Apply和Reset Button只负责应用和重置我们的动画,其他是三个button用于动画效果。我们会在这三个Button上演示不同的动画效果。最重要的是在开始前我们需要知道这三个Button的约束。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <Button
        android:id="@+id/applyButton" 
        android:text="Apply"
        ...
        />

    <Button
        android:id="@+id/resetButton"
        android:text="Reset"
        ...
        />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="Button 1"
        android:layout_marginLeft="52dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="52dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="69dp" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        android:text="Button 2"
        app:layout_constraintLeft_toRightOf="@+id/button1"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.571"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="136dp" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_red_dark"
        android:text="Button 3"
        android:layout_marginTop="102dp"
        app:layout_constraintTop_toBottomOf="@+id/button1"
        android:layout_marginLeft="88dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="88dp" />

</android.support.constraint.ConstraintLayout>

因为查看完代码,你能够很容易的理解这个三个Button之间的关系,但为了轻松一下看下面这张图
按钮关系图

哈哈,我知道这个图和查看xml比起来相当简单。现在你了解了三个button之间和父布局之间的关系。太棒了。
另外,在更深入之前我想给你解释另一个新的API。

public class MainActivity extends AppCompatActivity {

    private ConstraintLayout constraintLayout;
    private ConstraintSet applyConstraintSet = new ConstraintSet();
    private ConstraintSet resetConstraintSet = new ConstraintSet();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        constraintLayout = (ConstraintLayout) findViewById(R.id.main);
        resetConstraintSet.clone(constraintLayout);
        applyConstraintSet.clone(constraintLayout);
    }

    public void onApplyClick(View view) {

    }

    public void onResetClick(View view) {

    }

我们主要看ConstraintSet的两个实例,其他代码都很简单。ConstraintSet 这个API在这篇教程中我们会大量使用。简单来说,你可以想像这个API将会记住我们在XML中实现的所有约束。怎么样?就如你看到的,在上面代码中我有一个ConstraintLayout的引用,之后我将clone它的约束到这两个字段resetConstraintSetapplyConstraintSet中。非常简单。
从这里开始,为了新的要求我将要改变我的写作风格。迷惑。。。
对于同样的要求我将使用不同的语句,因此你可以很容易理解这篇文章的标题了。

New Requirements:

当用户点击Apply时,我想要button1通过动画的方式和父视图的左对齐;
用开发者语言描述:
哥们儿,当用户点击Apply时,我想要在ConstraintLayout中使用java代码将button1和父视图做对齐,你能帮助我吗?

Solution:
public void onApplyClick(View view) {
    applyConstraintSet.setMargin(R.id.button1,ConstraintSet.START,8);
    applyConstraintSet.applyTo(constraintLayout);
}

public void onResetClick(View view) {
    resetConstraintSet.applyTo(constraintLayout);
}

从现在开始我只向你展示onApplyClick()方法,其他部分到是相同了。忘记了,如果你看onResetClick(),我总是应用初始的约束来让UI回到初始状态。
现在这里有两个新API的方法,setMargin()applyTo(),我觉得applyTo() 就不必解释了吧。
setMargin() 将会接受三个参数(viewId,anchor,margin)。Button1的左边距52dp,但当用户点击时变成8px。接下来给你展示效果。
展示动画

没有按钮是移动的而是突然改变,这看起来一点也不像动画。这太糟糕了,因为我们需要再次审核一下代码。
审查代码之后我搞明白了,我需要在applyButton()方法中添加一行代码。下面就是添加完这样代码的效果。
动画效果
搞定!是时候回顾一下新代码的变动了。

public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);
    applyConstraintSet.setMargin(R.id.button1,ConstraintSet.START,8);
    applyConstraintSet.applyTo(constraintLayout);
}

这里我必须添加TransitionManager API。各位,对于TransitionManager API这里有一个支持库,你可以添加gradle依赖。

compile 'com.android.support:transition:25.1.0'

在进入下一个需求之前,我想校正一下这些事情。
简单来说我们仅仅使用了两个API,ConstraintSet和TransitionManager。从现在开始我们仅使用了ConstraintSet API。

New Requirement:

用户语言描述:
我想给所有按钮添加动画,当用户点击Apply时,所有按钮在父控件中水平居中。
开发者语言描述:
哥们儿,当用户点击apply按钮时,我想要所有的按钮移动到父控件的水平中部,需要在ConstraintLayout中使用Java代码完成。你能帮助我吗?

Solution:
public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);
    applyConstraintSet.centerHorizontally(R.id.button1, R.id.main);
    applyConstraintSet.centerHorizontally(R.id.button2, R.id.main);
    applyConstraintSet.centerHorizontally(R.id.button3, R.id.main);
    applyConstraintSet.applyTo(constraintLayout);
}

这里我使用了centerHorizontally()方法。这个方法接收两个参数:
First:我想做水平居中的View;
Second:根据哪个View来水平居中;
centerHorizontally效果
Oh这不是我想要的效果。在分析之后我知道了问题所在。对于不同的按钮有不同的margin,当我们点击Apply按钮时,这些按钮都要居中但是然需要考虑margin。所以是时候解决这个问题了。

public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);

    applyConstraintSet.setMargin(R.id.button1,ConstraintSet.START,0);
    applyConstraintSet.setMargin(R.id.button1,ConstraintSet.END,0);
    applyConstraintSet.setMargin(R.id.button2,ConstraintSet.START,0);
    applyConstraintSet.setMargin(R.id.button2,ConstraintSet.END,0);
    applyConstraintSet.setMargin(R.id.button3,ConstraintSet.START,0);
    applyConstraintSet.setMargin(R.id.button3,ConstraintSet.END,0);


    applyConstraintSet.centerHorizontally(R.id.button1, R.id.main);
    applyConstraintSet.centerHorizontally(R.id.button2, R.id.main);
    applyConstraintSet.centerHorizontally(R.id.button3, R.id.main);
    applyConstraintSet.applyTo(constraintLayout);
}

这里我让所有按钮的左右margin都为0,然后看效果。
这里写图片描述

New Requirement:

用户语言描述:
当用户点击Apply时,我想给button3添加动画使其移动的父控件中部;
开发者语音描述:
哥们儿,当用户点击Apply时,我想要button3移动到父控件的中部,需要在ConstraintLayout中使用Java代码实现。你能帮助我吗?

Solution:
public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);

    applyConstraintSet.setMargin(R.id.button3,ConstraintSet.START,0);
    applyConstraintSet.setMargin(R.id.button3,ConstraintSet.END,0);
    applyConstraintSet.setMargin(R.id.button3,ConstraintSet.TOP,0);
    applyConstraintSet.setMargin(R.id.button3,ConstraintSet.BOTTOM,0);

    applyConstraintSet.centerHorizontally(R.id.button3, R.id.main);
    applyConstraintSet.centerVertically(R.id.button3, R.id.main);

    applyConstraintSet.applyTo(constraintLayout);
}

这里首先我给四个边添加了0边距,之后我用到了centerHorizontal + centerVertical 方法。
button3动画

New Requirement:

用户语言描述:
当用户点击Apply时,我想给所有button添加动画效果使其从当前大小到600px;
开发者语音描述:
哥们儿,当用户点击Apply时,我想给所有button添加动画效果使其从当前大小到600px,需要在ConstraintLayout中使用Java代码实现。你能帮助我吗?

Solution:
public void onApplyClick(View view) {
        TransitionManager.beginDelayedTransition(constraintLayout);

        applyConstraintSet.constrainWidth(R.id.button1,600);
        applyConstraintSet.constrainWidth(R.id.button2,600);
        applyConstraintSet.constrainWidth(R.id.button3,600);

//        applyConstraintSet.constrainHeight(R.id.button1,100);
//        applyConstraintSet.constrainHeight(R.id.button2,100);
//        applyConstraintSet.constrainHeight(R.id.button3,100);

        applyConstraintSet.applyTo(constraintLayout);

    }

这里我使用了constraintWidth 方法,效果如下。
宽度增加动画

New Requirement:

用户语言描述:
当用户点击Apply时,我想给所有button1添加动画效果使其它的宽高和等于屏幕大小,同时其他按钮隐藏;
开发者语音描述:
哥们儿,当用户点击Apply时,我先想要button1的宽高值为match_parent,而其他视图Visible属性设置为gone,需要在ConstraintLayout中使用Java代码实现。你能帮助我吗?

Solution:
public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);

    applyConstraintSet.setVisibility(R.id.button2,ConstraintSet.GONE);
    applyConstraintSet.setVisibility(R.id.button3,ConstraintSet.GONE);
    applyConstraintSet.clear(R.id.button1);
    applyConstraintSet.connect(R.id.button1,ConstraintSet.LEFT,R.id.main,ConstraintSet.LEFT,0);
    applyConstraintSet.connect(R.id.button1,ConstraintSet.RIGHT,R.id.main,ConstraintSet.RIGHT,0);
    applyConstraintSet.connect(R.id.button1,ConstraintSet.TOP,R.id.main,ConstraintSet.TOP,0);
    applyConstraintSet.connect(R.id.button1,ConstraintSet.BOTTOM,R.id.main,ConstraintSet.BOTTOM,0);
    applyConstraintSet.applyTo(constraintLayout);
}

这里我想解释一下我用到的几个新方法:
setVisibility:这个很简单,就不解释了;
clear:清楚加在这个View上的所有约束;
connet:给这个View添加约束,这个方法接收五个参数。
1st:我想添加约束的View;
2nd:侧面/边缘 我想使用的约束;
3rd:给视图添加约束时对应的锚点视图;
4th:锚点视图的侧面/边缘;
5th:边距;
button1铺满全屏

是时候开始一些高端的特性了。根据我们在totorial2部分学习的Chaining 概念。我将向你展示如何用JAVA来实现。

New Requirement:

用户语言描述:
当用户点击Apply时,我想给所有button添加动画,彼此对齐,位于屏幕的顶部并且水平居中;
开发者语音描述:
哥们儿,当用户点击Apply时,我想实现三个按钮的packed chaning效果,需要在ConstraintLayout中使用Java代码实现。你能帮助我吗?

Solution:

正如我说的这是先进的用法,但是我要解释一下其实也没啥大不了的。所以准备好了。

public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);

    applyConstraintSet.clear(R.id.button1);
    applyConstraintSet.clear(R.id.button2);
    applyConstraintSet.clear(R.id.button3);

首先,我清除了三个按钮的所以约束。这是我个人的偏好,你也可以只移除边距,大小或其他属性,但我感觉这是最简单的实现方式。现在我们的按钮已经没有约束了。(0 width, 0 height, 0 margin …)

// button 1 left and top align to parent
applyConstraintSet.connect(R.id.button1, ConstraintSet.LEFT, R.id.main, ConstraintSet.LEFT, 0);

现在我给button1添加左约束,就像上面展示的一样。

// button 3 right and top align to parent
applyConstraintSet.connect(R.id.button3, ConstraintSet.RIGHT, R.id.main, ConstraintSet.RIGHT, 0);

接着我给button3添加了右约束,在你的大脑中产生一个这个代码的草图,现在button1在父控件的左上角,同时button2在父控件的右边。

// bi-direction or Chaining between button 1 and button 2
applyConstraintSet.connect(R.id.button2, ConstraintSet.LEFT, R.id.button1, ConstraintSet.RIGHT, 0);
applyConstraintSet.connect(R.id.button1, ConstraintSet.RIGHT, R.id.button2, ConstraintSet.LEFT, 0);

这里button1和button2 之间创建了bi-directional的关系,正如上面展示的那样;

// bi-direction or Chaining between button 2 and button 3
applyConstraintSet.connect(R.id.button2, ConstraintSet.RIGHT, R.id.button3, ConstraintSet.LEFT, 0);
applyConstraintSet.connect(R.id.button3, ConstraintSet.LEFT, R.id.button2, ConstraintSet.RIGHT, 0);

这里button2和button3之间创建了bi-directional的关系,正如上面展示的那样;

applyConstraintSet.createHorizontalChain(R.id.button1,
        R.id.button3,
        new int[]{R.id.button1, R.id.button3}, 
        null, ConstraintWidget.CHAIN_PACKED);

这个方法会给我们创建一个水平的链表。因为这个method会接收5个参数。
1st:头View的id;
2nd:这个链表尾View的id;
3rd:int数组,头、尾视图的id组成的int类型数组;
4th:float数组,如果想要有权重的链表设置,否则为null;
5th:链表的类型,例如CHAIN_SPREAD;

现在我尝试运行,我得到了下面的结果;
HorizontalChain

Oh no. That is not required behaviour. If you guys remember I clear all constraints of these Buttons. That’s why there width and height is 0. Now I need to give width and height as shown below.
当然这不是我们想要的结果,如果你们还记得我清除了这些按钮的所以约束,这就是为什么width和height都是0.现在我需要给他们width和height赋值,正如下面这样。

applyConstraintSet.constrainWidth(R.id.button1,ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainWidth(R.id.button2,ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainWidth(R.id.button3,ConstraintSet.WRAP_CONTENT);

applyConstraintSet.constrainHeight(R.id.button1,ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainHeight(R.id.button2,ConstraintSet.WRAP_CONTENT);
applyConstraintSet.constrainHeight(R.id.button3,ConstraintSet.WRAP_CONTENT);

现在再运行一次:
给宽高赋值

完整展示一下代码:

public void onApplyClick(View view) {
    TransitionManager.beginDelayedTransition(constraintLayout);

    applyConstraintSet.clear(R.id.button1);
    applyConstraintSet.clear(R.id.button2);
    applyConstraintSet.clear(R.id.button3);

    // button 1 left and top align to parent
    applyConstraintSet.connect(R.id.button1, ConstraintSet.LEFT, R.id.main, ConstraintSet.LEFT, 0);

    // button 3 right and top align to parent
    applyConstraintSet.connect(R.id.button3, ConstraintSet.RIGHT, R.id.main, ConstraintSet.RIGHT, 0);

    // bi-direction or Chaining between button 1 and button 2
    applyConstraintSet.connect(R.id.button2, ConstraintSet.LEFT, R.id.button1, ConstraintSet.RIGHT, 0);
    applyConstraintSet.connect(R.id.button1, ConstraintSet.RIGHT, R.id.button2, ConstraintSet.LEFT, 0);

    // bi-direction or Chaining between button 2 and button 3
    applyConstraintSet.connect(R.id.button2, ConstraintSet.RIGHT, R.id.button3, ConstraintSet.LEFT, 0);
    applyConstraintSet.connect(R.id.button3, ConstraintSet.LEFT, R.id.button2, ConstraintSet.RIGHT, 0);

    applyConstraintSet.createHorizontalChain(R.id.button1,
            R.id.button3,
            new int[]{R.id.button1, R.id.button3}, null, ConstraintWidget.CHAIN_PACKED);

    applyConstraintSet.constrainWidth(R.id.button1,ConstraintSet.WRAP_CONTENT);
    applyConstraintSet.constrainWidth(R.id.button2,ConstraintSet.WRAP_CONTENT);
    applyConstraintSet.constrainWidth(R.id.button3,ConstraintSet.WRAP_CONTENT);

    applyConstraintSet.constrainHeight(R.id.button1,ConstraintSet.WRAP_CONTENT);
    applyConstraintSet.constrainHeight(R.id.button2,ConstraintSet.WRAP_CONTENT);
    applyConstraintSet.constrainHeight(R.id.button3,ConstraintSet.WRAP_CONTENT);

    applyConstraintSet.applyTo(constraintLayout);
}

现在试着改变一下链表样式:

applyConstraintSet.createHorizontalChain(R.id.button1,
        R.id.button3,
        new int[]{R.id.button1, R.id.button3}, null, ConstraintWidget.CHAIN_SPREAD);

CHAIN_SPREAD

再次改变链表样式:

applyConstraintSet.createHorizontalChain(R.id.button1,
        R.id.button3,
        new int[]{R.id.button1, R.id.button3}, null, ConstraintWidget.CHAIN_SPREAD_INSIDE);

ConstraintWidget.CHAIN_SPREAD_INSIDE

现在我将再次向你展示一下带有bias(偏移)的CHAIN_PACKED ;

applyConstraintSet.createHorizontalChain(R.id.button1,
        R.id.button3,
        new int[]{R.id.button1, R.id.button3}, null, ConstraintWidget.CHAIN_PACKED);

applyConstraintSet.setHorizontalBias(R.id.button1, .1f);

这里正如上所示,我用到了新的setHorizontalBias()方法,其中我给我们链组的头View一个float类型的偏移值;

Bonus:

I am showing you one more use of ConstraintSet which also mentioned in Android API doc. So basically we can apply two different ConstraintSet on same ConstraintLayout as shown below.
这里我将向你展示ConstraintSet另一种用法,这种方式在Android API的文档中也提到了。基本上就是我们可以应用不同的ConstraintSet到同一个ConstraintLayout上,正如下面所示。

public class MainActivity extends AppCompatActivity {

    private ConstraintLayout constraintLayout;
    private ConstraintSet constraintSet1 = new ConstraintSet();
    private ConstraintSet constraintSet2 = new ConstraintSet();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        constraintLayout = (ConstraintLayout) findViewById(R.id.main);
        constraintSet1.clone(constraintLayout);
        constraintSet2.clone(this, R.layout.activity_main2);
    }

    public void onApplyClick(View view) {
        TransitionManager.beginDelayedTransition(constraintLayout);
        constraintSet2.applyTo(constraintLayout);
    }

    public void onResetClick(View view) {
        TransitionManager.beginDelayedTransition(constraintLayout);
        constraintSet1.applyTo(constraintLayout);
    }
}

不同的ConstraintSet

XML of activity_main:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.constraintanimation.MainActivity">


    <Button
        android:onClick="onApplyClick"
        app:layout_constraintHorizontal_weight="1"
        android:id="@+id/applyButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Apply"
        android:layout_marginLeft="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="16dp"
        app:layout_constraintRight_toLeftOf="@+id/resetButton"
        android:layout_marginRight="8dp"
        android:layout_marginEnd="8dp" />

    <Button
        android:onClick="onResetClick"
        app:layout_constraintHorizontal_weight="1"
        android:id="@+id/resetButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Reset"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="16dp"
        app:layout_constraintLeft_toRightOf="@+id/applyButton"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"

        />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="92dp"
        android:layout_height="92dp"
        app:srcCompat="@mipmap/ic_launcher"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.02"
        android:layout_marginEnd="8dp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Hello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\n"
        android:layout_marginRight="8dp"
        android:lines="6"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginEnd="8dp"
        app:layout_constraintLeft_toRightOf="@+id/imageView"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="16dp" />

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CheckBox"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="16dp"
        app:layout_constraintRight_toLeftOf="@+id/textView"
        android:layout_marginRight="8dp"
        app:layout_constraintHorizontal_bias="1.0"
        android:layout_marginEnd="8dp" />

    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>
XML of activty_main2:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.constraintanimation.MainActivity">


    <Button
        android:onClick="onApplyClick"
        app:layout_constraintHorizontal_weight="1"
        android:id="@+id/applyButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Apply"
        android:layout_marginLeft="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="16dp"
        app:layout_constraintRight_toLeftOf="@+id/resetButton"
        android:layout_marginRight="8dp"
        android:layout_marginEnd="8dp" />

    <Button
        android:onClick="onResetClick"
        app:layout_constraintHorizontal_weight="1"
        android:id="@+id/resetButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Reset"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="16dp"
        app:layout_constraintLeft_toRightOf="@+id/applyButton"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"

        />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="353dp"
        android:layout_height="157dp"
        app:srcCompat="@mipmap/ic_launcher"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="8dp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="352dp"
        android:layout_height="108dp"
        android:text="Hello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\nHello this is a simple demo. Thanks for reading and learning new things.\n"
        android:lines="6"
        android:layout_marginTop="12dp"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp" />

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="CheckBox"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginRight="16dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginEnd="16dp" />

    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="Button"
        android:layout_marginRight="16dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginEnd="16dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/textView"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/applyButton" />

</android.support.constraint.ConstraintLayout>

我们终于完成了 ConstraitLayout 动画效果.现在剩下的一个也是最后一个主题是 Constraint Layout Visual [Design] Editor ( What the hell is this )[Part4]
OK,是时候说再见了,祝你有一个愉快的周末。

原文链接:http://www.uwanttolearn.com/android/constraint-layout-animations-dynamic-constraints-ui-java-hell/?utm_source=Android+Weekly&utm_campaign=6222cbbb6f-android-weekly-243&utm_medium=email&utm_term=0_4eb677ad19-6222cbbb6f-337874629

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误通常在使用约束布局ConstraintLayout)时出现,表示一个视图在垂直方向上没有正确的约束条件。在没有垂直约束的情况下,视图在运行时会跳到顶部。 要解决这个问题,你需要为视图添加垂直约束条件。具体的解决方法如下: 1. 打开布局文件,找到出错的视图。 2. 确保该视图与父容器或其他视图之间有垂直的约束条件。可以使用以下约束属性来添加垂直约束: - `app:layout_constraintTop_toTopOf`: 将视图的顶部与另一个视图或父容器的顶部对齐。 - `app:layout_constraintBottom_toBottomOf`: 将视图的底部与另一个视图或父容器的底部对齐。 - `app:layout_constraintTop_toBottomOf`: 将视图的顶部与另一个视图或父容器的底部对齐。 - `app:layout_constraintBottom_toTopOf`: 将视图的底部与另一个视图或父容器的顶部对齐。 3. 根据你的布局需求,选择适当的约束属性,并将其添加到视图的属性中。例如: ```xml <Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="My Button" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> ``` 在这个例子中,`my_button`按钮的顶部和底部分别与父容器的顶部和底部对齐,从而解决了垂直约束错误。 4. 重复以上步骤,为其他出错的视图添加垂直约束条件。 通过添加垂直约束条件,你可以解决这个错误,并确保视图在运行时正确地定位。如果还有其他问题,请提供相关的代码和错误信息,我会尽力帮助你解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值