Search code examples
androidandroid-motionlayout

Programmatically set margins in a MotionLayout


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;
}

Solution

  • 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.