Android 以编程方式将视图添加到线性布局中

Android 以编程方式将视图添加到线性布局中,android,fragment,android-linearlayout,Android,Fragment,Android Linearlayout,我试图在线性布局中模拟ListView,以便显示具有相同布局的三行。此单一视图由分级栏和内容栏组成。这很奇怪,但所有的分级栏都会收到最后一个赋值。首先,这是我的自定义组件,它扩展了LinearLayout,只添加了以下两种方法: public void setElements(List<Item> elements) { removeAllViews(); for (int i = 0; i < elements.size() && i <

我试图在线性布局中模拟ListView,以便显示具有相同布局的三行。此单一视图由分级栏和内容栏组成。这很奇怪,但所有的分级栏都会收到最后一个赋值。首先,这是我的自定义组件,它扩展了LinearLayout,只添加了以下两种方法:

public void setElements(List<Item> elements) {
    removeAllViews();
    for (int i = 0; i < elements.size() && i < 3; i++) {
        View vi = buildElementView(elements.get(i));
        vi.setId(i);
        addView(vi);
    }
}

private View buildElementView(Item itemElement) {
    View view = inflater.inflate(R.layout.element_list_item, null, true);
    // set values
    View header = view.findViewById(R.id.header);
    RatingBar ratingInItem = (RatingBar) header.findViewById(R.id.ratingBarInItem);
    TextView content = (TextView) view.findViewById(R.id.content);

    content.setText(itemElement.getContent());

    ratingInItem.setRating(itemElement.getRating());
    return view;
}

谢谢

我认为您使用的findViewById()视图错误,导致了问题

这是一个基于您正在做的工作的示例,对我来说很有用

LinearLayout ll = (LinearLayout)findViewById(R.id.ll);
ViewGroup parentGroup = parentGroup = (ViewGroup)ll;

for (int i = 0; i < 3; i++)
{
    LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.element_list_item, null, true);
    RatingBar rBar = (RatingBar)view.findViewById(R.id.ratingBar1);
    rBar.setProgress(i);
    parentGroup.addView(view);
}
然后,您可以在onCreateView中获取参数并恢复数据(如果需要)

片段开始时效果很好,但当我尝试旋转手机时,项目内容会正确更改,但分级栏会获得最后一个值(如果有3个元素的分级为1、2和3,则所有分级栏都有三星)。是虫子吗

这不是一个bug——这是Android的工作原理

为什么会发生这种情况?

默认情况下,系统将保存和恢复具有ID的视图的状态,并使用这些ID维护状态的内部映射。由于您在
线性布局中使用相同的布局
,因此每个子级都有一个ID为
ratingBarInItem
分级栏
。当系统保存视图的状态时,它会保存第一个栏的状态,然后用第二个栏覆盖它,然后用第三个栏覆盖该状态。然后,当您恢复状态时,它会将ID为
ratingBarInItem
的每个视图恢复为状态图中的视图-这将是最后保存的值,即第三项中的值

如何解决此问题?

你有两个选择

  • 手动保存并恢复视图的状态
  • 显示您已经在保存视图中的“元素”。那么,您可以更新
    onrestoreinnstancestate
    以读取这些元素,然后使用它们重新更新子视图(即,再次调用
    setElements

  • 为每个评级栏指定一个唯一的ID
  • 将子视图充气以添加到布局后,使用创建一个新的唯一ID,您可以在每个
    分级栏上设置该ID

    RatingBar ratingInItem = (RatingBar) header.findViewById(R.id.ratingBarInItem);
    ratingInItem.setID(View.generateViewID());
    
    这样,您就不必实现保存或恢复状态,因为现在每个视图都有一个唯一的ID,默认的系统行为将起作用


    希望有帮助

    当活动被终止时,您如何保存分级?分级从网络中检索并使用OnSaveInstanceState保存。您可以共享代码的这一部分吗?(实例)
    LinearLayout ll = (LinearLayout)findViewById(R.id.ll);
    ViewGroup parentGroup = parentGroup = (ViewGroup)ll;
    
    for (int i = 0; i < 3; i++)
    {
        LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.element_list_item, null, true);
        RatingBar rBar = (RatingBar)view.findViewById(R.id.ratingBar1);
        rBar.setProgress(i);
        parentGroup.addView(view);
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        getFragmentManager().putFragment(outState, Content.class.getName(), this);
    }
    
    Bundle extras = this.getArguments();
    if(extras != null)
    {
        //set arguments here
    }
    
    RatingBar ratingInItem = (RatingBar) header.findViewById(R.id.ratingBarInItem);
    ratingInItem.setID(View.generateViewID());