Removing/Editing a constraint of a view inside a ConstraintLayout programmatically - android

I have a view (Linearlayout) inside a ConstraintLayout with the following attributes:
android:id="#+id/myView"
app:layout_constraintTop_toBottomOf="#+id/anotherView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
At some occasions I wish to align myView to the left, by simply removing the right constraint. however I'm not able to do so.
I tried to use the following, simply to copy and apply the constraint parameters:
ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(holder.myView.getLayoutParams());
holder.myView.setLayoutParams(layoutParams);
but the layoutParams always receives an empty parameters set,and sends the view to the top left corner. Perhaps it's because I'm using this inside of a recyclerView?
How it looks inside the recyclerView:
public void onBindViewHolder(final RecyclerView.ViewHolder basicHolder, int position) {
ProfileAdapter.UserInfoViewHolder holder = (ProfileAdapter.UserInfoViewHolder) basicHolder;
ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(holder.myView.getLayoutParams(‌​));
holder.myView.setLayoutParams(layoutParams);
}

There's a bug (will be fixed in the next release) when setting layout params the way you do it. In the meantime, you can do:
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) holder.myView.getLayoutParams();
layoutParams.rightToRight = ConstraintLayout.LayoutParams.UNSET;
holder.myView.setLayoutParams(layoutParams);

The same in Kotlin:
val layoutParams = view.layoutParams as ConstraintLayout.LayoutParams
layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.UNSET

Related

Android : How to programmatically set layout_constraintRight_toRightOf "parent"

I have a view in ConstrainLayout as follows.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="260dp"
android:textColor="#FFF"
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="#+id/parent"
app:layout_constraintTop_toBottomOf="#id/message_date"
android:id="#+id/text_main"
/>
I would like to change the view to either app:layout_constraintLeft_toLeftOf="#+id/parent" or layout_constraintLeft_toRightOf="#+id/parent" programmatically in recycleViewHolder based on some conditions.
Here is an example of setting a button to the bottom of parent view using java code:
ConstraintLayout constraintLayout;
ConstraintSet constraintSet;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
constraintLayout = (ConstraintLayout) findViewById(R.id.activity_main_constraint_layout);
Button button = new Button(this);
button.setText("Hello");
constraintLayout.addView(button);
constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout);
constraintSet.connect(button.getId(), ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.RIGHT, 0);
constraintSet.constrainDefaultHeight(button.getId(), 200);
constraintSet.applyTo(constraintLayout);
}
to achieve something like this,
app:layout_constraintLeft_toLeftOf="#+id/parent"
your java code should look like this
set.connect(YOURVIEW.getId(),ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.LEFT,0);
and to achieve something like this,
layout_constraintLeft_toRightOf="#+id/parent"
your java code should look like this,
set.connect(YOURVIEW.getId(),ConstraintSet.LEFT,ConstraintSet.PARENT_ID,ConstraintSet.RIGHT,0);
Here, I'm assuming android:id="#+id/parent" is the id of your parent ConstraintLayout .
constraintSet = new ConstraintSet(); and so on
Did not work for me anyhow.
Solved by
LayoutParams layoutParams = (LayoutParams) viewToChange.getLayoutParams();
layoutParams.leftToLeft = anotherViewId;
layoutParams.rightToRight =anotherViewId;
layoutParams.topToTop = anotherViewId;
layoutParams.bottomToBottom = anotherViewId;
layoutParams.startToStart =anotherViewId;
layoutParams.endToEnd = anotherViewId;
viewToChange.setLayoutParams(layoutParams);
Use id
class MyLayout(context: Context) : ConstraintLayout(context) {
fun show() {
val view = ImageView(context)
addView(view)
val params = view.layoutParams as ConstraintLayout.LayoutParams
params.height = 100
params.width = 50
params.rightToRight = id
view.requestLayout()
}
}
I had same situation when I needed to move buttons down once a new EditText appears, In XML file they had constraints like this:
app:layout_constraintTop_toBottomOf="#+id/first_layout"
and what I needed to do is changing to sth like programmatically:
app:layout_constraintTop_toBottomOf="#+id/second_layout"
Using ConstraintLayout.LayoutParams the task is pretty straightforward e.g.
Kotlin:
val currentLayout = btn.layoutParams as ConstraintLayout.LayoutParams // btn is a View here
currentLayout.topToBottom = R.id.second_layout // resource ID of new parent field
btn.layoutParams = currentLayout
and that's it!
Haven't seen better solution than this:
textMain.updateLayoutParams<ConstraintLayout.LayoutParams> {
startToEnd = anyOtherView.id
topToTop = anyOtherView.id
endToStart = anyOtherView.id
bottomToBottom = anyOtherView.id
}
In Android, you can programmatically set the layout_constraintRight_toRightOf attribute to "parent" using the ConstraintLayout.LayoutParams class. Here's an example:
ConstraintLayout layout = findViewById(R.id.constraint_layout);
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) view.getLayoutParams();
params.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID;
view.setLayoutParams(params);
In the above example, "constraint_layout" is the id of the ConstraintLayout, "view" is the view that you want to set the constraint on and the "params.rightToRight = ConstraintLayout.LayoutParams.PARENT_ID" is used to set the layout_constraintRight_toRightOf attribute to "parent".
This will set the right side of the view to the right side of its parent, aligning it to the right edge of the screen.
You can also use setRightToRight(int rightToRight) method of ConstraintLayout.LayoutParams.
It's also important to note that you should call requestLayout() on the view after modifying its layout parameters, so that the changes will be reflected on the layout.

