ConstraintLayout: kısıtlamaları program aracılığıyla değiştirme


110

Ben yardıma ihtiyacım ConstraintSet. Amacım, görünümün koddaki kısıtlamalarını değiştirmek, ancak bunu nasıl doğru yapacağımı çözemiyorum.

4 TextViews ve bir var ImageView. ImageViewURL’lerden birine kısıtlamalar koymam gerekiyor TextView.

check_answer4 = (TextView) findViewById(R.id.check_answer4);
check_answer1 = (TextView) findViewById(R.id.check_answer1);
check_answer2 = (TextView) findViewById(R.id.check_answer2);
check_answer3 = (TextView) findViewById(R.id.check_answer3);

correct_answer_icon = (ImageView) findViewById(R.id.correct_answer_icon);

1 cevap doğruysa, ben set kısıtlamaları gerekir ImageViewiçin

app:layout_constraintRight_toRightOf="@+id/check_answer1"
app:layout_constraintTop_toTopOf="@+id/check_answer1"

2 cevap doğruysa, ben set kısıtlamaları gerekir ImageViewiçin

app:layout_constraintRight_toRightOf="@+id/check_answer2"
app:layout_constraintTop_toTopOf="@+id/check_answer2"

Ve bunun gibi.


bunun için kısıtlamayı dinamik olarak değiştirmeniz gerekir.
Shweta Chauhan

4
@shweta Tam olarak bunu soruyorum, dinamik olarak nasıl yapılır?
Big Coach

alma. cevabınızı yayınlamak.
Shweta Chauhan

Yanıtlar:


185
  1. Görüntü görünümünün kısıtlamalarını şu şekilde ayarlamak için:

     app:layout_constraintRight_toRightOf="@+id/check_answer1"
     app:layout_constraintTop_toTopOf="@+id/check_answer1"
    

    kullanım:

     ConstraintLayout constraintLayout = findViewById(R.id.parent_layout);
     ConstraintSet constraintSet = new ConstraintSet();
     constraintSet.clone(constraintLayout);
     constraintSet.connect(R.id.imageView,ConstraintSet.RIGHT,R.id.check_answer1,ConstraintSet.RIGHT,0);
     constraintSet.connect(R.id.imageView,ConstraintSet.TOP,R.id.check_answer1,ConstraintSet.TOP,0);
     constraintSet.applyTo(constraintLayout);
    
  2. Görüntü görünümünün kısıtlamalarını şu şekilde ayarlamak için:

     app:layout_constraintRight_toRightOf="@+id/check_answer2"
     app:layout_constraintTop_toTopOf="@+id/check_answer2"
    

    kullanım:

     ConstraintLayout constraintLayout = findViewById(R.id.parent_layout);
     ConstraintSet constraintSet = new ConstraintSet();
     constraintSet.clone(constraintLayout); 
     constraintSet.connect(R.id.imageView,ConstraintSet.RIGHT,R.id.check_answer2,ConstraintSet.RIGHT,0);      
     constraintSet.connect(R.id.imageView,ConstraintSet.TOP,R.id.check_answer2,ConstraintSet.TOP,0);
     constraintSet.applyTo(constraintLayout);
    

3
constraintSet.clone (constraintLayout); bu satırda, constraintLayout ebeveyn düzeni mi?
Reejesh PK

5
@Pang .clone(constraintLayout)bu değişken nedir ve nereden bulabilirim?
leonheess

8
@ReejeshPK @ MiXT4PE Evet, ana sayfa düzeni, yaniConstraintLayout constraintLayout = findViewById(R.id.parent_layout);
Muhammad Muzammil

1
@leonheess Bunun, Kısıtlama Düzeni Görünüm Grubunuza referans veren bir değişken olması gerektiğini düşünüyorum
Felix Favor Chinemerem

81

Çalışma zamanı sırasında kısıtlamaları değiştirmek istediğimizi varsayalım, düğme1, tıklandığında button2 ile hizalanacak:

