I need to change margin of toolbar, which was made of ConstraintLayout, in different cases. I tried to do it in following way
ConstraintLayout.LayoutParams newLayoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);
ConstraintLayout.MarginLayoutParams layoutParams = new ConstraintLayout.MarginLayoutParams(newLayoutParams);
layoutParams.setMargins(0, 0, 0, 0);
toolbar.setLayoutParams(newLayoutParams);
but in second case layoutParams.setMargins(16, 16, 16, 16);
it did not change. So, can someone give other way or point to the mistake. Thanks for spending time to my problem.
I tried to use newLayoutParams.setMargins(54, 54, 54, 0); this puts margin to left and right, but I still need to put margin on top of it.
Finally with help of #Aksh I found my mistake and solve my problem. If someone find it useful, I will put my code bellow
ConstraintLayout.LayoutParams newLayoutParams = (ConstraintLayout.LayoutParams) toolbar.getLayoutParams();
newLayoutParams.topMargin = 0;
newLayoutParams.leftMargin = 0;
newLayoutParams.rightMargin = 0;
toolbar.setLayoutParams(newLayoutParams);
good way to add margin to a view in constraintlayout
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayoutId)
val marginTop = context.getDimension(10f)
constraintSet.setMargin(R.id.tv_user, ConstraintSet.TOP, marginTop)
constraintSet.applyTo(constraintLayoutId)
fun Context.getDimension(value: Float): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, value, this.resources.displayMetrics).toInt()
}
I once modified a ConstraintLayout with a ConstraintSet to change the elements it got linked with. I also changed the margin within that process which is the last parameter of the connect method:
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(layout);
constraintSet.connect(
R.id.layout_id,
ConstraintSet.START,
R.id.layout_id2,
ConstraintSet.END,
8);
constraintSet.applyTo(layout);
Maybe this gives you another hint to find a solution?
You might wanna try
ViewGroup.MarginLayoutParams params = yourConstraintLayout.getLayoutParams();
params.topMargin = x;
//others shows up in suggestion
I haven't tried it though I believe it should work as ConstraintLayout is a ViewGroup.
For layoutParams.setMargins(w, x, y, z) the reason it's not changing is because you're most likely treating the values as Dp's rather than Px's, for which the method accepts.
To get Px from the Dp, you want to use:
int pxValue = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
Related
I want to display a box with suggested entries next to an EditText.
I figured I'd have to set LayoutParams (like suggested in this question.
However, no matter what I try, the box always ends up in the top left corner.
What I tried:
- get LayoutParams as MarginLayoutParams (which they are), and set them. Set them back in the view for good measure.
- All the answers in the link mentioned above
Change the position with TranslationX and -Y (which works, but runs into other problems like status bar might not always be 24dp and seems a hack)
val layoutParams = box?.layoutParams
//val layoutParams = ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply{
// setMargins(left, top, 0,0)
//}
if (layoutParams !is ViewGroup.MarginLayoutParams) return#onTextChanged
//layoutParams.leftMargin = left
layoutParams.marginStart = left
layoutParams.topMargin = top
box?.layoutParams = layoutParams // Don't think this is necessary
Log.d(TAG, "$layoutParams")
// works, but don't like it
// box?.translationX = left.toFloat()
// box?.translationY = top.toFloat()
//doesn't work
//box?.setMargins(left, top, right, 1000)
the function View.Setmargins is as follows:
fun View.setMargins(left: Int, top: Int, right: Int, bottom: Int) {
if (layoutParams is MarginLayoutParams) {
val p = layoutParams as MarginLayoutParams
p.setMargins(left, top, right, bottom)
requestLayout()
}
}
Complete source of the thing I want to do here (snippet above is at line 170, edited it a bit to show things I've tried)
Other things I have tried: add box to different layouts, which in all cases results in the box being drawn in the top-left corner of that layout
For anybody having the same problem as I had:
Mike M. 's suggestion to get the LayoutParams as ConstraintLayout.LayoutParams, and also set its topToTop and startToStart fields to ConstraintLayout.LayoutParams.PARENT_ID did the trick, ie.
(box?.layoutParams as ConstraintLayout.LayoutParams).apply{
topToTop = ConstraintLayout.LayoutParams.PARENT_ID
startToStart = ConstraintLayout.LayoutParams.PARENT_ID
topMargin = top
marginStart = left
}
I have added 2 views from xml in constraint layout, Now i need to add new view below the view created from xml
This is what i do to add new view
//leftMargin calculation
int topMargin= Utils.pxToDp(20);
ImageView imageView = new ImageView(this);
imageView.setId(View.generateViewId());
constraintLayout.addView(imageView);
ConstraintSet set = new ConstraintSet();
set.clone(constraintLayout);
set.constrainWidth(imageView.getId(), ConstraintSet.MATCH_CONSTRAINT);
set.connect(imageView.getId(), ConstraintSet.TOP, eventsViewPager.getId(), ConstraintSet.BOTTOM, topMargin);
I am defining margin 20dp here, but it just adds a thin line over the view, and if i use margin around 400, then it gives me the desired result, there must be some mistake in conversion may be that i am making here.
This is how i convert values from px to dp
public static int pxToDp(int px){
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
I think you should convert DP to pixel and not viceversa, use TypedValue for that like this:
int marginTopDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
getResources().getDisplayMetrics());
I'm writing a custom view to be able to use custom XML attributes to set a view's margin and size based on these attributes, everything worked fine until i got to the part where children of ConstraintLayout get's their margins and size determined by custom values.
The margins doesn't make any difference and the view stays on the top left corner of its parent ConstraintLayout.
What could be the problem? (The Image should be 500PXs away from the screen boundaries)
if (hasCustomWidth || hasCustomHeight || hasCustomTopMargin || hasCustomRightMargin || hasCustomBottomMargin || hasCustomLeftMargin) {
if(((ViewGroup)getParent()) instanceof LinearLayout) {
LinearLayout.LayoutParams newLayoutParams = new LinearLayout.LayoutParams((int) Math.round(customWidth), (int) Math.round(customHeight));
ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) newLayoutParams;
marginLayoutParams.setMargins((int) Math.round(customLeftMargin), (int) Math.round(customTopMargin), (int) Math.round(customRightMargin), (int) Math.round(customBottomMargin));
setLayoutParams(newLayoutParams);
} else if(((ViewGroup)getParent()) instanceof ConstraintLayout) {
ConstraintLayout parentConstraintLayout = (ConstraintLayout)CustomAppCompatImageView.this.getParent();
ConstraintLayout.LayoutParams newLayoutParams = new ConstraintLayout.LayoutParams((int) Math.round(customWidth), (int) Math.round(customHeight));
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(parentConstraintLayout);
constraintSet.connect(CustomAppCompatImageView.this.getId(), ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 500);
constraintSet.setMargin(CustomAppCompatImageView.this.getId(), ConstraintSet.LEFT, 500);
setLayoutParams(newLayoutParams);
constraintSet.applyTo(parentConstraintLayout);
parentConstraintLayout.invalidate();
} else {
throw new RuntimeException("no listed parent LayoutParams subclass!");
}
invalidate();
}
Result:
I found the solution: apparently Android doesn't take ConstraintSet.LEFT and ConstraintSet.RIGHT as proper arguments, and must be replaced with ConstraintSet.START and ConstraintSet.END.
I need to set the top margin on a RecyclerView programmatically, but I get this exception:
java.lang.RuntimeException: Unable to resume activity java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.support.v7.widget.RecyclerView$LayoutParams
Here is my code:
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams)recyclerView.getLayoutParams();
int marginTopDp = (int)getResources().getDimension(R.dimen.margin);
int marginTopPx = (int) (marginTopDp * getResources().getDisplayMetrics().density + 0.5f);
layoutParams.setMargins(0, marginTopPx, 0, 0);
recyclerView.setLayoutParams(layoutParams);
If I use the ViewGroup.LayoutParams layoutParams = recyclerView.getLayoutParams as the stack trace suggests, I cannot call setMargin anymore as that method does not exist for ViewGroup.LayoutParams.
Any help would be appreciated.
Try this out. You can refer to this for more info.
ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(mRecyclerView.getLayoutParams());
marginLayoutParams.setMargins(0, 10, 0, 10);
mRecyclerView.setLayoutParams(marginLayoutParams);
for me, the parent of recyclerview is a constraintLayout,
val margins = (rv.layoutParams as ConstraintLayout.LayoutParams).apply {
leftMargin = 0
rightMargin = 0
}
rv.layoutParams = margins
or it will get cast error, viewGroup.LayoutParams can't be cast to COnstarintLayout.LayoutParams
You need use new object of MargingLayoutParams
final FrameLayout.MarginLayoutParams marginLayoutParams = new
FrameLayout.MarginLayoutParams(rvContacts.getLayoutParams());
marginLayoutParams.leftMargin = left;
marginLayoutParams.topMargin = top;
marginLayoutParams.rightMargin = right;
marginLayoutParams.bottomMargin = bottom;
recyclerView.setLayoutParams(marginLayoutParams);
recyclerView.requestLayout();
I am also facing this type of issue, Use below code to handle margin issue of recyclerview.
ViewGroup.MarginLayoutParams marginLayoutParams=
(ViewGroup.MarginLayoutParams) recyclerView.getLayoutParams();
// here i try to set only top margin, Get dimension from dimension file.
int topMargin = getResources()
.getDimensionPixelSize(R.dimen.top_margin);
marginLayoutParams.setMargins(marginLayoutParams.getMarginStart(),
topMargin, marginLayoutParams.getMarginEnd(), marginLayoutParams.bottomMargin);
recyclerView.setLayoutParams(marginLayoutParams);
Padding usage with clipToPadding="false" did the trick in my case. [Kotlin]
So I added android:clipToPadding="false" to my RecyclerView in xml.
Can be done programmatically as well.
And then just used:
recyclerView.setPadding(10, 0, 0, someSpace)
someSpace is dp variable in case you need it.
resources.getDimension(R.dimen.some_space).toInt()
P.S don't forget to create some_space in dimension file :)
Is there an easy and simple way to set LayoutParams ? Or to be exactly, the MarginLayoutParams? I want to set the MarginRight to a few dp, unfortunately im not able to set these in the LayoutFile cause the Target is a ListFragment and in Code-Behind looks it very ugly.
The reason i do this not in the Layout of the items is so the code is optimized and perfomant.
To sum up: Is there any very simple and clean way to set Params ?
Yes, you can do something like this:
MyImageView i2 = new MyImageView(context);
LayoutParams lp = new LayoutParams(300, 300);
lp.LeftMargin = 100;
lp.TopMargin = 100;
lp.Gravity = 0;
this.AddView(i2, lp);
LayoutParams lp = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT );
lp.setMargins( left, top, right, bottom );
You might need to write it as LinearLayout.LayoutParams, depending on what type of layout is the container.
And then you call the method setLayoutParams( lp ); on the given view/layout/widget.