首页 文章

如何以编程方式在RelativeLayout中布局视图?

提问于
浏览
224

我试图以编程方式实现以下(而不是通过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);

9 回答

  • 1

    从我能够拼凑到一起,您必须使用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());

  • 5

    简而言之:通过相对布局,您可以在布局中定位元素 .

    • 创建一个新的RelativeLayout.LayoutParams
    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(...)
    

    (无论如何......填充父级或包装内容,绝对数字,如果必须,或引用XML资源)

    • 添加规则:规则指的是层次结构中的父级或其他“兄弟” .
    lp.addRule(RelativeLayout.BELOW, someOtherView.getId())
    lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
    
    • 只需应用布局参数:最“ Health ”的方法是:
    parentLayout.addView(myView, lp)
    

    Watch out :不要从布局回调中更改布局 . 这样做很诱人,因为这是视图获得实际尺寸的时候 . 但是,在这种情况下,预计会出现意外结果 .

  • 2

    刚刚花了4个小时解决这个问题 . 终于意识到你 must not use zero as view id . 你会认为它被允许为NO_ID == -1,但如果你把它放到你的视野中,事情往往会变得混乱......

  • 3

    Android 22 minimal runnable example

    enter image description here

    资源:

    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 ... 生成的默认项目 . GitHub repository with minimal build code .

  • 192

    呼叫

    tv1.setId(1)
    

    tv1.setText("A");
    
  • 59

    尝试:

    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);
    
  • 0

    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);
    
  • 29
    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);
        }
    
    }
    
  • 7

    如果你真的想手动布局,我建议根本不要使用标准布局 . 自己动手做,这里有一个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)
        }
    }
    

    这可能会让您了解这是如何工作的

相关问题