【问题标题】:Programmatically add view into a LinearLayout以编程方式将视图添加到 LinearLayout
【发布时间】:2012-04-06 15:02:48
【问题描述】:

我正在尝试在 LinearLayout 中模拟 ListView,以显示具有相同布局的三行。这个单一视图由一个评分栏和一个内容组成。这很奇怪,但是所有的 ratingBars 都会收到最后一个分配的值。首先这是我的自定义组件,它扩展了 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;
}

这是我正在膨胀的布局:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.weorder.client"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@color/transparent"
    android:minHeight="60.0dp"
    android:orientation="vertical"
    android:paddingBottom="8.0dp"
    android:paddingLeft="5.0dp"
    android:paddingRight="5.0dp"
    android:paddingTop="8.0dp" >

    <RelativeLayout
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <RatingBar
            android:id="@+id/ratingBarInItem"
            style="@style/RatingBarSm"
            android:isIndicator="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:numStars="5"
            android:stepSize="0.1" />

    </RelativeLayout>

    <TextView
        android:id="@+id/content"
        style="@style/Content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:layout_marginTop="3dp"

        android:textColor="@color/dark_brown"
        android:textSize="@dimen/text_size_small" />

 </LinearLayout>

我在片段的 onActivityCreated() 中调用 setElements 方法。片段开始时效果很好,但是当我尝试旋转手机时,项目的内容会正确更改,但评分栏会获得最后一个值(如果有 3 个元素的评分为 1,2 和 3,则所有评分栏都有 3 颗星) .是bug吗?

编辑:这是我的 onSaveInstanceMethod:

    @Override
public void onSaveInstanceState(Bundle outState) {

    if (elements != null) {
        outState.putSerializable("elements", elements);
    }

    super.onSaveInstanceState(outState);
}

谢谢

【问题讨论】:

  • Activity被杀死时如何保存评分?
  • 评分从网络中检索并使用 onsaveinstancestate 保存
  • 你能分享那部分代码吗? (onaveinstance)

标签: android fragment android-linearlayout


【解决方案1】:

我认为您使用 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);
}

根据您设置评分栏的方式,结果应显示三个评分栏,分别为 0 星、1 星和 2 星。 我将新视图附加到视图父级三次。父级是我的线性布局,新视图是评分栏(或您选择的任何内容)。

为了保存在片段中使用

@Override
public void onSaveInstanceState(Bundle outState)
{
    super.onSaveInstanceState(outState);
    getFragmentManager().putFragment(outState, Content.class.getName(), this);
}

然后您可以在 onCreateView 中获取您的参数并恢复您的数据(如果需要)

Bundle extras = this.getArguments();
if(extras != null)
{
    //set arguments here
}

【讨论】:

    【解决方案2】:

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

    这不是错误 - 这就是 Android 的工作原理。

    为什么会这样?

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

    你如何解决这个问题?

    你有两个选择。

    1. 自己手动保存和恢复视图的状态。

    您表明您已经在保存视图中的“元素”。好吧,您可以更新 onRestoreInstanceState 以读取这些元素,然后使用它们重新更新子视图(即,只需再次调用 setElements)。

    1. 为每个评分栏指定一个唯一 ID。

    膨胀子视图以添加到布局后,使用 generateViewID 创建一个新的唯一 ID,您可以在每个 RatingBar 上设置。

    RatingBar ratingInItem = (RatingBar) header.findViewById(R.id.ratingBarInItem);
    ratingInItem.setID(View.generateViewID());
    

    那么您不必实现保存或恢复状态,因为现在每个视图都有一个唯一的 ID,默认的系统行为将起作用。

    希望有帮助!

    【讨论】:

      猜你喜欢
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-09
      • 2017-06-28
      相关资源
      最近更新 更多