Android - 动态添加视图到视图中

162

我有一个视图的布局 -

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="0px"
    android:orientation="vertical">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/items_header"
        style="@style/Home.ListHeader" />

    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/items_none"
        android:visibility="gone"
        style="@style/TextBlock"
        android:paddingLeft="6px" />

    <ListView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/items_list" />


</LinearLayout>

我想要做的是,在我的主活动中使用这样的布局

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="0px"
    android:id="@+id/item_wrapper">
</LinearLayout>

我想循环遍历我的数据模型并将由第一个布局组成的多个视图注入到主布局中。我知道可以通过完全在代码中构建控件来实现这一点,但我想知道是否有一种动态构建视图的方法,以便我可以继续使用布局而不是把所有内容都放在代码中。


你可以在 https://dev59.com/7G865IYBdhLWcg3wFqdV#43465331 查看答案。 - Tell Me How
5个回答

250
使用 LayoutInflater 来基于布局模板创建一个视图,然后将其注入到需要它的视图中。
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.your_layout, null);

// fill in any details dynamically here
TextView textView = (TextView) v.findViewById(R.id.a_text_view);
textView.setText("your text");

// insert into main view
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.insert_point);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));

您可能需要调整要插入视图的索引。

此外,根据您想要在父视图中的适合程度设置LayoutParams。例如使用FILL_PARENTMATCH_PARENT等。


2
这是你想要将动态生成的布局放置在主视图中的位置。这就是你需要从自己的代码中填充的部分。 - Mark Fisher
1
对于那些想现在尝试的人 - 仍以第一行显示的方式获得的布局充气机似乎不能工作,而应该使用 getLayoutInflater() - Brendan
3
在活动中使用 LayoutInflater vi = getLayoutInflater(); 可以保留活动主题,否则你将无法获得该主题。 - akarthik10
在我的视图中,我有一个文本视图和一个图像,它们最初的可见性为“gone”。现在,在动态添加后,我在循环内设置其可见性为可见,但它不起作用。 - pa1pal

39

请查看LayoutInflater类。

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup parent = (ViewGroup)findViewById(R.id.where_you_want_to_insert);
inflater.inflate(R.layout.the_child_view, parent);

1
在 Kotlin 中,使用绑定时,整个过程可以转换为一行代码,如下所示: layoutInflater.inflate(R.layout.layout_you_want_to_add, binding.layoutInWhichYouWanToAdd) 就是这样。感谢您的回答。 - Kashif Masood

20

16
为了让@Mark Fisher的回答更清晰,被插入的视图应该是一个在布局文件夹下但没有像LinearLayout等内部布局(ViewGroup)的xml文件。我的例子:

res/layout/my_view.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/i_am_id"
    android:text="my name"
    android:textSize="17sp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

然后,插入点应该是像LinearLayout这样的布局:

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/aaa"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/insert_point"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </LinearLayout>

</RelativeLayout>
然后代码应该是:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shopping_cart);

    LayoutInflater inflater = getLayoutInflater();
    View view = inflater.inflate(R.layout.my_view, null);
    ViewGroup main = (ViewGroup) findViewById(R.id.insert_point);
    main.addView(view, 0);
}

我发表这个非常相似的答案的原因是当我尝试实现马克的解决方案时,我卡在了应该使用哪个xml文件来插入点和子视图上。我首先在子视图中使用布局,但完全不起作用,这花费了我几个小时才弄清楚。所以希望我的探索可以节省其他人的时间。


14
// Parent layout
LinearLayout parentLayout = (LinearLayout)findViewById(R.id.layout);

// Layout inflater
LayoutInflater layoutInflater = getLayoutInflater();
View view;

for (int i = 1; i < 101; i++){
    // Add the text layout to the parent layout
    view = layoutInflater.inflate(R.layout.text_layout, parentLayout, false);

    // In order to get the view we have to use the new view with text_layout in it
    TextView textView = (TextView)view.findViewById(R.id.text);
    textView.setText("Row " + i);

    // Add the text view to the parent layout
    parentLayout.addView(textView);
}

1
虽然这段代码可能是解决方案,但包括解释真的有助于提高您的帖子质量。记住,您正在回答未来读者的问题,那些人可能不知道您建议代码的原因。 - yivi
它是否正常工作,但之后只获取最后一个textView ID。 - Sandeep Pareek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接