Jak programowo dodawać widoki do widoków

179

Powiedzmy, że mam LinearLayouti chcę dodać do niego Widok w moim programie z kodu Java. Jaka metoda jest do tego używana? Nie pytam, jak to się robi w XML, który znam, ale raczej, jak mogę zrobić coś zgodnie z tym przykładowym kodem?

(One View).add(Another View)

Jak można to zrobić w Swing.

Moki
źródło

Odpowiedzi:

248

Dzwonienie addViewto poprawna odpowiedź, ale musisz zrobić coś więcej, aby zadziałało.

Jeśli tworzysz View za pomocą konstruktora (np. Button myButton = new Button();), Będziesz musiał wywołać setLayoutParamsnowo skonstruowany widok, przekazując instancję wewnętrznej klasy LayoutParams widoku nadrzędnego, zanim dodasz nowo skonstruowane dziecko do widoku nadrzędnego.

Na przykład możesz mieć następujący kod w swojej onCreate()funkcji, zakładając, że Twój LinearLayout ma identyfikator R.id.main:

LinearLayout myLayout = findViewById(R.id.main);

Button myButton = new Button(this);
myButton.setLayoutParams(new LinearLayout.LayoutParams(
                                     LinearLayout.LayoutParams.MATCH_PARENT,
                                     LinearLayout.LayoutParams.MATCH_PARENT));

myLayout.addView(myButton);

Upewnij się, że ustawiłeś LayoutParams, jest ważne. Każdy widok wymaga co najmniej parametru layout_width i layout_height. Ważne jest również uzyskanie odpowiedniej klasy wewnętrznej. Miałem problemy z poprawnym wyświetlaniem widoków dodanych do TableRow, dopóki nie zorientowałem się, że nie przekazałem wystąpienia TableRow.LayoutParams do setLayoutParams widoku podrzędnego.

Brian Cooley
źródło
5
W jaki sposób można utworzyć widok programowo, ale przy użyciu pliku układu XML, który został napisany specjalnie dla tego nowego widoku?
SK9
9
@ SK9 Użyłbyś LayoutInflater, który można uzyskać z kontekstu, zwykle bieżącego działania. Coś takiego: LayoutInflater myInflater = getLayoutInflater; Wyświetl myView = myInflater.inflate (R.layout.myLayout, rodzic, fałsz);
Brian Cooley
1
W rzeczywistości getLayoutInflater () pochodzi z klasy Window (nie Context) i jest wygodną metodą w Activity.
Brian Cooley,
2
W ramach praktyki kodowania w przypadku findViewById rzutowanie na ViewGroup lub zawsze najbardziej ogólną formę obiektu, tak aby w przypadku zmiany z LinearLayout na RelativeLayout nie było refaktoryzacji.
Joel
1
Oto kilka szczegółów: D
Vivek Solanki
51

dla wszystkich jeszcze zainteresowanych:

najlepszym sposobem, jaki znalazłem, jest użycie statycznej metody inflate View.

View inflatedView = View.inflate(context, yourViewXML, yourLinearLayout);

gdzie yourViewXML jest czymś w rodzaju R.layout.myView

proszę zauważyć, że potrzebujesz ViewGroup, aby dodać widok (który jest dowolnym układem, jaki możesz wymyślić)

więc jako przykład powiedzmy, że masz fragment, który został już zawyżony i wiesz, że widok główny jest układem i chcesz dodać do niego widok:

    View view = getView(); // returns base view of the fragment
    if (view == null)
        return;
    if (!(view instanceof ViewGroup))
        return;

    ViewGroup viewGroup = (ViewGroup) view;
    View popup = View.inflate(viewGroup.getContext(), R.layout.someView, viewGroup);
ndori
źródło
Mógłbyś również napisać metodę statyczną, coś takiego addView(View v){ // your code after get view }, jak widok znaleziony przy użyciu findViewById(int resourceID)lub zawyżony jak twój inflatedView... tylko po to, aby rozwinąć przykład twojego fragmentu.
zgc7009
22

To już późno ale to może komuś pomóc :) :) Aby programowo dodać widok spróbuj polubić

LinearLayout rlmain = new LinearLayout(this);      
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);          
LinearLayout   ll1 = new LinearLayout (this);

ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.logo);              
LinearLayout .LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);

iv.setLayoutParams(lp);
ll1.addView(iv);
rlmain.addView(ll1);              
setContentView(rlmain, llp);

Spowoduje to programowe utworzenie całego widoku. Możesz dodać dowolną liczbę widoków tak samo. Mam nadzieję, że to może pomóc. :)

AndroidOptimist
źródło
3

Jeszcze jeden sposób dodawania widoku z działania

ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
yoAlex5
źródło
0

Pomysł programowego ustawiania ograniczeń może być męczący. Poniższe rozwiązanie będzie działać dla dowolnego układu, czy to z ograniczeniami, liniowymi, itp. Najlepszym sposobem byłoby ustawienie symbolu zastępczego, tj. FrameLayout z odpowiednimi ograniczeniami (lub odpowiednie umieszczenie w innym układzie, np. Liniowym) w miejscu, w którym można oczekiwać, że utworzony programowo widok mieć.

Wszystko, co musisz zrobić, to programowo zawyżać widok i jako element podrzędny w stosunku do FrameLayout przy użyciu addChild()metody method. Wtedy podczas działania widok byłby zawyżony i umieszczony we właściwej pozycji. Zgodnie z zaleceniem systemu Android należy dodać tylko jeden widok podrzędny do FrameLayout [link] .

Oto jak wyglądałby Twój kod, zakładając, że chcesz programowo utworzyć TextView w określonej pozycji:

Krok 1:

W swoim układzie, który zawiera widok, który ma być zawyżony, umieść FrameLayout we właściwej pozycji i nadaj mu identyfikator, powiedzmy „kontener”.

Krok 2 Utwórz układ z elementem głównym jako widokiem, który chcesz rozszerzyć w czasie wykonywania, wywołaj plik układu jako „textview.xml”:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

</TextView>

Przy okazji, ustaw parametry układu twojego frameLayout na wrap_content, w przeciwnym razie układ ramki będzie tak duży jak rodzic, tj. Aktywność, tj. Ekran telefonu.

android:layout_width="wrap_content"
android:layout_height="wrap_content"

Jeśli nie jest ustawione, ponieważ widok podrzędny ramki domyślnie przechodzi do lewej górnej części układu ramki, dlatego widok po prostu przeleci do lewej górnej części ekranu.

Krok 3

W swojej metodzie oncreate wykonaj następujące czynności:

FrameLayout frameLayout = findViewById(R.id.container);
                TextView textView = (TextView) View.inflate(this, R.layout.textview, null);
                frameLayout.addView(textView);

(Zwróć uwagę, że ustawienie ostatniego parametru findViewByIddo nulli dodanie widoku przez wywołanie addView()widoku kontenera (frameLayout) jest tym samym, co zwykłe dołączenie powiększonego widoku przez przekazanie truetrzeciego parametru z findViewById(). Aby uzyskać więcej informacji, zobacz to ).

kush
źródło
0

Powinniście również upewnić się, że kiedy nadpisujesz onLayout, MUSISZ wywołać super.onLayoutwszystkie właściwości, inaczej widok nie będzie zawyżony!

Oz Shabat
źródło