Comment mettre en forme des vues dans RelativeLayout par programmation?

J’essaie d’atteindre le suivant par programmation (plutôt que de manière déclarative via XML):

    

En d’autres termes, comment faire apparaître le second TextView sous le premier, mais je veux le faire en code:

 RelativeLayout layout = new RelativeLayout(this); TextView label1 = new TextView(this); TextView label2 = new TextView(this); ... layout.addView(label1); layout.addView(label2); setContentView(layout); 

Mettre à jour:

Merci, TreeUK. Je comprends la direction générale, mais cela ne fonctionne toujours pas – “B” chevauche “A”. Qu’est-ce que je fais mal?

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

D’après ce que j’ai pu reconstituer, vous devez append la vue en utilisant 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); 

Tout crédit à sechastain, pour positionner vos articles par programmation, vous devez leur atsortingbuer des identifiants.

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

Puis addRule(RelativeLayout.RIGHT_OF, tv1.getId());

Coupez court à la longue histoire: avec une disposition relative, vous positionnez les éléments dans la mise en page.

  1. créer un nouveau RelativeLayout.LayoutParams

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

    (peu importe … remplir le contenu parent ou wrap, les nombres absolus si vous devez, ou la référence à une ressource XML)

  2. Ajouter des règles: les règles font référence au parent ou à d’autres “frères” dans la hiérarchie.

     lp.addRule(RelativeLayout.BELOW, someOtherView.getId()) lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT) 
  3. Appliquez simplement les parameters de mise en page: La manière la plus «saine» de le faire est:

     parentLayout.addView(myView, lp) 

Attention : ne modifiez pas la disposition des rappels de mise en page. Il est tentant de le faire car c’est à ce moment que les vues obtiennent leur taille réelle. Cependant, dans ce cas, des résultats inattendus sont attendus.

Je viens de passer 4 heures avec ce problème. Enfin réalisé que vous ne devez pas utiliser zéro comme vue id . On pourrait penser qu’il est autorisé sous la forme NO_ID == -1, mais les choses ont tendance à s’embrouiller si vous le donnez à votre avis …

Android 22 exemple minimal d’exécution

entrer la description de l'image ici

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

Fonctionne avec le projet par défaut généré par android create project ... Référentiel GitHub avec code de construction minimal .

appel

 tv1.setId(1) 

après

 tv1.setText("A"); 

Essayer:

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

Cette approche avec ViewGroup.MarginLayoutParams a fonctionné pour moi:

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

Si vous souhaitez vraiment mettre en page manuellement, je vous suggérerais de ne pas utiliser de mise en page standard. Faites-le vous-même, voici un exemple de kotlin:

 class ProgrammaticalLayout @JvmOverloads constructor(context: Context, attrs: AtsortingbuteSet? = 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) } } 

Cela pourrait vous donner une idée de la façon dont cela pourrait fonctionner