Adding dynamic views in a for loop leads to random positioning - Android

I dynamically add views to the relative layout (let’s say, the container) in a for loop. There is a strange thing that I notice.
When adding lines one by one in a relative layout in a for,, loop , I see that for the first time several views overlap. But when I lock and open the screen, I see that the views are placed correctly.

Do I have to understand something when dynamically adding views to a relative layout?

Edit
I found a solution on how to get rid of this (please check my answer). But I would be more than happy to accept an answer that analyzes this problem and tells me why this is happening. I have simplified the code and the comments should give a good idea of ​​what I am doing.

int prev_id=ID_OF_THE_ELEMENT_ABOVE; /*Empty RelativeView with width and height as MATCH_PARENT and WRAP_CONTENT respectively*/ RelativeLayout container=(RelativeLayout) findViewById(R.id.container); while(ThereIsData){ /*GET THE DATA HERE THAT HAS TO BE ASSIGNED TO EACH TEXTVIEW*/ ... /* ADD TEXTVIEW #1 below prev_id/ ... ... /*ADD TEXTVIEW #2 (WITH BASELINE OF TEXTVIEW# ... ... /*TEXTVIEW #3 (BELOW TEXTVIEW#1)*/ ... ... /*TEXTVIEW #4 (BELOW TEXTVIEW#2)*/ ... ... /*ASSIGN THE ID OF TEXTVIEW#3 TO prev_id SO THAT IN THE NEXT ITERATION TEXTVIEW#1 CAN USE prev_id */ prev_id=ID(TEXTVIEW#2); /*ADD TEXTVIEWS CREATED IN THIS ITERATION*/ container.addView(TEXTVIEW#1); container.addView(TEXTVIEW#2); container.addView(TEXTVIEW#3); container.addView(TEXTVIEW#4); } 
+8
android
source share
5 answers

This is because you have a RelativeLayout with height as WRAP_CONTENT , and adding a view does not refresh the entire container at this time .. since you answered, you can add line to measure dimensions explicitly or invalidate to completely recreate it.

In any case LinearLayout it would be better to choose a LinearLayout , as it would automatically arrange the children in the horizontal or vertical style, and you can even add a new view anywhere except the last position, and it will be automatically updated.

+4
source share

I used to deal with common problems a year ago when I was working on a library for dynamically creating layouts from XML files (since Android does not support this). Therefore, when you dynamically add views to a RelativeLayout , you need to keep in mind a few things:

  • Create a View container (in this case, RelativeLayout )
  • Create all views without assigning any layout options.
  • Add all child views to the container.
  • Iterate over the children of the container and populate each child layout. This is necessary because when relational constraints are applied, Excpetion is created if there is no relative View (previously not added to the container).

This is an example of code taken from a project I was working on. Keep in mind that this is just one part, so it contains references to classes that are not defined in the Android API. I am sure this will give you the basic idea of ​​dynamically creating a RelativeLayot :

 private void setChildren(RelativeLayout layout, T widget, InflaterContext inflaterContext, Context context, Factory<Widget, View> factory) { List<Widget> children = widget.getChildren(); if (Utils.isEmpty(children))) { return; } // 1. create all children for (Widget child : children) { View view = factory.create(inflaterContext, context, child); layout.addView(view); } // 2. Set layout parameters. This is done all children are created // because there are relations between children. for (Widget child : children) { try { View view = ViewIdManager.getInstance().findViewByName(layout, child.getId()); if (view != null) { populateLayoutParmas(child, view); } } catch (IndexNotFoundException e) { Log.e(LOG_TAG, "Cannot find a related view for " + child.getId(), e); } } } 
+1
source share

Try adding your views to the vertical linear layout. The following link may help you.

http://www.myandroidsolutions.com/2012/06/19/android-layoutinflater-turorial/

Fill your layout in a loop.

0
source share

I have not yet found the answer to the question of why this is happening. But I found a solution. After adding each line in the loop, call container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT); This seems to solve the problem. But I really think that container.addView() should also call measure() .

 /*ADD TEXTVIEWS CREATED IN THIS ITERATION*/ container.addView(TEXTVIEW#1); container.addView(TEXTVIEW#2); container.addView(TEXTVIEW#3); container.addView(TEXTVIEW#4); //--------------------------------------------------------------------- container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT); 
0
source share

 //Declare globally LinearLayout[] layout; ImageView[] imageView1; ImageView[] imageView2; ImageView[] imageView3; // Initialize your layout. It would be RelativeLayout too. Just reference to it. LinearLayout ll = (LinearLayout) findViewById(R.id.mylinear); // set listview row size as your demand layout = new LinearLayout[200]; imageView1 = new ImageView[200]; imageView2 = new ImageView[200]; imageView3 = new ImageView[200]; for (int i = 0; i < 200; i++) { layout[i] = new LinearLayout(this); layout[i].setBackgroundResource(R.drawable.book_shelf); // layout[i].setLayoutParams(new // LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.FILL_PARENT, // 120)); layout[i].setLayoutParams(new LinearLayout.LayoutParams( android.widget.LinearLayout.LayoutParams.FILL_PARENT, 220)); imageView1[i] = new ImageView(this); imageView2[i] = new ImageView(this); imageView3[i] = new ImageView(this); imageView1[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200, 0.33f)); imageView1[i].setPadding(0, 20, 0, 0); imageView1[i].setImageResource(R.drawable.bibid_one_bankim); imageView2[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200, 0.33f)); imageView2[i].setPadding(0, 20, 0, 0); imageView2[i].setImageResource(R.drawable.bibid_two_bankim); imageView3[i].setLayoutParams(new LinearLayout.LayoutParams(0, 200, 0.33f)); imageView3[i].setImageResource(R.drawable.dena_pawna); imageView3[i].setPadding(0, 20, 0, 0); layout[i].setId(i); layout[i].setClickable(true); final int j = i; layout[i].addView(imageView1[i]); layout[i].addView(imageView2[i]); layout[i].addView(imageView3[i]); ll.addView(layout[i]); } } 
0
source share

All Articles