ConstraintLayout動(dòng)態(tài)添加View负间,改變約束

DEMO源碼

使用的ConstraintLayout版本

implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

如果不使用androidx的話可以使用下面的版本

implementation 'com.android.support.constraint:constraint-layout:1.1.3'

注意:使用不同的ConstraintLayout版本可能會(huì)有坑踱阿,如果在使用過(guò)程中發(fā)現(xiàn)實(shí)現(xiàn)不了想要添加的約束,可以嘗試改變ConstraintLayout的版本如上所示歼冰。

1. 動(dòng)態(tài)添加View

第一種情況:所有的View都是動(dòng)態(tài)添加

舉個(gè)例子

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/clRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/ivLeft"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_lake"
        app:layout_constraintDimensionRatio="h,16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvRight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="@string/lake_tahoe_title"
        android:textSize="30sp"
        app:layout_constraintLeft_toRightOf="@+id/ivLeft"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tvBottom"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="24dp"
        android:layout_marginEnd="8dp"
        android:text="@string/lake_discription"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/ivLeft" />

</androidx.constraintlayout.widget.ConstraintLayout>

初始布局.jpg

上面的布局文件中呈現(xiàn)的效果如圖所示,接下來(lái)我們用代碼的方式動(dòng)態(tài)添加View,實(shí)現(xiàn)上面的效果粤咪。

首先在res/values文件夾下新建一個(gè)ids.xml,在ids.xml中聲明我們要添加的View的控件id。

ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="clRoot" type="id" />
    <item name="ivLeft" type="id" />
    <item name="tvRight" type="id" />
    <item name="tvBottom" type="id" />
</resources>

然后開(kāi)始寫(xiě)代碼

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    addViewUseLayoutParams()
}

使用ConstraintLayout.LayoutParams

    private fun addViewUseLayoutParams() {
        val constraintLayout = ConstraintLayout(this)
        constraintLayout.id = R.id.clRoot
        constraintLayout.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        //先設(shè)置根布局
        setContentView(constraintLayout)

        val ivLeft = ImageView(this)
        ivLeft.id = R.id.ivLeft
        ivLeft.scaleType = ImageView.ScaleType.CENTER_CROP
        ivLeft.setImageResource(R.drawable.ic_lake)

        val ivLeftLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            ScreenUtil.dpToPx(this, 100), 0
        )
        ivLeftLayoutParams.leftToLeft = R.id.clRoot
        ivLeftLayoutParams.marginStart = ScreenUtil.dpToPx(this, 8)
        ivLeftLayoutParams.topToTop = R.id.clRoot
        ivLeftLayoutParams.topMargin = ScreenUtil.dpToPx(this, 8)
        ivLeftLayoutParams.dimensionRatio = "h,16:9"

        ivLeft.layoutParams = ivLeftLayoutParams

        val tvRight = TextView(this)
        tvRight.id = R.id.tvRight
        tvRight.text = getString(R.string.lake_tahoe_title)
        tvRight.textSize = 30F
        val tvRightLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            ConstraintLayout.LayoutParams.WRAP_CONTENT,
            ConstraintLayout.LayoutParams.WRAP_CONTENT
        )
        tvRightLayoutParams.startToEnd = R.id.ivLeft
        tvRightLayoutParams.topToTop = R.id.clRoot
        tvRightLayoutParams.marginStart = ScreenUtil.dpToPx(this, 16)
        tvRightLayoutParams.topMargin = ScreenUtil.dpToPx(this, 16)

        tvRight.layoutParams = tvRightLayoutParams


        val tvBottom = TextView(this)
        tvBottom.id = R.id.tvBottom
        tvBottom.text = getString(R.string.lake_discription)
        val tvBottomLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            0,
            ConstraintLayout.LayoutParams.WRAP_CONTENT
        )
        tvBottomLayoutParams.startToStart = R.id.clRoot
        tvBottomLayoutParams.marginStart = ScreenUtil.dpToPx(this, 8)

        tvBottomLayoutParams.endToEnd = R.id.clRoot
        tvBottomLayoutParams.marginEnd = ScreenUtil.dpToPx(this, 8)

        tvBottomLayoutParams.topToBottom = R.id.ivLeft
        tvBottomLayoutParams.topMargin = ScreenUtil.dpToPx(this, 24)

        tvBottom.layoutParams = tvBottomLayoutParams

        constraintLayout.addView(ivLeft)
        constraintLayout.addView(tvRight)
        constraintLayout.addView(tvBottom)

    }

