7

I have some views that need some margins set programmatically (from an applyWindowInsets listener), but the views seem to be ignoring any margins I set with my code, even though I am not animating the margins.

I'm able to set padding just fine, but I cannot accomplish what I need using only padding.

The issue seems to be related to MotionLayout since it works fine if it is a ConstraintLayout.

I've been using this util method.

public static void addTopMargin(View v, int margin) {
    ((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin += margin;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
lbenedetto
  • 2,022
  • 1
  • 21
  • 39
  • I have been using a workaround that doesn't work in all cases, but enough that I was able to accomplish what I needed. If you put the view you want to control in a LinearLayout, you can control whatever properties you need on the child object, and the motion layout will control all the properties on the LinearLayout – lbenedetto Sep 04 '19 at 11:29

2 Answers2

7

The issue you're having is that MotionLayout derives its margins from the assigned ConstraintSets, so changing the base margin isn't actually doing anything. To get this to work, you need to target one or both of the ConstraintSets that define the MotionScene:

val motionLayout = findViewById(R.id.motionLayoutId)
motionLayout.getConstraintSet(R.id.startingConstraintSet)?
    .setMargin(targetView.id, anchorId, value)

You could also do this for more than one view with a let:

val motionLayout = findViewById(R.id.motionLayoutId)
motionLayout.getConstraintSet(R.id.startingConstraintSet)?.let {
    setMargin(firstView.id, anchorId, value)
    setMargin(secondView.id, anchorId, value)
}

For the top margin, use ConstraintSet.TOP, etc.

Remember that if you're not wanting to animate that margin, you'll have to assign to both the start and end ConstraintSet.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
UnOrthodox
  • 106
  • 1
  • 4
1

Just adding a simple note to UnOrthodox solution that in case of you don't need to animate that margin you will need to keep the base margin with adding the ConstraintSets margin:

public static void addTopMargin(View v, int margin) {
    ((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin += margin;
    MotionLayout root = findViewById(R.id.motion_layout);
    root.getConstraintSet(R.id.start).setMargin(firstView.id, anchorId, margin);
    root.getConstraintSet(R.id.end).setMargin(firstView.id, anchorId, margin);
}