Программное удаление / добавление ограничения в ConstraintLayout

Я хочу удалить и добавить ограничение программно в зависимости от некоторого условия. Вот скриншоты:

Кнопка создания объявления имеет верхнее ограничение

и я хочу удалить его вот так, но в коде:

вот кнопка с удаленным ограничением сверху

поэтому тот же эффект, который нужно достичь программно

и вот код, который я пробовал:

    if (advertisements.size() > 0) { //my own condition
        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) btnCreateAd.getLayoutParams();
        layoutParams.topToBottom = R.id.imvEmpty; //the imageview that is in center of the view
        btnCreateAd.setLayoutParams(layoutParams);
        recyclerView.setVisibility(View.VISIBLE);
        txvMyAdEmptyText.setVisibility(View.GONE);
        imvEmpty.setVisibility(View.GONE);
        adapter.setList(advertisements);
        adapter.notifyDataSetChanged();
    } else {
        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) btnCreateAd.getLayoutParams();
        layoutParams.topToBottom = -1; //here i am trying to remove top constraint but it doesn't work
        btnCreateAd.setLayoutParams(layoutParams);

        recyclerView.setVisibility(View.GONE);
        txvMyAdEmptyText.setVisibility(View.VISIBLE);
        imvEmpty.setVisibility(View.VISIBLE);
        adapter.setList(new ArrayList<Advertisement>());
    }
    mConstraintView.invalidate(); //this is my constraint view

ИЗМЕНИТЬ

Я также пробовал использовать ConstraintSet, но результат был даже другим каким-то образом мой RecyclerView (который установлен на границах родительского представления) исчезал

 ConstraintSet set = new ConstraintSet();
    set.clone(parentView);

    if (advertisements.size() > 0) {

        recyclerView.setVisibility(View.VISIBLE);
        txvMyAdEmptyText.setVisibility(View.GONE);
        imvEmpty.setVisibility(View.GONE);
        adapter.setList(advertisements);
        adapter.notifyDataSetChanged();

    } else {

        set.connect(btnCreateAd.getId(), ConstraintSet.TOP, imvEmpty.getId(), ConstraintSet.BOTTOM, 0);

        recyclerView.setVisibility(View.GONE);
        txvMyAdEmptyText.setVisibility(View.VISIBLE);
        imvEmpty.setVisibility(View.VISIBLE);
        adapter.setList(new ArrayList<Advertisement>());
    }
    set.connect(btnCreateAd.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0);
    set.connect(btnCreateAd.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 0);
    set.connect(btnCreateAd.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 0);

    set.applyTo(parentView);

person Damir Mailybayev    schedule 21.06.2017    source источник
comment
посмотрим, поможет ли это stackoverflow.com/questions/5107740/   -  person Valdio Veliu    schedule 21.06.2017
comment
@ValdioVeliu извините, но это для параметров RelativeLayout, мне нужно от constraintLayoutParams.   -  person Damir Mailybayev    schedule 22.06.2017
comment
@Chisko Я пробовал также с ConstraintSet, но он не работает в этом случае, и, более того, каким-то образом он нарушает мои другие ограничения представлений. Кстати, все представления уже созданы в макете (я имею в виду, что я не создаю представление динамически).   -  person Damir Mailybayev    schedule 22.06.2017


Ответы (3)


Я не работал с вашим кодом, но ниже показано, как разорвать и наложить ограничение с помощью ConstraintSet.

ConstraintSet set = new ConstraintSet();
ConstraintLayout layout;

layout = (ConstraintLayout) findViewById(R.id.layout);
set.clone(layout);
// The following breaks the connection.
set.clear(R.id.bottomText, ConstraintSet.TOP);
// Comment out line above and uncomment line below to make the connection.
// set.connect(R.id.bottomText, ConstraintSet.TOP, R.id.imageView, ConstraintSet.BOTTOM, 0);
set.applyTo(layout);
person Cheticamp    schedule 22.06.2017
comment
Наконец-то появился способ программно удалить ограничения, спасибо. - person Lalit Fauzdar; 31.12.2017
comment
@ DominikusK. Ой, спасибо, что позвонил мне! Если вас интересует анимация этих переходов, это полезный пост - person bmjohns; 27.01.2018
comment
Кто-нибудь заметил проблему с Api 21 или 22 с ConstraintLayout 1.1.1 при изменении ограничений? Кажется немного ненадежным, хотя отлично работает на api 28 - person Bakhshi; 13.06.2018
comment
Да @Bakhshi, я тоже заметил. Вы решили это? Если да, то как? Я использую версию 1.1.3 - person Shubham Gupta; 13.09.2018
comment
set.clone(layout); эта строка была очень важной, так как мой макет начал исчезать после того, как я применил без этой строки. - person Reejesh PK; 17.01.2019

Другой способ сделать это - использовать ConstraintLayout.LayoutParams.UNSET. Таким образом не используется ConstraintSet.clear.

Предполагая, что мы хотим удалить нижнее ограничение нашего самого constraintLayout, но может быть любым представлением:

val containerParams = cl_container.layoutParams as ConstraintLayout.LayoutParams
containerParams.bottomToBottom = ConstraintLayout.LayoutParams.UNSET
cl_container.layoutParams = containerParams
person j2emanue    schedule 20.04.2020
comment
Не могли бы вы предоставить Java-версию этого кода? - person NALIN_yo; 24.08.2020
comment
Котлин и Java взаимозаменяемы. Ищите вариант поменять в ide или онлайн - person j2emanue; 25.08.2020

Вот версия ответа для Java от j2emanue с использованием _ 1_, который работает без указания идентификатора элемента, которому запрещен макет:

final ConstraintLayout constraintLayout = findViewById(R.id.constraintLayout);
final ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) constraintLayout.getLayoutParams();
layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.UNSET;
constraintLayout.setLayoutParams(layoutParams);
person Unmitigated    schedule 08.09.2020