效果和上面是一樣的渴杆,就不截圖了寥枝。在上面的方法中宪塔,我們是使用ConstraintLayout.LayoutParams來(lái)實(shí)現(xiàn)添加view并指定約束的。接下來(lái)囊拜,我們換一種方式某筐,使用ConstraintSet來(lái)添加view并指定約束。關(guān)于ConstraintSet的介紹請(qǐng)參考 ConstraintSet冠跷。

使用ConstraintSet

    private fun addViewUseConstraintSet() {
        val constraintLayout = ConstraintLayout(this)
        constraintLayout.id = R.id.clRoot
        constraintLayout.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        //先設(shè)置根布局
        setContentView(constraintLayout)

        val constraintSet = ConstraintSet()

        val ivLeft = ImageView(this)
        ivLeft.id = R.id.ivLeft
        ivLeft.scaleType = ImageView.ScaleType.CENTER_CROP
        ivLeft.setImageResource(R.drawable.ic_lake)

        constraintSet.constrainWidth(R.id.ivLeft, ScreenUtil.dpToPx(this, 100))
        constraintSet.constrainHeight(R.id.ivLeft, 0)
        constraintSet.setDimensionRatio(R.id.ivLeft, "h,16:9")

        //layout_constraintTop_toTopOf
        constraintSet.connect(
            R.id.ivLeft, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP,
            ScreenUtil.dpToPx(this, 16)
        )

        constraintSet.connect(
            R.id.ivLeft, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START,
            ScreenUtil.dpToPx(this, 16)
        )

        val tvRight = TextView(this)
        tvRight.id = R.id.tvRight
        tvRight.text = getString(R.string.lake_tahoe_title)
        tvRight.textSize = 30F

        constraintSet.constrainHeight(R.id.tvRight, ConstraintLayout.LayoutParams.WRAP_CONTENT)
        constraintSet.constrainWidth(R.id.tvRight, ConstraintLayout.LayoutParams.WRAP_CONTENT)
        
        constraintSet.connect(
            R.id.tvRight, ConstraintSet.START, R.id.ivLeft, ConstraintSet.END,
            ScreenUtil.dpToPx(this, 16)
        )
        constraintSet.connect(
            R.id.tvRight, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP,
            ScreenUtil.dpToPx(this, 16)
        )

        val tvBottom = TextView(this)
        tvBottom.id = R.id.tvBottom
        tvBottom.text = getString(R.string.lake_discription)
        //設(shè)置高度
        constraintSet.constrainHeight(R.id.tvBottom, ConstraintLayout.LayoutParams.WRAP_CONTENT)

        constraintSet.connect(
            R.id.tvBottom, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START,
            ScreenUtil.dpToPx(this, 8)
        )

        constraintSet.connect(
            R.id.tvBottom, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END,
            ScreenUtil.dpToPx(this, 8)
        )

        constraintSet.connect(
            R.id.tvBottom, ConstraintSet.TOP, R.id.ivLeft, ConstraintSet.BOTTOM,
            ScreenUtil.dpToPx(this, 24)
        )

        constraintLayout.addView(ivLeft)
        constraintLayout.addView(tvRight)
        constraintLayout.addView(tvBottom)

        TransitionManager.beginDelayedTransition(constraintLayout)

        constraintSet.applyTo(constraintLayout)
    }

效果也是一樣的南誊。

第二種情況,動(dòng)態(tài)添加個(gè)別View,感覺(jué)這種場(chǎng)景應(yīng)該不多

