Android : How to programmatically set layout_constraintRight_toRightOf "parent" - android

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.

Related

how to MODIFY a constraint layout programmatically?

Ive got a view like below :
<org.rayanmehr.atlas.shared.customview.CustomTextView
android:id="#+id/tvDownVoteCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
app:layout_constraintVertical_bias="0"
app:layout_constraintTop_toBottomOf="#+id/anchorHelper"
app:layout_constraintLeft_toRightOf="#+id/tvDownVoteIcon"
app:layout_constraintBottom_toBottomOf="#+id/imgComment"
/>
how can i modify the value of app:layout_constraintVertical_bias or any other constraint property programmatically without having top set the whole set of the properties again in my activity ?
Here is what I did (no need for ConstraintSet, we can work directly on the constraints themselves):
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) myView.getLayoutParams();
params.horizontalBias = 0.2f; // here is one modification for example. modify anything else you want :)
myView.setLayoutParams(params); // request the view to use the new modified params
it worked like a charm when I had a SeekBar and a TextView below it (aligned to it both left+right), and I wanted to update the TextView position to be under the SeekBar's cursor, so I had to update the horizontal bias params on the SeekBar's OnSeekBarChangeListener
If you are using Kotlin and you have androidx-core-ktx lib you can simply do:
someView.updateLayoutParams<ConstraintLayout.LayoutParams> { horizontalBias = 0.5f }
I just found the answer in here and you can use ConstraintSet to achieve this like below:
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(context, R.id.activity_constraint);
//for example lets change the vertical bias of tvDownVoteIcon
float biasedValue = 0.2f;
constraintSet.setVerticalBias(R.id.tvDownVoteIcon, biasedValue);
//or change the anchor
constraintSet.connect
(R.id.tvDownVoteIcon,ConstraintSet.RIGHT,R.id.txt,ConstraintSet.RIGHT,0);
//then apply
constraintSet.applyTo( (ConstraintLayout) findViewById(R.id.activity_constraint));
Disclaimer: I haven't used this specific functionality. This is just my interpretation on how I would try to do it.
I think that what you need is ConstraintSet. After obtaining it, you could modify it and apply it again. This is a relevant example from this article.
override fun onCreate(savedInstanceState: Bundle?) {
...
val constraintSet1 = ConstraintSet()
constraintSet1.clone(constraintLayout)
val constraintSet2 = ConstraintSet()
constraintSet2.clone(constraintLayout)
constraintSet2.centerVertically(R.id.image, 0)
var changed = false
findViewById(R.id.button).setOnClickListener {
TransitionManager.beginDelayedTransition(constraintLayout)
val constraint = if (changed) constraintSet1 else constraintSet2
constraint.applyTo(constraintLayout)
changed = !changed
}
}

How to access parent in ConstraintLayout

I am using ConstraintLayout to create a view programmatically and I want to set my button view topTotop of parent and leftToleft of the parent. How can I do that?
My code is below:
Button button = new Button(MainActivity.this);
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(widthInt, heightInt);
params.topToTop = // I want to set it parent
params.leftToLeft = // I want to set it parent
params.setMargins(marginStartint , marginTopInt , 0 , 0);
button.setLayoutParams(params);
You can use PARENT_ID
so your code becomes
params.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
params.leftToLeft = ConstraintLayout.LayoutParams.PARENT_ID;
You can use ConstraintSet's Connect method to perform such operations. There PARENT_ID to refer parent id.
ConstraintLayout layout = (ConstraintLayout)fndViewById(R.id.mainConstraint);
ConstraintSet set = new ConstraintSet();
set.clone(layout);
set.connect(view.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, 0);
//view refers to the view's constraint to be changed
set.applyTo(layout);
connect
void connect (int startID,
int startSide,
int endID,
int endSide,
int margin)
Create a constraint between two widgets.

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

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

Change Guideline percentage in constraint layout programmatically