görüntü açıklamasını buraya girin

Ardından, bu düzene sahip olmak:

<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"
    android:id="@+id/root"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">


    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"
        app:layout_constraintTop_toTopOf="@+id/button3"
        app:layout_constraintBottom_toBottomOf="@+id/button3"
        app:layout_constraintStart_toEndOf="@+id/button3"
        android:layout_marginStart="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginEnd="0dp" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:text="Button 2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginEnd="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="8dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintVertical_bias="0.5" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:text="Button 3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="8dp"
        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"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintVertical_bias="0.223" />
</android.support.constraint.ConstraintLayout>

Aşağıdakileri yapabiliriz:


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button1.setOnClickListener {
            val params = button1.layoutParams as ConstraintLayout.LayoutParams
            params.leftToRight = button2.id
            params.topToTop = button2.id
            params.bottomToBottom = button2.id
            button1.requestLayout()
        }
    }


Arkadaşım, kodunuzu alamıyorum .. nedir layoutParamsve val? Bu Java bile mi?
leonheess

43
Efendim, bu kotlin programlama dili. Java eşdeğeriConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) button1.getLayoutParams();
azizbekian

1
Sanırım
button1.layoutParams

1
@sumitsonawane, buna gerek yok, çünkü o örneği mutasyona uğratıyoruz ve ondan sonra gerçekleştirdiğimiz button1.requestLayout()ve daha sonra mutasyona uğrattığımız örneğini inceleyeceğiz LayoutParams.
azizbekian

2
@azizbekian, evet, benim için son çözüm requestLayout()çağrının yerine geçip setLayoutParams()sonra işe yarıyor. Sadece layoutParamsdüzeni değiştirmek ve istemek, hile yapmıyor gibi görünüyor.
qwertyfinger

2

Kotlin'de ConstraintSet, Kotlin'de dsl'den yararlanmak ve daha okunabilir bir kod üretmek için sınıfı genişletebilir ve bazı yöntemler ekleyebilirsiniz. Bunun gibi

class KotlinConstraintSet : ConstraintSet() {

    companion object {
        inline fun buildConstraintSet(block:KotlinConstraintSet.()->Unit) =
            KotlinConstraintSet().apply(block)
    }
    //add this if you plan on using the margin param in ConstraintSet.connect
    var margin: Int? = null
        get() {
            val result = field
            margin = null //reset it to work with other constraints
            return result
        }

    inline infix fun Unit.and(other: Int) = other // just to join two functions

    inline infix fun Int.topToBottomOf(bottom: Int) =
        margin?.let {
            connect(this, TOP, bottom, BOTTOM, it)
        } ?: connect(this, TOP, bottom, BOTTOM)

    inline fun margin(margin: Int) {
        this.margin = margin
    }

    inline infix fun Int.bottomToBottomOf(bottom: Int) =
        margin?.let {
            connect(this, BOTTOM, bottom, BOTTOM, it)
        } ?: connect(this, BOTTOM, bottom, BOTTOM)

    inline infix fun Int.topToTopOf(top: Int) =
        margin?.let {
            connect(this, TOP, top, TOP, it)
        } ?: connect(this, TOP, top, TOP)

    inline infix fun Int.startToEndOf(end: Int) =
        margin?.let {
            connect(this, START, end, END, it)
        } ?: connect(this, START, end, END)

            ...
    //TODO generate other functions depending on your needs

    infix fun Int.clear(constraint: Constraints) =
        when (constraint) {
            Constraints.TOP -> clear(this, TOP)
            Constraints.BOTTOM -> clear(this, BOTTOM)
            Constraints.END -> clear(this, END)
            Constraints.START -> clear(this, START)
        }

    //inline infix fun clearTopCon
    inline infix fun appliesTo(constraintLayout: ConstraintLayout) =
        applyTo(constraintLayout)

