原創(chuàng)文章隅津,轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/7888cde8292f
ConstraintLayout靜態(tài)構(gòu)建方法
ConstraintLayout的靜態(tài)構(gòu)建的方法噪矛,也就是在布局界面上對(duì)其進(jìn)行處理该窗,網(wǎng)絡(luò)上已經(jīng)有很多文章臂容,也可參考
https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout.html
簡(jiǎn)單而言使用界面對(duì)ConstraintLayout內(nèi)的控件進(jìn)行修改,就是要將控件上下左右(文字)的四個(gè)約束給定義好,直接在布局界面中進(jìn)行拖拉,并調(diào)整好控件的位置即可蹄梢。
ConstraintLayout.LayoutParams
名字很熟悉,繼承自ViewGroup.MarginLayoutParams富俄,而ViewGroup.MarginLayoutParams繼承自ViewGroup.LayoutParams禁炒。這個(gè)就比較熟悉了,在其他的Layout布局也時(shí)常使用這個(gè)來(lái)布局霍比,layoutparams用于在父布局中布局子控件幕袱,子控件利用layoutparams告訴父布局它想如何被放置在父布局中,它包含的屬性類型會(huì)根據(jù)需要為視圖組的每個(gè)子視圖定義尺寸和位置悠瞬。
尺寸的定義可以使用具體值们豌,但常用的是:wrap_content和match_parent ,對(duì)于如何使用Constraintlayoutparams中的layoutparams浅妆,可以參照其他layout的使用方法玛痊,這里沒(méi)有太多特別的地方。
ConstraintSet 約束集合
官網(wǎng)的定義狂打,這個(gè)類允許我們已編程方式定義要與ConstraintLayout一起使用的一組約束,它允許我們創(chuàng)建和保存約束混弥,并將其應(yīng)用于現(xiàn)有的ConstraintLayout中趴乡,ConstraintSet可以通過(guò)各種方式創(chuàng)建:
1. 手動(dòng)創(chuàng)建:
c = new ConstraintSet(); c.connect(...);
2. from a R.layout.*object:
c.clone(context,R.layout.layout1);
3. from a ConstraintLayout:
c.clone(clayout);
那么我們現(xiàn)在就來(lái)創(chuàng)建一個(gè)ConstraintSet 來(lái)嘗試一下(這里出現(xiàn)了問(wèn)題对省,后面有解釋):
首先是主布局xml的代碼:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.zjt.myapplicationfadsgwe.MainActivity"
android:id="@+id/contentPanel">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="0dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="0dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="0dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>
效果如圖:
代碼的邏輯很簡(jiǎn)單,就是點(diǎn)擊Button生成新的Button并將新的Button添加到主視圖中晾捏,代碼如下(注意看注釋):
public class MainActivity extends AppCompatActivity {
private Button add;
private ConstraintLayout constraintLayout;
private int num;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
add=findViewById(R.id.button);
constraintLayout=findViewById(R.id.contentPanel);
num=0;//代表按鈕點(diǎn)擊的次數(shù)
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {//點(diǎn)擊事件
if(num==0){
ConstraintSet constraintSet=new ConstraintSet();//新建一個(gè)ConstraintSet
num++;
Button new1=new Button(MainActivity.this);
//在其中添加第一個(gè)Button
new1.setText("第一個(gè)BUTTON");
constraintLayout.addView(new1);
constraintSet.clone(constraintLayout);
constraintSet.constrainWidth(new1.getId(), ConstraintLayout.LayoutParams.WRAP_CONTENT);
constraintSet.constrainHeight(new1.getId(),ConstraintLayout.LayoutParams.WRAP_CONTENT);
constraintSet.connect(new1.getId(),ConstraintSet.END, ConstraintSet.PARENT_ID,ConstraintSet.END);
constraintSet.connect(new1.getId(),ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START);
//這個(gè)按鈕距離頂部的margin值為1000
constraintSet.connect(new1.getId(),ConstraintSet.TOP, ConstraintSet.PARENT_ID,ConstraintSet.TOP,1000);
constraintSet.connect(new1.getId(),ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM);
constraintSet.applyTo(constraintLayout);
}else if(num==1){
ConstraintSet constraintSet=new ConstraintSet();
num++;
Button new2=new Button(MainActivity.this);
new2.setText("第二個(gè)");
constraintLayout.addView(new2);
constraintSet.clone(constraintLayout);
constraintSet.constrainWidth(new2.getId(), ConstraintLayout.LayoutParams.WRAP_CONTENT);
constraintSet.constrainHeight(new2.getId(),ConstraintLayout.LayoutParams.WRAP_CONTENT);
//這個(gè)按鈕什么都沒(méi)有蒿涎,添加了四個(gè)方向的約束后默認(rèn)居中
constraintSet.connect(new2.getId(),ConstraintSet.END, ConstraintSet.PARENT_ID,ConstraintSet.END);
constraintSet.connect(new2.getId(),ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START);
constraintSet.connect(new2.getId(),ConstraintSet.TOP, ConstraintSet.PARENT_ID,ConstraintSet.TOP);
constraintSet.connect(new2.getId(),ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM);
constraintSet.applyTo(constraintLayout);
}else if(num==2){
ConstraintSet constraintSet=new ConstraintSet();
num++;
Button new3=new Button(MainActivity.this);
new3.setText("3");
constraintLayout.addView(new3);
constraintSet.clone(constraintLayout);
constraintSet.constrainWidth(new3.getId(), ConstraintLayout.LayoutParams.WRAP_CONTENT);
constraintSet.constrainHeight(new3.getId(),ConstraintLayout.LayoutParams.WRAP_CONTENT);
constraintSet.connect(new3.getId(),ConstraintSet.END, ConstraintSet.PARENT_ID,ConstraintSet.END);
constraintSet.connect(new3.getId(),ConstraintSet.START, ConstraintSet.PARENT_ID,ConstraintSet.START);
constraintSet.connect(new3.getId(),ConstraintSet.TOP, ConstraintSet.PARENT_ID,ConstraintSet.TOP);
//這個(gè)按鈕距離底部的margin值為1000
constraintSet.connect(new3.getId(),ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM,1000);
constraintSet.applyTo(constraintLayout);
}
}
});
}
}
動(dòng)態(tài)添加第一個(gè)Button,效果如圖:
動(dòng)態(tài)添加第二個(gè)Button惦辛,效果如圖:
從圖上可以看到劳秋,第二個(gè)按鈕添加后,第一個(gè)按鈕的約束將不起作用胖齐?有些疑問(wèn)玻淑,那么再添加第三個(gè)按鈕嘗試,效果如圖:
這個(gè)意思很明顯了呀伙,在添加了新的按鈕以后补履,原來(lái)的約束將不起作用,都會(huì)修改為新的約束剿另。那也就是說(shuō)connect函數(shù)在Constraint的LEFT,RIGHT(START,END),TOP,BOTTOM等4個(gè)方向分別只能使用一次箫锤,舊的約束會(huì)被新的約束覆蓋。
PS:經(jīng)同學(xué)提醒雨女,將new的button的id打印出來(lái)發(fā)現(xiàn)是一樣的谚攒,如果先給Button使用setId方法設(shè)置了不同的Id,結(jié)果就沒(méi)有問(wèn)題了氛堕。
PS:只要傳入正確的id馏臭,即使是靜態(tài)的布局中的控件,也可以通過(guò)ConstraintSet調(diào)整約束
(附加一個(gè):如何優(yōu)雅的為Java代碼中新建的控件添加id:
首先在values文件夾中建立一個(gè)xml文件岔擂,我們把它命名為m_id.xml:
然后如圖添加:
在代碼中使用setId(R.id.命名的值)位喂,就可以使用這些id了。)
ConstraintSet動(dòng)畫
動(dòng)畫是最有趣的部分乱灵,這里做的很簡(jiǎn)單塑崖,但是也意味著動(dòng)畫的擴(kuò)展性很高,這個(gè)部分值得一學(xué):
首先是布局代碼:
主界面的代碼痛倚,activity_main.xml:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.zjt.constraintsettransition.MainActivity"
android:id="@+id/contentPanel">
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="動(dòng)畫"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintHorizontal_bias="0.028"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toStartOf="@+id/button3"
android:layout_marginEnd="8dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintHorizontal_bias="0.261"
app:layout_constraintVertical_bias="0.498" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toStartOf="@+id/button4"
android:layout_marginEnd="52dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintVertical_bias="0.498" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" />
</android.support.constraint.ConstraintLayout>
用來(lái)替換的界面的代碼:activity2.xml规婆,要特別注意的就是這兩個(gè)布局的對(duì)應(yīng)的id要一致,否則是無(wú)法完成動(dòng)畫效果的
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.zjt.constraintsettransition.MainActivity"
android:id="@+id/contentPanel">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="動(dòng)畫"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
app:layout_constraintHorizontal_bias="0.028"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="@+id/button2"
android:layout_width="87dp"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="80dp"
app:layout_constraintHorizontal_bias="0.501" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
android:layout_marginTop="80dp"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/button3"
app:layout_constraintVertical_bias="0.376" />
</android.support.constraint.ConstraintLayout>
主程序代碼:MainActivity.java
package com.example.zjt.constraintsettransition;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.transition.TransitionManager;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private ConstraintSet first,second;
private ConstraintLayout firstLayout;
private Button start;
boolean isFirst=true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
first=new ConstraintSet();
second=new ConstraintSet();
firstLayout=findViewById(R.id.contentPanel);
start=findViewById(R.id.start);
first.clone(firstLayout);
second.clone(this,R.layout.activity2);
start.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onClick(View view) {
if(isFirst){
isFirst=false;
TransitionManager.beginDelayedTransition(firstLayout);// 動(dòng)畫效果
second.applyTo(firstLayout);
}else {
isFirst=true;
TransitionManager.beginDelayedTransition(firstLayout);
first.applyTo(firstLayout);
}
}
});
}
}
效果如圖:
在整個(gè)ConstraintLayout的使用過(guò)程中蝉稳,遇到了很多的問(wèn)題抒蚜,問(wèn)題不在與xml界面的調(diào)整,而在于代碼中ConstraintSet的使用耘戚,最無(wú)法理解的地方在上面的例子就有嗡髓,就是生成了新的Button后原來(lái)的Button也會(huì)受到影響,這個(gè)地方如果有什么想法歡迎與我聯(lián)系收津。動(dòng)畫的擴(kuò)展性就很強(qiáng)了饿这,這里只是做一個(gè)簡(jiǎn)單的動(dòng)畫演示浊伙,實(shí)際上可以完成更多的效果,這個(gè)就需要再研究下了长捧。另外嚣鄙,ConstraintLayout還有一些問(wèn)題,就是如果使某個(gè)控件的一部分處于屏幕內(nèi)串结,一部分處于屏幕外哑子,原先使用relativelayout就很好處理了,在代碼中的Layoutparams進(jìn)行位置的處理皆可以肌割,而使用ConstraintLayout這個(gè)地方就不好完成卧蜓,目前我沒(méi)有解決辦法。(解決辦法:在使用connect函數(shù)時(shí)設(shè)置好margin即可)總的來(lái)說(shuō)声功,ConstraintLayout使得我們布局更加靈活烦却,同時(shí)也存在一些問(wèn)題,有待解決先巴。