I putting an in-game chat module into an app. I am adding text messages as they are received into a LinearLayout view. I want to set the layout params to the TextView but the following code is crashing and the error messages befuddle me.
private void addChat(String chat, String when, Boolean mine) {
int leftMargin;
TextView tv = new TextView(this);
llview.addView(tv);
tv.setTextColor(Color.WHITE);
tv.setTextSize(2,25);
tv.setText(chat);
if (mine) {
leftMargin = 5;
tv.setBackgroundColor(0x7C5B77);
}
else {
leftMargin = 50;
tv.setBackgroundColor(0x778F6E);
}
final ViewGroup.MarginLayoutParams lpt =(MarginLayoutParams)tv.getLayoutParams();
lpt.setMargins(leftMargin,lpt.topMargin,lpt.rightMargin,lpt.bottomMargin);
tv.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
}
when it runs, all of the above code executes but it crashes in android runtime as:
03-13 14:15:38.513: E/AndroidRuntime(12985): java.lang.ClassCastException: android.view.ViewGroup$LayoutParams
and stepping through with the debugger, it actually processes all of these lines
but then barfs when trying to render with an equally cryptic exception detailed message:
android.view.ViewGroup$LayoutParams
So, what have done to get to this state? What should I be doing to have alternating left/right indented messages ?
Just replace from bottom and add this
tv.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
before
llview.addView(tv);
after creating the view we have to add layout parameters .
change like this
TextView tv = new TextView(this);
tv.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
llview.addView(tv);
tv.setTextColor(Color.WHITE);
tv.setTextSize(2,25);
tv.setText(chat);
if (mine) {
leftMargin = 5;
tv.setBackgroundColor(0x7C5B77);
}
else {
leftMargin = 50;
tv.setBackgroundColor(0x778F6E);
}
final ViewGroup.MarginLayoutParams lpt =(MarginLayoutParams)tv.getLayoutParams();
lpt.setMargins(leftMargin,lpt.topMargin,lpt.rightMargin,lpt.bottomMargin);
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
/*width*/ ViewGroup.LayoutParams.MATCH_PARENT,
/*height*/ ViewGroup.LayoutParams.MATCH_PARENT,
/*weight*/ 1.0f
);
YOUR_VIEW.setLayoutParams(param);
int dp1 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
context.getResources().getDisplayMetrics());
tv.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
dp1 * 100)); // if you want to set layout height to 100dp
llview.addView(tv);
For Xamarin Android
align to the left of an object
int dp24 = (int)TypedValue.ApplyDimension( ComplexUnitType.Dip, 24, Resources.System.DisplayMetrics );
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams( dp24, dp24 );
lp.AddRule( LayoutRules.CenterInParent, 1 );
lp.AddRule( LayoutRules.LeftOf, //Id of the field Eg m_Button.Id );
m_Button.LayoutParameters = lp;
Related
I am able to control the height but somehow it does not make any difference to the button width.
// Table Row for Previous button
TableRow tableRow1 = new TableRow(this);
tableRow1.setLayoutParams(new TableRow.LayoutParams(
TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT));
tableRow1.setPadding(5, 5, 5, 5);
// Button - Previous
Button btnPrev = new Button(this);
btnPrev.setText("< Previous");
btnPrev.setGravity(Gravity.CENTER);
btnPrev.setOnClickListener(prevListener);
tableRow1.addView(btnPrev);
android.view.ViewGroup.LayoutParams params = btnPrev.getLayoutParams();
params.height = 20;
params.width = 60;
btnPrev.setLayoutParams(params);
// TextView for Previous button
TextView textView11 = new TextView(this);
textView11.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
textView11.setGravity(Gravity.CENTER_VERTICAL);
textView11.setGravity(Gravity.RIGHT);
textView11.setPadding(0, 0, 20, 0);
textView11.setText("New Entry Form");
tableRow1.addView(textView11);
android.view.ViewGroup.LayoutParams params1 = textView11
.getLayoutParams();
params1.height = (int) dipHeight;
textView11.setLayoutParams(params1);
tableLayout.addView(tableRow1);
I tried changing few things here and there but no look.
Can someone from you take a time and help me on this?
// replace this code
tableRow1.addView(btnPrev);
android.view.ViewGroup.LayoutParams params = btnPrev.getLayoutParams();
params.height = 20;
params.width = 60;
btnPrev.setLayoutParams(params);
to
tableRow1.addView(btnPrev,new android.view.ViewGroup.LayoutParams(20,60));
to set button width & height use below code
btnPrev.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
btnPrev.setwidth(60);
btnPrev.setheight(20);
You can set button width in two ways:
Via java :
Button.setWidth(int width);
Via XML properties :
<Button android:layout_height="wrap_content"
android:id="#+id/ButtonPrev"
android:layout_below="#id/output"
android:text="7"
android:minWidth="100dp">
</Button>
The property : android:minWidth will set the width of the button.
Reference : Set width of Button in Android
View.requestLayout() maybe what you want?
this is my code, but dont know why its returning null? however i can put a null check here, but is there anything wrong?
TextView descriptiontv = (TextView) findViewById(R.id.descriptiontv);
TextView tc = new TextView(c);
final PopupWindow windowPopUp = new PopupWindow(tc,LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT ,false);
tc.setBackgroundResource(R.drawable.bg_training_baloon_hc_2x);
tc.setText("this is a demo test to check how it looks, i m just wanting to test whether it works or not");
tc.setPadding(20, 20, 20, 20);
LinearLayout.LayoutParams params = new android.widget.LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
params.setMargins(30, 0, 30, 0);
tc.setLayoutParams(params);
Based on my experience, you have to add the view to its parent view first before you can set the layout parameters for it, like so:
TextView calendarYear = new TextView(getActivity());
calendarYear.setText(calendar.getYear() + "");
calendarYear.setTextSize(20);
calendarYear.setTypeface(null, Typeface.BOLD);
calendarYear.setGravity(Gravity.CENTER);
calendarYear.setTextColor(resources.getColor(android.R.color.black));
calendarItemsLinearLayout.addView(calendarYear);
// We have to add the TextView to the layout first before we
// can set the layout margins for it
ViewGroup.LayoutParams layoutParams = calendarYear.getLayoutParams();
((LinearLayout.LayoutParams)layoutParams).setMargins(0, (int)(16 * density), 0, 0);
calendarYear.setLayoutParams(layoutParams);
Here
tc.getLayoutParams()
you haven't given it any params yet so it will return null. Maybe you meant
descriptiontv.getLayoutParams()
Edit
Try changing
params.leftMargin = 30;
params.rightMargin = 30;
to
params.setMargins(30, 0, 30, 0);
And change
LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams)tc.getLayoutParams();
to
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
If I use xml file I have a option called layout_margin (for example layout_margin ="1dp" for text view ) but I want to set programmatically and I dont know how to do it.
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)textview.getLayoutParams();
params.setMargins(20, 0, 0, 0);
textview.setLayoutParams(params);
Please Google before adding your question to StackOverflow.
TextView tv = (TextView)findViewById(R.id.my_text_view);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)tv.getLayoutParams();
params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
tv.setLayoutParams(params);
Note, that not all LayoutParams has method setMargins();
RelativeLayout, LinearLayout etc has their own inner class LayoutParams, so availability of setMargins is not always available.
You can do by this:
TextView text = (TextView) findViewById(R.id.text);
LinearLayout.LayoutParams params= new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(left, top, right, bottom);//pass int values for left,top,right,bottom
text.setLayoutParams(params);
TextView tv = (TextView) findViewById(R.id.tvId);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
llp.setMargins(50, 0, 0, 0); // llp.setMargins(left, top, right, bottom);
tv.setLayoutParams(llp);
Try This: It worked...
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, 10, 0, 0);
firstName.setLayoutParams(params);
You can use the setMargins() on the LinearLayout.LayoutParams. See the answer of this StackOverflow question for more information.
TextView tv = (TextView)findViewById(R.id.item_title));
RelativeLayout.LayoutParams mRelativelp = (RelativeLayout.LayoutParams) tv
.getLayoutParams();
mRelativelp.setMargins(DptoPxConvertion(15), 0, DptoPxConvertion (15), 0);
tv.setLayoutParams(mRelativelp);
private int DptoPxConvertion(int dpValue)
{
return (int)((dpValue * mContext.getResources().getDisplayMetrics().density) + 0.5);
}
getLayoutParams() of textview should be casted to the corresponding Params based on the Parent of the textview in xml.
<RelativeLayout>
<TextView
android:id="#+id/item_title">
</RelativeLayout>
If parent of the TextView is RelativeLayout means, then RelativeLayout.LayoutParams as above. If parent is LinearLayout means then
LinearLayout.LayoutParams mLinearlp = (LinearLayout.LayoutParams) tv
.getLayoutParams();
To render the same real size on different devices use DptoPxConvertion() method which I have used above. setMargin(left,top,right,bottom) params will take values in pixel not in dp.
I'm trying to achieve the following programmatically (rather than declaratively via XML):
<RelativeLayout...>
<TextView ...
android:id="#+id/label1" />
<TextView ...
android:id="#+id/label2"
android:layout_below: "#id/label1" />
</RelativeLayout>
In other words, how do I make the second TextView appear below the first one, but I want to do it in code:
RelativeLayout layout = new RelativeLayout(this);
TextView label1 = new TextView(this);
TextView label2 = new TextView(this);
...
layout.addView(label1);
layout.addView(label2);
setContentView(layout);
Update:
Thanks, TreeUK. I understand the general direction, but it still doesn't work - "B" overlaps "A". What am I doing wrong?
RelativeLayout layout = new RelativeLayout(this);
TextView tv1 = new TextView(this);
tv1.setText("A");
TextView tv2 = new TextView(this);
tv2.setText("B");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.FILL_PARENT);
lp.addRule(RelativeLayout.RIGHT_OF, tv1.getId());
layout.addView(tv1);
layout.addView(tv2, lp);
From what I've been able to piece together, you have to add the view using LayoutParams.
LinearLayout linearLayout = new LinearLayout(this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
parentView.addView(linearLayout, relativeParams);
All credit to sechastain, to relatively position your items programmatically you have to assign ids to them.
TextView tv1 = new TextView(this);
tv1.setId(1);
TextView tv2 = new TextView(this);
tv2.setId(2);
Then addRule(RelativeLayout.RIGHT_OF, tv1.getId());
Cut the long story short:
With relative layout you position elements inside the layout.
create a new RelativeLayout.LayoutParams
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(...)
(whatever... fill parent or wrap content, absolute numbers if you must, or reference to an XML resource)
Add rules:
Rules refer to the parent or to other "brothers" in the hierarchy.
lp.addRule(RelativeLayout.BELOW, someOtherView.getId())
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
Just apply the layout params: The most 'healthy' way to do that is:
parentLayout.addView(myView, lp)
Watch out: Don't change layout from the layout callbacks. It is tempting to do so because this is when views get their actual sizes. However, in that case, unexpected results are expected.
Just spent 4 hours with this problem. Finally realized that you must not use zero as view id. You would think that it is allowed as NO_ID == -1, but things tend to go haywire if you give it to your view...
Android 22 minimal runnable example
Source:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RelativeLayout relativeLayout = new RelativeLayout(this);
final TextView tv1;
tv1 = new TextView(this);
tv1.setText("tv1");
// Setting an ID is mandatory.
tv1.setId(View.generateViewId());
relativeLayout.addView(tv1);
// tv2.
final TextView tv2;
tv2 = new TextView(this);
tv2.setText("tv2");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.FILL_PARENT);
lp.addRule(RelativeLayout.BELOW, tv1.getId());
relativeLayout.addView(tv2, lp);
// tv3.
final TextView tv3;
tv3 = new TextView(this);
tv3.setText("tv3");
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
lp2.addRule(RelativeLayout.BELOW, tv2.getId());
relativeLayout.addView(tv3, lp2);
this.setContentView(relativeLayout);
}
}
Works with the default project generated by android create project .... GitHub repository with minimal build code.
call
tv1.setId(1)
after
tv1.setText("A");
Try:
EditText edt = (EditText) findViewById(R.id.YourEditText);
RelativeLayout.LayoutParams lp =
new RelativeLayout.LayoutParams
(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT
);
lp.setMargins(25, 0, 0, 0); // move 25 px to right (increase left margin)
edt.setLayoutParams(lp); // lp.setMargins(left, top, right, bottom);
This approach with ViewGroup.MarginLayoutParams worked for me:
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.my_layout);
TextView someTextView = ...
int leftMargin = Util.getXPos();
int topMargin = Util.getYPos();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
new ViewGroup.MarginLayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
lp.setMargins(leftMargin, topMargin, 0, 0);
myLayout.addView(someTextView, lp);
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
final RelativeLayout relativeLayout = new RelativeLayout(this);
final TextView tv1 = new TextView(this);
tv1.setText("tv1 is here");
// Setting an ID is mandatory.
tv1.setId(View.generateViewId());
relativeLayout.addView(tv1);
final TextView tv2 = new TextView(this);
tv2.setText("tv2 is here");
// We are defining layout params for tv2 which will be added to its parent relativelayout.
// The type of the LayoutParams depends on the parent type.
RelativeLayout.LayoutParams tv2LayoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
//Also, we want tv2 to appear below tv1, so we are adding rule to tv2LayoutParams.
tv2LayoutParams.addRule(RelativeLayout.BELOW, tv1.getId());
//Now, adding the child view tv2 to relativelayout, and setting tv2LayoutParams to be set on view tv2.
relativeLayout.addView(tv2);
tv2.setLayoutParams(tv2LayoutParams);
//Or we can combined the above two steps in one line of code
//relativeLayout.addView(tv2, tv2LayoutParams);
this.setContentView(relativeLayout);
}
}
If you really want to layout manually, i'd suggest not to use a standard layout at all. Do it all on your own, here a kotlin example:
class ProgrammaticalLayout #JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ViewGroup(context, attrs, defStyleAttr) {
private val firstTextView = TextView(context).apply {
test = "First Text"
}
private val secondTextView = TextView(context).apply {
text = "Second Text"
}
init {
addView(firstTextView)
addView(secondTextView)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
// center the views verticaly and horizontaly
val firstTextLeft = (measuredWidth - firstTextView.measuredWidth) / 2
val firstTextTop = (measuredHeight - (firstTextView.measuredHeight + secondTextView.measuredHeight)) / 2
firstTextView.layout(firstTextLeft,firstTextTop, firstTextLeft + firstTextView.measuredWidth,firstTextTop + firstTextView.measuredHeight)
val secondTextLeft = (measuredWidth - secondTextView.measuredWidth) / 2
val secondTextTop = firstTextView.bottom
secondTextView.layout(secondTextLeft,secondTextTop, secondTextLeft + secondTextView.measuredWidth,secondTextTop + secondTextView.measuredHeight)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// just assume we`re getting measured exactly by the parent
val measuredWidth = MeasureSpec.getSize(widthMeasureSpec)
val measuredHeight = MeasureSpec.getSize(heightMeasureSpec)
firstTextView.measures(MeasureSpec.makeMeasureSpec(meeasuredWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
secondTextView.measures(MeasureSpec.makeMeasureSpec(meeasuredWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
setMeasuredDimension(measuredWidth, measuredHeight)
}
}
This might give you an idea how this could work
I'm trying to achieve the following programmatically (rather than declaratively via XML):
<RelativeLayout...>
<TextView ...
android:id="#+id/label1" />
<TextView ...
android:id="#+id/label2"
android:layout_below: "#id/label1" />
</RelativeLayout>
In other words, how do I make the second TextView appear below the first one, but I want to do it in code:
RelativeLayout layout = new RelativeLayout(this);
TextView label1 = new TextView(this);
TextView label2 = new TextView(this);
...
layout.addView(label1);
layout.addView(label2);
setContentView(layout);
Update:
Thanks, TreeUK. I understand the general direction, but it still doesn't work - "B" overlaps "A". What am I doing wrong?
RelativeLayout layout = new RelativeLayout(this);
TextView tv1 = new TextView(this);
tv1.setText("A");
TextView tv2 = new TextView(this);
tv2.setText("B");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.FILL_PARENT);
lp.addRule(RelativeLayout.RIGHT_OF, tv1.getId());
layout.addView(tv1);
layout.addView(tv2, lp);
From what I've been able to piece together, you have to add the view using LayoutParams.
LinearLayout linearLayout = new LinearLayout(this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
parentView.addView(linearLayout, relativeParams);
All credit to sechastain, to relatively position your items programmatically you have to assign ids to them.
TextView tv1 = new TextView(this);
tv1.setId(1);
TextView tv2 = new TextView(this);
tv2.setId(2);
Then addRule(RelativeLayout.RIGHT_OF, tv1.getId());
Cut the long story short:
With relative layout you position elements inside the layout.
create a new RelativeLayout.LayoutParams
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(...)
(whatever... fill parent or wrap content, absolute numbers if you must, or reference to an XML resource)
Add rules:
Rules refer to the parent or to other "brothers" in the hierarchy.
lp.addRule(RelativeLayout.BELOW, someOtherView.getId())
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
Just apply the layout params: The most 'healthy' way to do that is:
parentLayout.addView(myView, lp)
Watch out: Don't change layout from the layout callbacks. It is tempting to do so because this is when views get their actual sizes. However, in that case, unexpected results are expected.
Just spent 4 hours with this problem. Finally realized that you must not use zero as view id. You would think that it is allowed as NO_ID == -1, but things tend to go haywire if you give it to your view...
Android 22 minimal runnable example
Source:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RelativeLayout relativeLayout = new RelativeLayout(this);
final TextView tv1;
tv1 = new TextView(this);
tv1.setText("tv1");
// Setting an ID is mandatory.
tv1.setId(View.generateViewId());
relativeLayout.addView(tv1);
// tv2.
final TextView tv2;
tv2 = new TextView(this);
tv2.setText("tv2");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.FILL_PARENT);
lp.addRule(RelativeLayout.BELOW, tv1.getId());
relativeLayout.addView(tv2, lp);
// tv3.
final TextView tv3;
tv3 = new TextView(this);
tv3.setText("tv3");
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
lp2.addRule(RelativeLayout.BELOW, tv2.getId());
relativeLayout.addView(tv3, lp2);
this.setContentView(relativeLayout);
}
}
Works with the default project generated by android create project .... GitHub repository with minimal build code.
call
tv1.setId(1)
after
tv1.setText("A");
Try:
EditText edt = (EditText) findViewById(R.id.YourEditText);
RelativeLayout.LayoutParams lp =
new RelativeLayout.LayoutParams
(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT
);
lp.setMargins(25, 0, 0, 0); // move 25 px to right (increase left margin)
edt.setLayoutParams(lp); // lp.setMargins(left, top, right, bottom);
This approach with ViewGroup.MarginLayoutParams worked for me:
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.my_layout);
TextView someTextView = ...
int leftMargin = Util.getXPos();
int topMargin = Util.getYPos();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
new ViewGroup.MarginLayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
lp.setMargins(leftMargin, topMargin, 0, 0);
myLayout.addView(someTextView, lp);
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
final RelativeLayout relativeLayout = new RelativeLayout(this);
final TextView tv1 = new TextView(this);
tv1.setText("tv1 is here");
// Setting an ID is mandatory.
tv1.setId(View.generateViewId());
relativeLayout.addView(tv1);
final TextView tv2 = new TextView(this);
tv2.setText("tv2 is here");
// We are defining layout params for tv2 which will be added to its parent relativelayout.
// The type of the LayoutParams depends on the parent type.
RelativeLayout.LayoutParams tv2LayoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
//Also, we want tv2 to appear below tv1, so we are adding rule to tv2LayoutParams.
tv2LayoutParams.addRule(RelativeLayout.BELOW, tv1.getId());
//Now, adding the child view tv2 to relativelayout, and setting tv2LayoutParams to be set on view tv2.
relativeLayout.addView(tv2);
tv2.setLayoutParams(tv2LayoutParams);
//Or we can combined the above two steps in one line of code
//relativeLayout.addView(tv2, tv2LayoutParams);
this.setContentView(relativeLayout);
}
}
If you really want to layout manually, i'd suggest not to use a standard layout at all. Do it all on your own, here a kotlin example:
class ProgrammaticalLayout #JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ViewGroup(context, attrs, defStyleAttr) {
private val firstTextView = TextView(context).apply {
test = "First Text"
}
private val secondTextView = TextView(context).apply {
text = "Second Text"
}
init {
addView(firstTextView)
addView(secondTextView)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
// center the views verticaly and horizontaly
val firstTextLeft = (measuredWidth - firstTextView.measuredWidth) / 2
val firstTextTop = (measuredHeight - (firstTextView.measuredHeight + secondTextView.measuredHeight)) / 2
firstTextView.layout(firstTextLeft,firstTextTop, firstTextLeft + firstTextView.measuredWidth,firstTextTop + firstTextView.measuredHeight)
val secondTextLeft = (measuredWidth - secondTextView.measuredWidth) / 2
val secondTextTop = firstTextView.bottom
secondTextView.layout(secondTextLeft,secondTextTop, secondTextLeft + secondTextView.measuredWidth,secondTextTop + secondTextView.measuredHeight)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// just assume we`re getting measured exactly by the parent
val measuredWidth = MeasureSpec.getSize(widthMeasureSpec)
val measuredHeight = MeasureSpec.getSize(heightMeasureSpec)
firstTextView.measures(MeasureSpec.makeMeasureSpec(meeasuredWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
secondTextView.measures(MeasureSpec.makeMeasureSpec(meeasuredWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
setMeasuredDimension(measuredWidth, measuredHeight)
}
}
This might give you an idea how this could work