Как программно отображать Views в RelativeLayout?

Я пытаюсь достичь следующего программного (а не декларативно через XML):

<RelativeLayout...> <TextView ... android:id="@+id/label1" /> <TextView ... android:id="@+id/label2" android:layout_below: "@id/label1" /> </RelativeLayout> 

Другими словами, как сделать второй 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); 

Solutions Collecting From Web of "Как программно отображать Views в RelativeLayout?"

Из того, что мне удалось собрать вместе, вы должны добавить представление, используя 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, чтобы относительно позиционировать ваши предметы программно, вам нужно назначить им идентификаторы.

 TextView tv1 = new TextView(this); tv1.setId(1); TextView tv2 = new TextView(this); tv2.setId(2); 

Затем addRule(RelativeLayout.RIGHT_OF, tv1.getId());

Сократите длинную короткую историю: с относительным расположением вы размещаете элементы внутри макета.

  1. Создать новый RelativeLayout.LayoutParams

     RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(...) 

    (Независимо от того, … заполнить родительский или обертку содержимым, абсолютные числа, если нужно, или ссылку на XML-ресурс)

  2. Добавить правила: Правила относятся к родителям или к другим «братьям» в иерархии.

     lp.addRule(RelativeLayout.BELOW, someOtherView.getId()) lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT) 
  3. Просто примените параметры макета: самый «здоровый» способ сделать это:

     parentLayout.addView(myView, lp) 

Остерегайтесь : не изменяйте макет из обратных вызовов макета. Заманчиво это делать, потому что это – то, когда взгляды получают их фактические размеры. Однако в этом случае ожидаются неожиданные результаты.

Просто провел 4 часа с этой проблемой. Наконец понял, что вы не должны использовать нуль в качестве идентификатора вида . Вы могли бы подумать, что это разрешено как NO_ID == -1, но вещи, как правило, уходят с толку, если вы дадите это вашему взгляду …

вызов

 tv1.setId(1) 

после

 tv1.setText("A"); 

Пытаться:

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

Протестировано на 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 ... Репозиторий GitHub с минимальным кодом сборки .

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

Если вы действительно хотите создать макет вручную, я бы предложил не использовать стандартный макет вообще. Сделайте все это самостоятельно, вот пример 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) } } 

Это может дать вам представление о том, как это может работать