在上面的例子中蜜托,我們假設(shè)tvBottom已經(jī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"
    android:id="@+id/clRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tvBottom"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="24dp"
        android:layout_marginEnd="8dp"
        android:text="@string/lake_discription"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

31573289245_.pic.jpg

接下來(lái),我們動(dòng)態(tài)的把ivLefttvRight 添加到布局中去盗冷,實(shí)現(xiàn)和第一個(gè)例子中同樣的效果怠苔。

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //布局文件別忘了
        setContentView(R.layout.activity_main)
        addPartView()
    }
    private fun addPartView() {
        val ivLeft = ImageView(this)
        ivLeft.id = R.id.ivLeft
        ivLeft.scaleType = ImageView.ScaleType.CENTER_CROP
        ivLeft.setImageResource(R.drawable.ic_lake)

        val ivLeftLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            ScreenUtil.dpToPx(this, 100), 0
        )
        ivLeftLayoutParams.dimensionRatio = "h,16:9"
        ivLeftLayoutParams.topMargin = ScreenUtil.dpToPx(this, 16)
        ivLeftLayoutParams.marginStart = ScreenUtil.dpToPx(this, 16)
        ivLeftLayoutParams.leftToLeft = R.id.clRoot
        ivLeftLayoutParams.topToTop = R.id.clRoot

        ivLeft.layoutParams = ivLeftLayoutParams

        val tvRight = TextView(this)
        tvRight.id = R.id.tvRight
        tvRight.text = getString(R.string.lake_tahoe_title)
        tvRight.textSize = 30F
        val tvRightLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            ConstraintLayout.LayoutParams.WRAP_CONTENT,
            ConstraintLayout.LayoutParams.WRAP_CONTENT
        )
        tvRightLayoutParams.startToEnd = R.id.ivLeft
        tvRightLayoutParams.topToTop = R.id.clRoot
        tvRightLayoutParams.marginStart = ScreenUtil.dpToPx(this, 16)
        tvRightLayoutParams.topMargin = ScreenUtil.dpToPx(this, 16)

        tvRight.layoutParams = tvRightLayoutParams


        val tvBottomLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            0,
            ConstraintLayout.LayoutParams.WRAP_CONTENT
        )
        tvBottomLayoutParams.startToStart = R.id.clRoot
        tvBottomLayoutParams.marginStart = ScreenUtil.dpToPx(this, 8)

        tvBottomLayoutParams.endToEnd = R.id.clRoot
        tvBottomLayoutParams.marginEnd = ScreenUtil.dpToPx(this, 8)

        tvBottomLayoutParams.topToBottom = R.id.ivLeft
        tvBottomLayoutParams.topMargin = ScreenUtil.dpToPx(this, 24)

        tvBottomLayoutParams.bottomMargin = ScreenUtil.dpToPx(this, 8)

        //重新為布局中已經(jīng)存在的tvBottom設(shè)置新的布局參數(shù)。
        tvBottom.layoutParams = tvBottomLayoutParams

        clRoot.addView(ivLeft)
        clRoot.addView(tvRight)

    }

這種方式要注意重新為布局中已經(jīng)存在的控件設(shè)置新的布局參數(shù)仪糖。

動(dòng)態(tài)改變約束

如果我們想動(dòng)態(tài)改變布局中的View的約束該怎么做呢柑司?比如我們想把上面的布局樣式改成下圖所示。


Screenshot_1559374001.png

其實(shí)锅劝,在上面我們已經(jīng)給tvBottom動(dòng)態(tài)改變約束了攒驰,就是給View重新設(shè)置布局參數(shù)就好了。

給View重新設(shè)置布局參數(shù)

下面我們?cè)诖a中故爵,重新改變View的布局參數(shù)玻粪。

    private fun changeLayoutParams() {
        val ivLeftLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            0, 0
        )
        ivLeftLayoutParams.leftMargin = ScreenUtil.dpToPx(this, 16)
        ivLeftLayoutParams.rightMargin = ScreenUtil.dpToPx(this, 16)
        ivLeftLayoutParams.topMargin = ScreenUtil.dpToPx(this, 16)
        ivLeftLayoutParams.leftToLeft = R.id.clRoot
        ivLeftLayoutParams.rightToRight = R.id.clRoot
        ivLeftLayoutParams.dimensionRatio = "h,16:9"
        ivLeftLayoutParams.topToTop = R.id.clRoot

        //修改布局參數(shù)
        ivLeft.layoutParams = ivLeftLayoutParams

        val tvRightLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            ConstraintLayout.LayoutParams.WRAP_CONTENT,
            ConstraintLayout.LayoutParams.WRAP_CONTENT
        )
        tvRightLayoutParams.leftToLeft = R.id.clRoot
        tvRightLayoutParams.topToBottom = R.id.ivLeft
        tvRightLayoutParams.marginStart = ScreenUtil.dpToPx(this, 16)
        tvRightLayoutParams.topMargin = ScreenUtil.dpToPx(this, 16)

        tvRight.layoutParams = tvRightLayoutParams


        val tvBottomLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
            0,
            ConstraintLayout.LayoutParams.WRAP_CONTENT
        )
        tvBottomLayoutParams.startToStart = R.id.clRoot
        tvBottomLayoutParams.marginStart = ScreenUtil.dpToPx(this, 8)

        tvBottomLayoutParams.endToEnd = R.id.clRoot
        tvBottomLayoutParams.marginEnd = ScreenUtil.dpToPx(this, 8)

        tvBottomLayoutParams.topToBottom = R.id.tvRight
        tvBottomLayoutParams.topMargin = ScreenUtil.dpToPx(this, 24)

        tvBottomLayoutParams.bottomMargin = ScreenUtil.dpToPx(this, 8)

        tvBottom.layoutParams = tvBottomLayoutParams
    }

