Android - dynamiczne dodawanie widoków do widoku

148

Mam układ do widoku -

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

To, co chcę robić, to moja główna działalność z takim układem

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

Chcę przejrzeć mój model danych i wstawić wiele widoków składających się z pierwszego układu do głównego układu. Wiem, że mogę to zrobić, budując kontrolki całkowicie w kodzie, ale zastanawiałem się, czy istnieje sposób na dynamiczne budowanie widoków, aby móc dalej używać układu zamiast umieszczać wszystko w kodzie.

Josh
źródło
Możesz sprawdzić odpowiedź na ten stackoverflow.com/questions/3995215/ ...
Tell Me How

Odpowiedzi:

230

Użyj, LayoutInflateraby utworzyć widok na podstawie szablonu układu, a następnie wstaw go do widoku, w którym jest potrzebny.

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

Konieczne może być dostosowanie indeksu, w którym chcesz wstawić widok.

Dodatkowo ustaw LayoutParams zgodnie z tym, jak chcesz, aby pasował do widoku nadrzędnego. np. z FILL_PARENT, lub MATCH_PARENTitp.

Mark Fisher
źródło
2
tam gdzie chcesz umieścić dynamicznie generowany układ w głównym widoku. to jest bit, który musisz wypełnić z własnego kodu.
Mark Fisher,
Dla tych, którzy chcą to teraz wypróbować - inflator układu uzyskany, jak pokazano w pierwszej linii, nadal działa, ale wydaje się, że nie działa, zamiast tego użyjgetLayoutInflater()
Brendan
2
Użyj LayoutInflater vi = getLayoutInflater();z działania, aby zachować motyw działania, którego nie otrzymasz w inny sposób.
akarthik10,
1
@MrG Powinieneś zadać osobne pytanie w sprawie SO. To pytanie dotyczy tego, jak dynamicznie tworzyć widoki, a nie fragmenty.
Mark Fisher
2
@Arsh Jeśli masz nowe pytanie i konkretny problem, zadaj osobne pytanie SO szczegółowo opisujące, jaki kod wypróbowałeś, a który nie działa, zamiast komentować tutaj.
Mark Fisher,
36

Zobacz LayoutInflaterklasę.

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
źródło
jak dodać onClicklistener do zawyżonych widoków osób. Proszę podać fragment
Sagar Devanga
14

Aby odpowiedź @Marka Fishera była jaśniejsza, wstawiany widok, który jest zawyżany, powinien być plikiem xml w folderze układu, ale bez układu (ViewGroup), takiego jak LinearLayout itp. W środku. Mój przykład:

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

Następnie punkt wstawiania powinien mieć układ podobny do 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>

Wtedy powinien być kod

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

Powodem, dla którego publikuję tę bardzo podobną odpowiedź, jest to, że kiedy próbowałem wdrożyć rozwiązanie Marka, utknąłem w tym, jakiego pliku xml powinienem użyć dla insert_point i widoku potomnego. Najpierw użyłem układu w widoku dziecka i całkowicie nie działał, co zajęło mi kilka godzin. Mam więc nadzieję, że moja eksploracja pozwoli zaoszczędzić czas innym.

York Yang
źródło
@York Yang, jak mogę dodać tutaj identyfikatory vies, jeśli dodamy więcej niż jeden widok za pomocą pętli for.
Rahul Kushwaha
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
źródło
1
Chociaż ten fragment kodu może być rozwiązaniem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod.
yivi
Jak mogę uzyskać identyfikatory różnych widoków utworzonych za pomocą pętli For.
Rahul Kushwaha