Android动态布局之 ConstraintLayout(通过代码参数控制子View的布局)

Constraintlayout布局如今已是Android的默认布局,它的优势是具有非常良好的屏幕适配特性和灵活的布局风格,既可通过传统的layout.xml文档控制,又可以通过可视化工具来构建布局。关于Constraintlayout的详细介绍和使用方法可以参 谷歌文档。接下来进入正题:

众所周知,像RelativeLayout这样的布局可以通过addRule()动态的把子View布局到特定的位置。可能有的看官会说:”我一开始就把布局写在loayout.xml里不行吗?“  既然这样,我们不妨设想下你接到一个需求,你有两个按钮从左到右分别为btn_one和btn_two,点击btn_one后该按钮会跑到btn_two的右边,点击btn_two后该按钮会跑到btn_one的左边(实际需求一定还会更加复杂)。所以xml控制的静态布局是有弊端的,这时通过代码实现的动态布局就派上了用场,类似的还有mView.setLayoutParams(layoutParams)也是如此。那么Constraintlayout可以实现类似的动态布局吗?这答案当然是肯定的,Constraintlayout不仅能实现动态布局,还能在动态布局的基础上进行view动画。接下来我们就详细介绍下:

首先介绍ConstraintSet对象。它是一个ConstraintLayout 内所有子元素的约束条件、也包括外边距和内边距。你可以使用ConstraintSet对象在代码中实时更新你ConstraintLayout 内所有子元素的布局,从而达到动态布局的效果。

要使用要使用 ConstraintSet需要指定两个xml布局文件,一个是初始布局(例如:activity_main.xml),另一个是变化后的布局(这里我命名为:constraint_two.xml)。如下为 Constraintlayout的动态布局Demo:

1. 在activity_main.xml中,我们为布局的创建了一个 android:id="@+id/constraint_one" id, 其次就是一个Button和TextView,初始时Button在TextView上方,当我们点击按钮后该Button会移动到TextView下方,具体布局文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraint_one"
    android:orientation="vertical">

    <Button
        android:id="@+id/loadImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Load Image"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="10dp"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hello~~"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintLeft_toLeftOf="@id/loadImage"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.24" />
    
</androidx.constraintlayout.widget.ConstraintLayout>


2. 我们还需要新建一个constraint_two.xml。并为该布局定义一个android:id="@+id/constraint_two".注意这里有一个魔鬼细节,我们只用将需要需要改变布局的子View添加进去就行,并且该子View的android:id需要和初始布局(也就是上面的activity_main.xml)中的保持一致。因为我只想改变id为loadImage按钮的布局,所以我只把它给写入constraint_two.xml中,而TextView则没有写入,这里需要看官们特别注意下,具体代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraint_two">

    <Button
        android:id="@+id/loadImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Load Image"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

3. 接下来就是MainActivity的代码了,里面的注释请看官仔细阅读:

public class MainActivity extends AppCompatActivity {

    Button loadButton;
    ConstraintLayout constraint_one; //声名 constraint_one
    private static Boolean isConstraintOne = true; //判断是否处在constraint_one的布局中

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        constraint_one = (ConstraintLayout) findViewById(R.id.constraint_one); //初始化constraint_one
        loadButton = findViewById(R.id.loadImage);
        
        //分别创建两个ConstraintSet对象,并把改变前后的两个布局给保存到其中,这里使用的是`.clone`的方法
        ConstraintSet mConstrainSet_one = new ConstraintSet();
        ConstraintSet mConstrainSet_two = new ConstraintSet();
        mConstrainSet_one.clone(constraint_one);
        mConstrainSet_two.clone(this, R.layout.constraint_two);
        
        //对按钮添加点击事件
        loadButton.setOnClickListener(view -> {
            if (isConstraintOne) {
                mConstrainSet_two.applyTo(constraint_one);//将改变后的布局应用进去
                
                //此方法是给这次改变添加个动画效果
                //添加了此句代码后,Button的改变会以动画的形式逐渐移动到改变后的目标位置
                TransitionManager.beginDelayedTransition(constraint_one);
                
                isConstraintOne = false;
            } else {
                mConstrainSet_one.applyTo(constraint_one);//恢复到初始时的布局状态
                isConstraintOne = true;
            }
        });
    }
}

好了,这就是关于 Constraintlayout动态布局的基本介绍及其简单的使用方法和Demo案例。欢迎大家对我进行指正或者补充,如果对你有所帮助不妨点赞鼓励下,祝大家技术稳步前进,工资早日翻倍(狗头坏笑)!

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值