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.