如何以编程方式在RelativeLayout中布局视图?
我试图通过编程实现以下(而不是通过XML声明):
<RelativeLayout...> <TextView ... android:id="@+id/label1" /> <TextView ... android:id="@+id/label2" android:layout_below: "@id/label1" /> </RelativeLayout>
换句话说,如何让第二个TextView
出现在第一个TextView
下面,但我想在代码中做到这一点:
RelativeLayout layout = new RelativeLayout(this); TextView label1 = new TextView(this); TextView label2 = new TextView(this); ... layout.addView(label1); layout.addView(label2); setContentView(layout);
更新:
谢谢,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);
从我已经能够拼凑在一起,你必须使用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);
所有功劳sechastain,相对地定位你的项目编程,你必须分配ID给他们。
TextView tv1 = new TextView(this); tv1.setId(1); TextView tv2 = new TextView(this); tv2.setId(2);
然后addRule(RelativeLayout.RIGHT_OF, tv1.getId());
长话短说:使用相对布局,您可以在布局中定位元素。
-
创build一个新的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)
注意 :不要更改布局callback的布局。 这是很诱人的,因为这是视图获得实际大小的时候。 但是,在这种情况下,预期会有意想不到的结果。
刚刚花了4个小时,这个问题。 最后意识到你不能使用零作为view id 。 你会认为它可以作为NO_ID == -1,但是如果你把它提供给你的观点,事情往往会变得不合时宜。
呼叫
tv1.setId(1)
后
tv1.setText("A");
Android 22最小的可运行示例
资源:
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); } }
与android create project ...
生成的默认项目一起android create project ...
。 GitHub仓库与最小的构build代码 。
尝试:
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);
这个方法与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);
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); } }
如果你真的想手动布局,我build议不要使用标准的布局。 一个人做这一切,这里是一个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) } }
这可能会给你一个想法如何可以工作