How to programmatically set weight for Button

I need to implement Dialog for my Android app through Java code, so I can't use XML.
I have root LinearLayout where I implement range seek bar, then I have another LinearLayout under root layout, with horizontal orientation, where I want to add two buttons in same row. So I need to set weight to 1, and width to FILL_PARENT and height to WRAP_CONTENT.
How I can do that with Java code?
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
p.weight = 1;
rangeSeekBar.setLayoutParams(p);
I'm not sure which view you want to set the layout params on. I just assumed the rangeSeekbar to show an example. Change if you need.
When using the layout params always use the root's param type..
Ex. if you have a View you want to apply params to within a RelativeLayout use RelativeLayout.LayoutParams..
You can pass it in as part of the LinearLayout.LayoutParams constructor:
Did you mean wrap_content?
LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT, 1.0f);
1.0f is the weight
Is not using XML a requirement? If not, you could always build your layout in XML and then use a LayoutInflater at run-time to build up your view hierarchy and pass that to setView() on your dialog.
For example:
LayoutInflater inflater = LayoutInflater.from(getActivity());
View v = inflater.inflate(R.layout.my_dialog_layout, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(v);
an easier way:
public static void setLayoutWeight(View view , float weight)
{
((LinearLayout.LayoutParams) view.getLayoutParams()).weight = weight;
view.requestLayout();
}

How to set layout_gravity programmatically?

My question is simple,
How to set my buttons layout_gravity programmatically?
I found this on internet, but it simply throws me a Nullpointer exception:
Button MyButton = new Button(this);
LinearLayout.LayoutParams lllp=(LinearLayout.LayoutParams)MyButton.getLayoutParams();
lllp.gravity=Gravity.RIGHT;
MyButton.setLayoutParams(lllp);
MyLinearLayout.addView(MyButton);
Any solution?
Java
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
params.weight = 1.0f;
params.gravity = Gravity.TOP;
button.setLayoutParams(params);
Kotlin
val params = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
).apply {
weight = 1.0f
gravity = Gravity.TOP
}
For gravity values and how to set gravity check Gravity.
Basically, you should choose the LayoutParams depending on the parent. It can be RelativeLayout, LinearLayout etc...
I'd hate to be resurrecting old threads but this is a problem that is not answered correctly and moreover I've ran into this problem myself.
Here's the long bit, if you're only interested in the answer please scroll all the way down to the code:
android:gravity and android:layout_gravity works differently. Here's an article I've read that helped me.
GIST of article: gravity affects view after height/width is assigned. So gravity centre will not affect a view that is done FILL_PARENT (think of it as auto margin). layout_gravity centre WILL affect view that is FILL_PARENT (think of it as auto pad).
Basically, android:layout_gravity CANNOT be access programmatically, only android:gravity.
In the OP's case and my case, the accepted answer does not place the button vertically centre.
To improve on Karthi's answer:
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
button.setLayoutParams(params);
Link to LinearLayout.LayoutParams.
android:layout_gravity shows "No related methods" meaning cannot be access programatically.
Whereas gravity is a field in the class.
I had a similar problem with programmatically setting layout_gravity on buttons in a GridLayout.
The trick was to set gravity on the button layoutParams AFTER the button was added to a parent (GridLayout), otherwise the gravity would be ignored.
grid.addView(button)
((GridLayout.LayoutParams)button.getLayoutParams()).setGravity(int)
MyButton.setGravity(Gravity.RIGHT);
For layout_gravity use the answer stated by "karthi". This method sets gravity to place the children inside the view.
layoutParams2.gravity = Gravity.RIGHT|Gravity.BOTTOM;
use this to add mor than one gravity
If you want to change the layou_gravity of an existing view do this:
((FrameLayout.LayoutParams) view.getLayoutParams()).gravity = Gravity.BOTTOM;
Remember to use the right LayoutParams based on the Layout type your view is in. Ex:
LinearLayout.LayoutParams
KOTLIN setting more than one gravity on FrameLayout without changing size:
// assign more than one gravity,Using the operator "or"
var gravity = Gravity.RIGHT or Gravity.CENTER_VERTICAL
// update gravity
(pagerContainer.layoutParams as FrameLayout.LayoutParams).gravity = gravity
// refresh layout
pagerContainer.requestLayout()
This question is old but I just had the same problem and solved it like this
LayoutParams lay = new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)
lay.gravity = Gravity.CENTER;
I use someting like that: (Xamarin and C# code)
LinearLayout linLayout= new LinearLayout(this);
linLayout.SetGravity(GravityFlags.Center);
TextView txtView= new TextView(this);
linLayout.AddView(txtView);
the SetGravity puts my textView in the center of the layout.
So SetGravity layout property refer to layout content
In case you need to set Gravity for a View use the following
Button b=new Button(Context);
b.setGravity(Gravity.CENTER);
For setting layout_gravity for the Button
use gravity field for the layoutparams as
LayoutParams lp=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp.gravity=Gravity.CENTER;
try this
hope this clears
thanks
If you want to put a view in the center of parent, you can do with following code..
public class myLayout extends LinearLayout {
public myLayout(Context context) {
super(context);
RelativeLayout vi = (RelativeLayout) ((LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.activity_main, null);
LinearLayout.LayoutParams cc = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
cc.gravity = Gravity.CENTER;
this.setGravity(Gravity.CENTER);
this.addView(vi);
}
}
these code section make LinearLayout put the first view elements in the center of parent.
So, we system don't consider the initial width and high to arrange view in the center .
I do the code section well.
The rest of the answers are right, I want to add more explaination. The layout_gravity is about how to position the view in parent view.
You must set gravity **after method parentView.addView() ** was called. We can see the code:
public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params == null) {
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
And the problem of null pointer is because it's not calling addView before getLayoutParams().
The annotation was already said "This method may return null if this View is not attached to a parent ViewGroup or {#link#setLayoutParams(android.view.ViewGroup.LayoutParams)} was not invoked successfully. When a View is attached to a parent ViewGroup, this method must not return null."
to RelativeLayout, try this code , it works for me:
yourLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
Perfectly Working!!! None of the above answer works for me. In Xml file setting gravity and setting layout_gravity is different. Check out the below code
// here messageLL is the linear layout in the xml file
// Before adding any view just remove all views
messageLL.removeAllViews();
// FrameLayout is the parent for LinearLayout
FrameLayout.LayoutParams params = new
FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER|Gravity.CENTER_VERTICAL;
messageLL.setLayoutParams(params);
messageText.setVisibility(View.GONE);
messageNoText.setVisibility(View.VISIBLE);
messageLL.addView(messageNoText);
Also check This,where you can find clear explanation about gravity and layout_gravity .
Most of above answer are right, so written a helper methods, so you can use it
directly in you project .
set layout_gravity programmtically
// gravity types : Gravity.BOTTOM, Gravity.START etc.
// view : can be any view example : button, textview, linearlayout, image etc.
// for single view
public static void setLayoutGravity(int gravity, View view){
((LinearLayout.LayoutParams) view.getLayoutParams()).gravity = gravity;
}
// for mulitple views
public static void setLayoutGravity(int gravity, View ...view){
for(View item : view)
((LinearLayout.LayoutParams) item.getLayoutParams()).gravity = gravity;
}
Modify the existing layout params and set layout params again
//Get the current layout params and update the Gravity
(iv.layoutParams as FrameLayout.LayoutParams).gravity = Gravity.START
//Set layout params again (this updates the view)
iv.layoutParams = layoutParams
I switched from LinearLayout.LayoutParams to RelativeLayout.LayoutParams to finally get the result I was desiring on a custom circleview I created.
But instead of gravity you use addRule
RelativeLayout.LayoutParams mCircleParams = new RelativeLayout.LayoutParams(circleheight,circleheight);
mCircleParams.addRule(RelativeLayout.CENTER_IN_PARENT);
int width=getResources().getDisplayMetrics().widthPixels;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
(width, width);
params.gravity = Gravity.CENTER;
iv_main_text = new HTextView(getContext());
iv_main_text.setLayoutParams(params);
iv_main_text.setBackgroundColor(Color.BLUE);
iv_main_text.setTextSize(60);
iv_main_text.setGravity(Gravity.CENTER);
iv_main_text.setTextColor(Color.BLACK);
FloatingActionButton sendFab = new FloatingActionButton(this);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(32, 32, 32, 32);
layoutParams.gravity = Gravity.END|Gravity.BOTTOM;
sendFab.setLayoutParams(layoutParams);
sendFab.setImageResource(android.R.drawable.ic_menu_send);
Try this code
Button btn = new Button(YourActivity.this);
btn.setGravity(Gravity.CENTER | Gravity.TOP);
btn.setText("some text");
or
btn.setGravity(Gravity.TOP);

How to programmatically set the layout_align_parent_right attribute of a Button in Relative Layout?

I have a relative layout which I am creating programmatically:
RelativeLayout layout = new RelativeLayout( this );
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
Now I have two buttons which I want to add in this relative layout. But the problem is both buttons are being shown on the left of the RelatiiveLayout overlapping on each other.
buttonContainer.addView(btn1);
buttonContainer.addView(btn2);
Now I want to know how can I programmatically set the the android:layout_alignParentRight="true"
or android:layout_toLeftOf="#id/btn" attribute of buttons as we do in the xml?
You can access any LayoutParams from code using View.getLayoutParams. You just have to be very aware of what LayoutParams your accessing. This is normally achieved by checking the containing ViewGroup if it has a LayoutParams inner child then that's the one you should use. In your case it's RelativeLayout.LayoutParams. You'll be using RelativeLayout.LayoutParams#addRule(int verb) and RelativeLayout.LayoutParams#addRule(int verb, int anchor)
You can get to it via code:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)button.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.LEFT_OF, R.id.id_to_be_left_of);
button.setLayoutParams(params); //causes layout update
For adding a RelativeLayout attribute whose value is true or false use 0 for false and RelativeLayout.TRUE for true:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) button.getLayoutParams()
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE)
It doesn't matter whether or not the attribute was already added, you still use addRule(verb, subject) to enable/disable it. However, post-API 17 you can use removeRule(verb) which is just a shortcut for addRule(verb, 0).
you need to create and id for the
buttons you need to refference:
btn1.setId(1);
you can use the params variable to
add parameters to your layout, i
think the method is addRule(), check
out the android java docs for this
LayoutParams object.
Kotlin version:
Use these extensions with infix functions that simplify later calls
infix fun View.below(view: View) {
(this.layoutParams as? RelativeLayout.LayoutParams)?.addRule(RelativeLayout.BELOW, view.id)
}
infix fun View.leftOf(view: View) {
(this.layoutParams as? RelativeLayout.LayoutParams)?.addRule(RelativeLayout.LEFT_OF, view.id)
}
infix fun View.alightParentRightIs(aligned: Boolean) {
val layoutParams = this.layoutParams as? RelativeLayout.LayoutParams
if (aligned) {
(this.layoutParams as? RelativeLayout.LayoutParams)?.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
} else {
(this.layoutParams as? RelativeLayout.LayoutParams)?.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0)
}
this.layoutParams = layoutParams
}
Then use them as infix functions calls:
view1 below view2
view1 leftOf view2
view1 alightParentRightIs true
Or you can use them as normal functions:
view1.below(view2)
view1.leftOf(view2)
view1.alightParentRightIs(true)
In Kotlin:
val params = mBinding.tvTotalAmount.layoutParams as RelativeLayout.LayoutParams
params.addRule(RelativeLayout.ALIGN_PARENT_END)
mBinding.tvTotalAmount.layoutParams = params