改變后的效果就不貼了。

使用ConstraintSet 動(dòng)態(tài)修改約束

使用ConstraintSet 動(dòng)態(tài)修改約束分四步诬垂。

  1. 首先要聲明一下ConstraintSet對(duì)象
  val constraintSet = ConstraintSet()
  1. 復(fù)制一份現(xiàn)有的約束關(guān)系劲室,這一步不是必須的。
//從一個(gè)constraintLayout中復(fù)制約束
set.clone(constraintLayout: ConstraintLayout);
//從一個(gè)ConstraintSet中復(fù)制約束
set.clone(set: ConstraintSet);
//從一個(gè)布局文件中復(fù)制約束
set.clone(context: Context, constraintLayoutId: Int);

如果說(shuō)你要改變布局中某些控件的約束结窘,但是還要保存其他控件的約束關(guān)系很洋,那么你就需要從已有的根布局中復(fù)制一份約束,然后只更改哪些需要改變的控件的約束關(guān)系隧枫。

注意復(fù)制約束關(guān)系的時(shí)候喉磁,布局中的每個(gè)控件必都有id,不然會(huì)報(bào)下面的錯(cuò)誤官脓。

 java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet

  1. 設(shè)置控件之間的約束
  2. 應(yīng)用新的約束协怒。在應(yīng)用約束的時(shí)候,為了讓約束改變的時(shí)候不是那么突兀卑笨,我們可以設(shè)置一個(gè)動(dòng)畫(huà)孕暇,來(lái)讓約束改變平滑一點(diǎn)。
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_dynamic_add_view)
      
        ivLeft.setOnClickListener {
            changeConstraintSet()
        }
    }
    private fun changeConstraintSet() {
        val constraintSet = ConstraintSet()
        //從根布局中克隆約束參數(shù)
        constraintSet.clone(clRoot)

        //清空控件原有的約束
        constraintSet.clear(R.id.ivLeft)
        constraintSet.clear(R.id.tvRight)
        constraintSet.clear(R.id.tvBottom)

        constraintSet.constrainWidth(R.id.ivLeft, 0)
        constraintSet.constrainHeight(R.id.ivLeft, 0)
        //設(shè)置ivLeft頂部和父布局頂部對(duì)齊
        constraintSet.connect(
            R.id.ivLeft, ConstraintSet.TOP, R.id.clRoot, ConstraintSet.TOP,
            ScreenUtil.dpToPx(this, 16)
        )
        constraintSet.connect(
            R.id.ivLeft, ConstraintSet.START, R.id.clRoot, ConstraintSet.START,
            ScreenUtil.dpToPx(this, 16)
        )
        constraintSet.connect(
            R.id.ivLeft, ConstraintSet.END, R.id.clRoot, ConstraintSet.END,
            ScreenUtil.dpToPx(this, 16)
        )
        //設(shè)置寬高比
        constraintSet.setDimensionRatio(R.id.ivLeft, "h,16:9")


        constraintSet.constrainWidth(R.id.tvRight, ConstraintLayout.LayoutParams.WRAP_CONTENT)
        constraintSet.constrainHeight(R.id.tvRight, ConstraintLayout.LayoutParams.WRAP_CONTENT)

        constraintSet.connect(
            R.id.tvRight, ConstraintSet.TOP, R.id.ivLeft, ConstraintSet.BOTTOM,
            ScreenUtil.dpToPx(this, 24)
        )

        constraintSet.connect(
            R.id.tvRight, ConstraintSet.START, R.id.clRoot, ConstraintSet.START,
            ScreenUtil.dpToPx(this, 8)
        )

        constraintSet.constrainHeight(R.id.tvBottom, ConstraintLayout.LayoutParams.WRAP_CONTENT)

        constraintSet.connect(
            R.id.tvBottom, ConstraintSet.START, R.id.clRoot, ConstraintSet.START,
            ScreenUtil.dpToPx(this, 8)
        )
        constraintSet.connect(
            R.id.tvBottom, ConstraintSet.END, R.id.clRoot, ConstraintSet.END,
            ScreenUtil.dpToPx(this, 8)
        )

        constraintSet.connect(
            R.id.tvBottom, ConstraintSet.TOP, R.id.tvRight, ConstraintSet.BOTTOM,
            ScreenUtil.dpToPx(this, 24)
        )

        constraintSet.applyTo(clRoot)
        //設(shè)置一個(gè)動(dòng)畫(huà)效果,讓約束改變平滑一點(diǎn)妖滔,這一步不是必須的
        TransitionManager.beginDelayedTransition(clRoot)
    }

