Android - динамически добавлять представления в представление


148

У меня есть макет для просмотра -

<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>

Я хочу пройтись по моей модели данных и добавить несколько представлений, состоящих из первого макета, в основной макет. Я знаю, что могу сделать это, полностью построив элементы управления в коде, но мне было интересно, есть ли способ динамически создавать представления, чтобы я мог продолжать использовать макет вместо того, чтобы помещать все в код.


Вы можете проверить ответ для этого stackoverflow.com/questions/3995215/…
Расскажите мне, как

Ответы:


230

Используйте 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_PARENTили MATCH_PARENT, и т. д.


2
это то место, где вы хотите разместить динамически создаваемый макет на главном экране. это бит, который вы должны заполнить из своего собственного кода.
Марк Фишер

Для тех, кто хочет попробовать это сейчас - инфлятор макета, полученный, как показано в первой строке, все еще разрешается, но, похоже, не работает, вместо этого используйтеgetLayoutInflater()
Brendan

2
Используйте LayoutInflater vi = getLayoutInflater();из действия, чтобы сохранить тему действия, которую вы не получите иначе.
akarthik10

1
@MrG Вы должны поднять отдельный вопрос о SO. Этот вопрос о том, как динамически создавать представления, а не о фрагментах.
Марк Фишер

2
@ Arsh Если у вас есть новый вопрос и конкретная проблема, поднимите отдельный вопрос SO, подробно описывающий, какой код вы пробовали, который не работает, вместо того, чтобы комментировать здесь.
Марк Фишер

36

Смотрите 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);

Как я могу добавить onClicklistener к завышенным представлениям людей.
Пожалуйста,

20

Похоже, что вы действительно хотите ListView с пользовательским адаптером, чтобы надуть указанный макет. Используя ArrayAdapter и метод, notifyDataSetChanged()вы получаете полный контроль над генерацией и рендерингом Views.

Взгляните на эти уроки


14

Чтобы сделать ответ @Mark Fisher более понятным, вставляемый вид должен быть раздувным xml-файлом в папке макета, но без макета (ViewGroup), такого как LinearLayout и т. Д. Внутри. Мой пример:

разреш / макет / 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:

разреш / макет / 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-файл я должен использовать для insert_point и дочернего представления. Сначала я использовал макет в детском представлении, и он полностью не работал, что потребовало несколько часов, чтобы понять. Поэтому надеюсь, что мое исследование может сэкономить время других.


@York Yang, как мне добавить Id's vies, если мы добавим более одного представления, используя цикл for.
Рахул Кушваха

5
// 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

Как я могу получить идентификаторы различных представлений, созданных с помощью For Loop.
Рахул Кушваха
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.