Android - Adicionar vistas dinamicamente à vista

148

Eu tenho um layout para uma visualização -

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

O que eu quero fazer é na minha atividade principal com um layout como este

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

Quero fazer um loop no meu modelo de dados e injetar várias visualizações que consistem no primeiro layout no layout principal. Eu sei que posso fazer isso criando os controles completamente dentro do código, mas queria saber se havia uma maneira de criar dinamicamente os modos de exibição para que eu possa continuar usando um layout em vez de colocar tudo no código.

Josh
fonte
Você pode verificar a resposta para este stackoverflow.com/questions/3995215/…
Diga-me como

Respostas:

230

Use o LayoutInflaterpara criar uma vista com base no seu modelo de layout e injete-a na vista onde você precisar.

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

Talvez você precise ajustar o índice onde deseja inserir a exibição.

Além disso, defina o LayoutParams de acordo com como você deseja que ele caiba na visualização pai. por exemplo FILL_PARENT, com , ou MATCH_PARENTetc.

Mark Fisher
fonte
2
é onde você deseja colocar o layout gerado dinamicamente em sua visualização principal. esse é o bit que você precisa preencher com seu próprio código.
Mark Fisher
Para aqueles que querem tentar fazer isso agora - o inflador disposição obtido como mostrado na primeira linha ainda resolve mas não aparece para trabalhar, em vez usargetLayoutInflater()
Brendan
2
Use a LayoutInflater vi = getLayoutInflater();partir de uma atividade para preservar o tema da atividade que você não vê de outra forma.
akarthik10
1
@ MrG Você deve fazer uma pergunta separada sobre SO. Esta pergunta é sobre como criar visualizações dinamicamente, não sobre fragmentos.
Mark
2
@Arsh Se você tiver uma nova pergunta e um problema específico, faça uma pergunta SO separada, detalhando qual código você tentou e que não está funcionando, em vez de comentar aqui.
Mark Fisher
36

Veja a LayoutInflaterturma.

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);
Gabriel Negut
fonte
Como faço para adicionar onClicklistener às visualizações individuais que foram infladas
favor
14

Para tornar a resposta de @Mark Fisher mais clara, a exibição inserida que está sendo inflada deve ser um arquivo xml na pasta de layout, mas sem um layout (ViewGroup) como LinearLayout etc. Meu exemplo:

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

Em seguida, o ponto de inserção deve ser um layout como 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>

Então o código deve ser

@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);
}

A razão pela qual eu postei essa resposta muito semelhante é que, quando tentei implementar a solução de Mark, fiquei presa em qual arquivo xml devo usar para insert_point e a visualização filho. Primeiro, usei o layout na exibição infantil e ele não estava funcionando totalmente, o que levou várias horas para descobrir. Portanto, espero que minha exploração possa economizar o tempo dos outros.

York Yang
fonte
@York Yang, como posso adicionar IDs de vies aqui se adicionarmos mais de uma visualização usando o loop for.
Rahul Kushwaha 14/05/19
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);
}
Tienanhvn
fonte
1
Embora esse snippet de código possa ser a solução, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código.
yivi
Como posso obter IDs de diferentes visualizações criadas usando o For Loop.
Rahul Kushwaha 14/05/19