I have a guideline in constraint layout like this
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/guideline8"
app:layout_constraintGuide_percent="0.5"
android:orientation="vertical"/>
Later I want to change the app:layout_constraintGuide_percent value to something else conditionally. How can I achieve this.
There is two ways to do it:
Using ConstraintLayout.LayoutParams
This method get a specific parameter from the ConstraintLayout and modify it.
Guideline guideLine = (Guideline) findViewById(R.id.your_guideline);
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) guideLine.getLayoutParams();
params.guidePercent = 0.45f; // 45% // range: 0 <-> 1
guideLine.setLayoutParams(params);
Using ConstraintSet
This method consists in cloning the ConstraintLayout attributes, modifying them and then applying to the View.
BUT it's very slow.
ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.your_constraint_with_guideline);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout);
constraintSet.setGuidelinePercent(R.id.your_guideline, 0.07f); // 7% // range: 0 <-> 1
TransitionManager.beginDelayedTransition(constraintLayout);
constraintSet.applyTo(constraintLayout);
Creating a parallax effect
To test those methods I created a parallax animation using a GuideLine and a ScrollView on top.
On the AndroidManifest.xml, inside your Activity, add this: android:hardwareAccelerated="true".
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:hardwareAccelerated="true">
...
MainActivity.java
Guideline guideTopInfo;
ConstraintLayout constraintLayout;
ConstraintLayout.LayoutParams params;
ConstraintSet constraintSet;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
guideTopInfo = (Guideline) findViewById(R.id.guideline2);
constraintLayout = (ConstraintLayout) findViewById(R.id.constraint_root);
params = (ConstraintLayout.LayoutParams) guideTopInfo.getLayoutParams();
//constraintSet = new ConstraintSet();
//constraintSet.clone(constraintLayout);
final ScrollView scrollView = (ScrollView) findViewById(R.id.scroll_front);
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
float percentage = scrollView.getScrollY() * 0.0001f; // 0.001f faster // 0.00001f slower parallax animation
Log.d("mLog", String.valueOf(percentage));
if(percentage >= 0) {
// my XML percentage value was 12%
params.guidePercent = 0.12f - percentage; // up
//params.guidePercent = 0.12f + percentage; // downm
guideTopInfo.setLayoutParams(params);
//constraintSet.setGuidelinePercent(R.id.guideline2, 0.12f - percentage);
//TransitionManager.beginDelayedTransition(constraintLayout);
//constraintSet.applyTo(constraintLayout);
}
}
});
}
My other answer about parallax if anyone is interested. ;)
This code will change you guidePercent to 0
ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) guideline.getLayoutParams();
lp.guidePercent = 0;
guideline.setLayoutParams(lp);
guideline.setGuidelinePercent(value: Float)
This is enough to change the guideline percent during runtime.
you cam make it center doing it worked with me i hope it helps
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintGuide_percent="0.5"
app:layout_constraintStart_toStartOf="parent" />
You need to use ConstraintSet object to set layout_constraintGuide_percent in code.
Below is the code to set layout_constraintGuide_percent in code. First you need to create constraint set object, call clone method passing constraintlayout and then call setGuidelinePercent passing guideline id and ratio.
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(constraintLayout);
constraintSet.setGuidelinePercent(R.id.guideline, 0.4f);
In Kotlin & inside Fragment or other activities,set GuideLine app: related parameters has a little difficulty , but I Solved it in this way :
val view = inflate(this, R.layout.ly_custom_menu_item_wallet_side_menu, null)
val guideL = view.findViewById<Guideline>(R.id.guideline_wallet)
var constParam: ConstraintLayout.LayoutParams = guideL.layoutParams as ConstraintLayout.LayoutParams
constParam.guidePercent = 0.42f
guideL.layoutParams = constParam
and this is Guideline element inside our ly_custom_menu_item_wallet_side_menu.xml layout :
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/guideline_wallet"
android:orientation="vertical"
app:layout_constraintGuide_end="84dp" />

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

Categories

Resources