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案例。欢迎大家对我进行指正或者补充,如果对你有所帮助不妨点赞鼓励下,祝大家技术稳步前进,工资早日翻倍(狗头坏笑)!
|