    inline infix fun clones(constraintLayout: ConstraintLayout) =
        clone(constraintLayout)

    inline fun constraint(view: Int, block: Int.() -> Unit) =
        view.apply(block)
}

enum class Constraints {
    TOP, BOTTOM, START, END //you could add other values to use with the clear fun like LEFT
}

Ve bunu böyle kullan

        buildConstraintSet {
            this clones yourConstraintLayout
            constraint(R.id.view1) {
                margin(value:Int) and this topToBottomOf R.id.view2
                margin(30) and this bottomToBottomOf ConstraintSet.PARENT_ID
            }
            constraint(R.id.view2) {
                this clear Constraints.BOTTOM
                margin(0) and this topToTopOf R.id.topGuide
            }
            constraint(R.id.view4) {
                this topToTopOf R.id.view2
                this bottomToBottomOf R.id.view3
                this startToEndOf R.id.view2
            }
            //or you could simply do
            R.id.view1 startToEndOf R.view2
            R.id.view1 toptToBottomOf R.view3
            R.id.view3 bottomtToBottomOf R.view2
            R.id.view3 clear Constraints.END

            // and finally call applyTo()
            this appliesTo yourConstraintLayout
        }

2

Cevabımın çok geç olduğunu biliyorum, yine de buraya uğramanın diğerlerine çok yardımcı olacağına eminim. Bu makale benim değil, ancak birkaç değişiklik yaptım, söylendiğine göre, makalenin tamamına buradan göz atmalısınız.

Kısıtlama Setleri

Java kodunda kısıt kümeleriyle çalışmanın anahtarı ConstraintSet sınıfıdır. Bu sınıf, bir ConstraintLayout örneğine kısıtlama oluşturma, yapılandırma ve uygulama gibi görevlere izin veren bir dizi yöntem içerir. Ek olarak, bir ConstraintLayout örneğinin mevcut kısıtlamaları bir ConstraintSet nesnesine kopyalanabilir ve aynı kısıtlamaları diğer düzenlere (değişiklik yapılarak veya değiştirilmeden) uygulamak için kullanılabilir.

Herhangi bir Java nesnesi gibi bir ConstraintSet örneği oluşturulur:

ConstraintSet set = new ConstraintSet();

Bir kısıtlama kümesi oluşturulduktan sonra, çok çeşitli görevleri gerçekleştirmek için örneklerde yöntemler çağrılabilir. Aşağıdaki kod, bir Düğme görünümünün sol tarafının, 70dp'lik bir marjla bir EditText görünümünün sağ tarafına bağlandığı bir kısıtlama kümesini yapılandırır:

set.connect(button1.getId(), ConstraintSet.LEFT, 
        editText1.getId(), ConstraintSet.RIGHT, 70);

Bir Düzene Kısıtlama Uygulama Kısıtlama kümesi yapılandırıldıktan sonra, yürürlüğe girmeden önce bir ConstraintLayout örneğine uygulanmalıdır. Bir kısıtlama kümesi, applyTo () yöntemine yapılan bir çağrı yoluyla, ayarların uygulanacağı mizanpaj nesnesine bir başvurudan geçerek uygulanır:

set.applyTo(myLayout);

ConstraintSetAPI ile yapabileceğiniz çok daha fazla şey var, Yatay ve dikey önyargı ayarlama, yatay ve dikey merkezleme, Zincirleri değiştirme ve çok daha fazlası.

Gerçekten güzel kitap.

Yine, bu sadece bir uyarlamadır.


1

Azizbekyan'ın cevabına ek olarak iki şeye işaret etmeme izin verin:

  1. Sol / sağ işe yaramadıysa, şu şekilde başla / bitir:

params.startToEnd = button2.id

  1. Bir kısıtlamayı kaldırmak istiyorsanız, UNSET işaretini şu şekilde kullanın:

params.startToEnd = ConstraintLayout.LayoutParams.UNSET

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.