Android 如何以编程方式在 RelativeLayout 中布置视图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2305395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to lay out Views in RelativeLayout programmatically?
提问by Dan
I'm trying to achieve the following programmatically (rather than declaratively via XML):
我正在尝试以编程方式(而不是通过 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:
换句话说,如何让第二个TextView
出现在第一个下方,但我想在代码中做到这一点:
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?
谢谢,TreeUK。我理解大方向,但它仍然不起作用 - “B”与“A”重叠。我究竟做错了什么?
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);
回答by Tristan Warner-Smith
From what I've been able to piece together, you have to add the view using LayoutParams.
从我已经能够拼凑起来的内容来看,您必须使用 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.
所有功劳都归功于 sechastain,要以编程方式相对定位您的项目,您必须为它们分配 id。
TextView tv1 = new TextView(this);
tv1.setId(1);
TextView tv2 = new TextView(this);
tv2.setId(2);
Then addRule(RelativeLayout.RIGHT_OF, tv1.getId());
然后 addRule(RelativeLayout.RIGHT_OF, tv1.getId());
回答by Meymann
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)
创建一个新的 RelativeLayout.LayoutParams
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(...)
(无论如何……填写父内容或包装内容,如果必须,请使用绝对数字,或对 XML 资源的引用)
添加规则:规则引用层次结构中的父级或其他“兄弟”。
lp.addRule(RelativeLayout.BELOW, someOtherView.getId()) lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
只需应用布局参数:最“健康”的方法是:
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.
注意:不要从布局回调中更改布局。这样做很诱人,因为这是视图获得实际大小的时候。但是,在这种情况下,会出现意想不到的结果。
回答by fastfox
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...
刚刚花了4个小时解决这个问题。终于意识到你不能使用零作为视图 id。你会认为它被允许为 NO_ID == -1,但如果你把它交给你的观点,事情往往会变得混乱......
回答by user299870
call
称呼
tv1.setId(1)
after
后
tv1.setText("A");
回答by Phant?maxx
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);
回答by Gene Bo
This approach with ViewGroup.MarginLayoutParams worked for me:
ViewGroup.MarginLayoutParams 的这种方法对我有用:
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);
回答by Richa
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);
}
}
回答by martyglaubitz
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:
如果你真的想手动布局,我建议根本不要使用标准布局。自己做这一切,这里有一个 kotlin 示例:
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
这可能会让你知道这是如何工作的