61

I want to remove and add constraint programmatically based on some condition. Here are the screenshots:

The button "create ad" has a top constraint

and I want to remove it like this but in code:

here is button with removed constraint on top

so the same effect in want to achieve programmatically

and here is the code that I tried:

    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

EDIT

I have tried using ConstraintSet also, but the result was even different somehow my RecyclerView (which is set to boundaries of parent view) was disappearing

 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);
Cheticamp
  • 50,205
  • 8
  • 64
  • 109
Damir Mailybayev
  • 871
  • 1
  • 8
  • 13
  • see if this helps https://stackoverflow.com/questions/5107740/how-do-i-programmatically-remove-an-existing-rule-that-was-defined-in-xml – Valdio Veliu Jun 21 '17 at 20:42
  • @ValdioVeliu sorry, but that is for RelativeLayout params, i need from constraintLayoutParams. – Damir Mailybayev Jun 21 '17 at 21:06
  • @Chisko i have tried also with ConstraintSet but it doesn't work for this case, and moreover somehow it is breaking my other constraints of the views. By the way all views are already created in layout (i mean I don't create a view dynamically). – Damir Mailybayev Jun 21 '17 at 23:23

3 Answers3

145

I have not worked through your code, but the following illustrates how to break and make the constraint using 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);
stkent
  • 18,470
  • 14
  • 80
  • 99
Cheticamp
  • 50,205
  • 8
  • 64
  • 109
  • Finally got a way to remove the constraints programmatically, Thanks. – Lalit Fauzdar Dec 31 '17 at 06:51
  • @DominikusK.Oops, thanks for calling me out! If your interested in animating these transitions, this is a helpful [post](https://robinhood.engineering/beautiful-animations-using-android-constraintlayout-eee5b72ecae3) – bmjohns Jan 27 '18 at 15:45
  • Has anyone noticed any problem with Api 21 or 22 with ConstraintLayout 1.1.1 when changing the constraints? Seems to be a bit unreliable though works perfectly on api 28 – Bakhshi Jun 13 '18 at 03:28
  • Yes @Bakhshi, I've noticed the same thing. Have you resolved it? If yes, how? I'm using version 1.1.3 – Shubham Gupta Sep 13 '18 at 07:39
  • `set.clone(layout);` this line was very important, since my layout started to disappear after I apply without this line. – Reejesh PK Jan 17 '19 at 09:21
7

Another way of doing this is with ConstraintLayout.LayoutParams.UNSET. This way is not using ConstraintSet.clear.

Assuming we want to remove the bottom constraint of our constraintLayout itself but can be any view:

val containerParams = cl_container.layoutParams as ConstraintLayout.LayoutParams
containerParams.bottomToBottom = ConstraintLayout.LayoutParams.UNSET
cl_container.layoutParams = containerParams
Vadim Kotov
  • 7,103
  • 8
  • 44
  • 57
j2emanue
  • 51,417
  • 46
  • 239
  • 380
2

Here is the Java version of the answer from j2emanue using ConstraintLayout.LayoutParams, which works without specifying the id of the element that the layout is contrained to:

final ConstraintLayout constraintLayout = findViewById(R.id.constraintLayout);
final ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) constraintLayout.getLayoutParams();
layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.UNSET;
constraintLayout.setLayoutParams(layoutParams);
iota
  • 34,586
  • 7
  • 32
  • 51