How do you setLayoutParams() for an ImageView?

I want to set the LayoutParams for an ImageView but cant seem to find out the proper way to do it.
I can only find documentation in the API for the various ViewGroups, but not an ImageView. Yet the ImageView seems to have this functionality.
This code doesn't work...
myImageView.setLayoutParams(new ImageView.LayoutParams(30,30));
How do I do it?
You need to set the LayoutParams of the ViewGroup the ImageView is sitting in. For example if your ImageView is inside a LinearLayout, then you create a
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
This is because it's the parent of the View that needs to know what size to allocate to the View.
Old thread but I had the same problem now. If anyone encounters this he'll probably find this answer:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
This will work only if you add the ImageView as a subView to a LinearLayout. If you add it to a RelativeLayout you will need to call:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(30, 30);
yourImageView.setLayoutParams(layoutParams);
If you're changing the layout of an existing ImageView, you should be able to simply get the current LayoutParams, change the width/height, and set it back:
android.view.ViewGroup.LayoutParams layoutParams = myImageView.getLayoutParams();
layoutParams.width = 30;
layoutParams.height = 30;
myImageView.setLayoutParams(layoutParams);
I don't know if that's your goal, but if it is, this is probably the easiest solution.
An ImageView gets setLayoutParams from View which uses ViewGroup.LayoutParams. If you use that, it will crash in most cases so you should use getLayoutParams() which is in View.class. This will inherit the parent View of the ImageView and will work always. You can confirm this here: ImageView extends view
Assuming you have an ImageView defined as 'image_view' and the width/height int defined as 'thumb_size'
The best way to do this:
ViewGroup.LayoutParams iv_params_b = image_view.getLayoutParams();
iv_params_b.height = thumb_size;
iv_params_b.width = thumb_size;
image_view.setLayoutParams(iv_params_b);
In order not to lose the rest of the parameters, you need to do as shown below:
Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.checked, null);
preview.setImageDrawable(drawable);
ViewGroup.LayoutParams layoutParams = preview.getLayoutParams();
layoutParams.width = 100;
layoutParams.height = 98;
preview.setLayoutParams(layoutParams);

Categories

Resources