在for循环中动态添加视图会导致偶然定位 - Android

时间:2015-05-11 12:06:04

标签: android

我在for循环中动态地将视图添加到相对布局(让他们说容器)。我注意到有些奇怪的事情。
当在for循环中的相对布局中逐行添加行时,我看到第一次有几个视图重叠。但是当我锁定并解锁屏幕时,我可以看到视图放置正确。

在将视图动态添加到相对布局时,我应该注意什么吗?

修改
我找到了一个解决方法,如何摆脱这个(请检查我的答案)。但我很乐意接受一个分析这个问题的答案并告诉我为什么会发生这种情况。

我已经简化为代码,评论应该对我正在做的事情有个好主意。

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

5 个答案:

答案 0 :(得分:4)

这是因为您RelativeLayout height WRAP_CONTENTmeasure,并且添加视图时不会刷新整个容器。在您的回答中,您可以明确地向invalidate维度添加一行,或者在LinearLayout视图中添加一行以完全重新创建。

在任何情况下horizontal最好选择加入,因为它会自动以verticalnamespace WebApplication2.Models { public class tableData1 { public string Name { get; set; } public string Location { get; set; } public string Time { get; set; } } } 方式安排孩子,您甚至可以在任何其他地方添加新视图比上一个位置,它会自动更新..

答案 1 :(得分:1)

我曾经在一年前遇到过常见问题,当时我正在开发一个库,用于从XML文件动态创建布局(因为Android不支持此功能)。因此,当您向RelativeLayout动态添加视图时,您必须考虑以下几点:

  1. 创建容器View(在本例中为RelativeLayout
  2. 创建所有视图而不指定任何布局参数。
  3. 将所有子视图添加到容器中。
  4. 迭代容器的子项并填充每个子项的布局参数。这是必需的,因为当应用关系约束时,如果缺少相对Excpetion(之前未添加到容器中),则抛出View
  5. 这是从我以前工作的项目中获取的示例代码。请记住,它只是一个部分,因此它包含对未在Android API中定义的类的引用。我相信它会为您提供动态创建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);
            }
        }
    }
    

答案 2 :(得分:0)

尝试在垂直线性布局中添加视图。 以下链接可能对您有所帮助

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

为for循环充气你的布局。

答案 3 :(得分:0)

我还没有找到为什么会发生这种情况的答案。但我找到了解决方案。在循环中添加每一行后,请致电container.measure(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT); 这似乎解决了这个问题。但我真的认为container.addView()也应该调用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); 

答案 4 :(得分:0)

&#13;
&#13;
   
//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]);
		}
	}
&#13;
&#13;
&#13;