Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
}
like image 484
lbenedetto Avatar asked Jun 03 '19 14:06

lbenedetto


People also ask

How do I set margins to recyclerView programmatically?

margin); int marginTopPx = (int) (marginTopDp * getResources(). getDisplayMetrics(). density + 0.5f); layoutParams. setMargins(0, marginTopPx, 0, 0); recyclerView.

How do you set the top margin in Java?

setMargins(left, top, right, bottom); yourbutton. setLayoutParams(params); Depending on what layout you're using you should use RelativeLayout. LayoutParams or LinearLayout.


2 Answers

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.

like image 72
UnOrthodox Avatar answered Oct 19 '22 07:10

UnOrthodox


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);
}
like image 1
Ahmed Abdel-Mohsen Avatar answered Oct 19 '22 08:10

Ahmed Abdel-Mohsen