Programmgesteuertes Hinzufügen von Ansichten zu Ansichten

177

Angenommen, ich habe eine LinearLayoutin meinem Programm aus dem Java-Code und möchte dieser eine Ansicht hinzufügen. Welche Methode wird dafür verwendet? Ich frage nicht, wie es in XML gemacht wird, was ich weiß, sondern wie ich etwas in Anlehnung an diesen Beispielcode tun kann.

(One View).add(Another View)

Wie man es in Swing machen kann.

Moki
quelle

Antworten:

246

Anrufen addViewist die richtige Antwort, aber Sie müssen etwas mehr tun, damit es funktioniert.

Wenn Sie eine Ansicht über einen Konstruktor erstellen (z. B. Button myButton = new Button();), müssen Sie setLayoutParamsdie neu erstellte Ansicht aufrufen und eine Instanz der inneren Klasse LayoutParams der übergeordneten Ansicht übergeben, bevor Sie Ihr neu erstelltes untergeordnetes Element zur übergeordneten Ansicht hinzufügen.

Beispielsweise könnte der folgende Code in Ihrer onCreate()Funktion enthalten sein, vorausgesetzt, Ihr LinearLayout hat die ID 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);

Es ist wichtig, dass Sie die LayoutParams festlegen. Jede Ansicht benötigt mindestens einen Parameter layout_width und einen layout_height. Es ist auch wichtig, die richtige innere Klasse zu finden. Ich hatte Probleme damit, Ansichten zu einer TableRow hinzuzufügen, damit sie ordnungsgemäß angezeigt werden, bis ich herausfand, dass ich keine Instanz von TableRow.LayoutParams an die setLayoutParams der untergeordneten Ansicht übergeben habe.

Brian Cooley
quelle
4
Wie würden Sie die Ansicht programmgesteuert erstellen, aber eine XML-Layoutdatei verwenden, die Sie speziell für diese neue Ansicht geschrieben haben?
SK9
8
@ SK9 Sie würden einen LayoutInflater verwenden, den Sie aus einem Kontext abrufen können, normalerweise der aktuellen Aktivität. So etwas wie: LayoutInflater myInflater = getLayoutInflater; View myView = myInflater.inflate (R.layout.myLayout, parent, false);
Brian Cooley
1
Tatsächlich stammt getLayoutInflater () aus der Window-Klasse (nicht aus Context) und ist eine praktische Methode in Activity.
Brian Cooley
2
Als Codierungspraxis können Sie in findViewById in ViewGroup oder immer die allgemeinste Form eines Objekts umwandeln, sodass Sie bei einem Wechsel von einem linearen Layout zu einem relativen Layout kein Refactoring durchführen müssen.
Joel Teply
Dies sind einige Details: D
Vivek Solanki
50

für alle, die noch interessiert sind:

Der beste Weg, den ich gefunden habe, ist die Verwendung der statischen Aufblasmethode von View.

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

Dabei ist yourViewXML so etwas wie R.layout.myView

Bitte beachten Sie, dass Sie eine ViewGroup benötigen, um eine Ansicht hinzuzufügen (dies ist jedes Layout, das Sie sich vorstellen können).

Nehmen wir als Beispiel an, Sie haben ein Fragment, dessen Ansicht bereits aufgeblasen wurde, und Sie wissen, dass die Stammansicht ein Layout ist, und Sie möchten ihm eine Ansicht hinzufügen:

    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
quelle
Sie könnten auch eine statische Methode schreiben, so etwas addView(View v){ // your code after get view }würde eine Ansicht annehmen, die mit findViewById(int resourceID)Ihrer inflatedView... gefunden oder aufgeblasen wurde, nur um Ihr Fragmentbeispiel zu erweitern.
zgc7009
22

Dies ist spät, aber dies kann jemandem helfen :) :) Um die Ansicht programmgesteuert hinzuzufügen, versuchen Sie es wie

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

Dadurch wird Ihre gesamte Ansicht programmgesteuert erstellt. Sie können beliebig viele Ansichten hinzufügen. Hoffe das kann helfen. :) :)

AndroidOptimist
quelle
2

Eine weitere Möglichkeit, eine Ansicht aus der Aktivität hinzuzufügen

ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
yoAlex5
quelle
0

Die Idee, Einschränkungen programmgesteuert festzulegen, kann lästig sein. Diese Lösung funktioniert für jedes Layout, egal ob Einschränkung, linear usw. Der beste Weg wäre, einen Platzhalter, dh ein FrameLayout mit geeigneten Einschränkungen (oder die richtige Platzierung in einem anderen Layout wie z. B. linear), an der Position festzulegen, an der Sie die programmgesteuert erstellte Ansicht erwarten würden haben.

Alles, was Sie tun müssen, ist, die Ansicht programmgesteuert und als untergeordnetes Element mithilfe der addChild()Methode in das FrameLayout aufzublasen . Dann wird Ihre Sicht zur Laufzeit aufgeblasen und in die richtige Position gebracht. Gemäß der Android-Empfehlung sollten Sie FrameLayout nur eine untergeordnete Ansicht hinzufügen [Link] .

So würde Ihr Code aussehen, vorausgesetzt, Sie möchten TextView programmgesteuert an einer bestimmten Position erstellen:

Schritt 1:

Platzieren Sie in Ihrem Layout, das die aufzublasende Ansicht enthalten würde, ein FrameLayout an der richtigen Position und geben Sie ihm eine ID, z. B. "Container".

Schritt 2 Erstellen Sie ein Layout mit dem Stammelement als Ansicht, die Sie zur Laufzeit aufblasen möchten. Rufen Sie die Layoutdatei als "textview.xml" auf:

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

Übrigens, setzen Sie die Layout-Parameter Ihres FrameLayout immer auf wrap_content, sonst wird das Frame-Layout so groß wie das übergeordnete Element, dh die Aktivität, dh der Telefonbildschirm.

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

Wenn nicht festgelegt, wird eine untergeordnete Ansicht des Rahmens standardmäßig links oben im Rahmenlayout angezeigt, sodass Ihre Ansicht einfach links oben auf dem Bildschirm angezeigt wird.

Schritt 3

Gehen Sie in Ihrer oncreate-Methode folgendermaßen vor:

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

(Beachten Sie, dass das Festlegen des letzten Parameters von findViewByIdto nullund das Hinzufügen einer Ansicht durch Aufrufen der addView()Containeransicht (frameLayout) dem einfachen Anhängen der aufgeblasenen Ansicht durch Übergeben truedes dritten Parameters von entspricht findViewById(). Weitere Informationen finden Sie hier .)

kush
quelle
0

Ihr solltet auch sicherstellen, dass ihr beim Überschreiben mit allen Eigenschaften onLayoutanrufen müsst, super.onLayoutsonst wird die Aussicht nicht aufgeblasen!

Oz Shabat
quelle