效果如下所示

1559465809770862.gif

遇到的一個(gè)問(wèn)題

在測(cè)試的時(shí)候派草,我想添加一個(gè)水平方向上的Guideline,讓它在父布局豎直方向比例為0.4的地方铛楣,然后在Guideline之上添加一個(gè)ImageView。代碼如下

    private fun addGuideLine() {
        val constraintLayout = ConstraintLayout(this)
        constraintLayout.id = R.id.clRoot
        constraintLayout.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT)
        //先設(shè)置根布局
        setContentView(constraintLayout)

        val guideline = Guideline(this)
        guideline.id = R.id.guideline

        val guideLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT)
        guideLayoutParams.guidePercent = 0.4f
        guideLayoutParams.topToTop = R.id.clRoot
        guideLayoutParams.bottomToBottom = R.id.clRoot
        //注意
        guideLayoutParams.orientation = ConstraintLayout.LayoutParams.VERTICAL

        guideline.layoutParams = guideLayoutParams

        constraintLayout.addView(guideline)

        val ivLeft = ImageView(this)
        ivLeft.id = R.id.ivLeft
        ivLeft.scaleType = ImageView.ScaleType.CENTER_CROP
        ivLeft.setImageResource(R.drawable.lake)

        val ivLeftLayoutParams: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams(
                0, 0)
        ivLeftLayoutParams.dimensionRatio = "h,16:9"
        ivLeftLayoutParams.bottomToTop = R.id.guideline
        ivLeftLayoutParams.startToStart = R.id.clRoot
        ivLeftLayoutParams.endToEnd = R.id.clRoot

        ivLeft.layoutParams = ivLeftLayoutParams

        constraintLayout.addView(ivLeft)
    }

在測(cè)試的時(shí)候報(bào)了一個(gè)錯(cuò)誤

java.lang.AssertionError: TOP at android.support.constraint.solver.widgets.Guideline.getAnchor(Guideline.java:159)


折騰了半天艺普,發(fā)現(xiàn)是Guideline的方向?qū)戝e(cuò)了簸州。

 guideLayoutParams.orientation = ConstraintLayout.LayoutParams.VERTICAL

正確的寫(xiě)法

 guideLayoutParams.orientation = ConstraintLayout.LayoutParams.HORIZONTAL

如果Guideline的方向?qū)戝e(cuò)了,會(huì)導(dǎo)致依賴Guideline的方向的控件的約束無(wú)法正確指定歧譬,所以會(huì)報(bào)錯(cuò)岸浑。如果遇到類似的問(wèn)題請(qǐng)仔細(xì)檢查,是否正確的設(shè)置了約束瑰步。

參考鏈接

  1. Android開(kāi)發(fā)筆記(一百四十九)約束布局ConstraintLayout
  2. ConstraintLayout 之 ConstraintSet 動(dòng)態(tài)修改約束(動(dòng)畫(huà))
  3. ConstraintSet
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末矢洲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缩焦,更是在濱河造成了極大的恐慌读虏,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袁滥,死亡現(xiàn)場(chǎng)離奇詭異盖桥,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)题翻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)揩徊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嵌赠,你說(shuō)我怎么就攤上這事塑荒。” “怎么了姜挺?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵齿税,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我初家,道長(zhǎng)偎窘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任溜在,我火速辦了婚禮陌知,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掖肋。我一直安慰自己仆葡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著沿盅,像睡著了一般把篓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腰涧,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天韧掩,我揣著相機(jī)與錄音,去河邊找鬼窖铡。 笑死疗锐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的费彼。 我是一名探鬼主播滑臊,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼箍铲!你這毒婦竟也來(lái)了雇卷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颠猴,失蹤者是張志新(化名)和其女友劉穎关划,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體芙粱,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祭玉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了春畔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脱货。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖律姨,靈堂內(nèi)的尸體忽然破棺而出振峻,到底是詐尸還是另有隱情,我是刑警寧澤择份,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布扣孟,位于F島的核電站,受9級(jí)特大地震影響荣赶,放射性物質(zhì)發(fā)生泄漏凤价。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一拔创、第九天 我趴在偏房一處隱蔽的房頂上張望利诺。 院中可真熱鬧,春花似錦剩燥、人聲如沸慢逾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)侣滩。三九已至口注,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間君珠,已是汗流浹背寝志。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留策添,地道東北人澈段。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舰攒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悔醋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容