Как программно добавлять представления в представления

179

Допустим, у меня есть LinearLayoutи я хочу добавить к нему представление в моей программе из кода Java. Какой метод используется для этого? Я не спрашиваю, как это делается в XML, который я знаю, но, скорее, как я могу сделать что-то вроде этого примера кода?

(One View).add(Another View)

Как можно сделать в Swing.

Moki
источник

Ответы:

248

Вызов addViewявляется правильным ответом, но вам нужно сделать немного больше, чтобы заставить его работать.

Если вы создаете представление с помощью конструктора (например, Button myButton = new Button();), вам необходимо вызвать setLayoutParamsвновь созданное представление, передавая экземпляр внутреннего класса LayoutParams родительского представления, прежде чем добавить вновь созданный дочерний элемент в родительское представление.

Например, вы могли бы иметь следующий код в своей onCreate()функции, предполагая, что ваш LinearLayout имеет идентификатор 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);

Важно установить LayoutParams. Каждому представлению требуется как минимум layout_width и параметр layout_height. Также важно получить правильный внутренний класс. Я изо всех сил пытался заставить представления, добавленные в TableRow, отображаться правильно, пока не выяснил, что я не передавал экземпляр TableRow.LayoutParams в setLayoutParams дочернего представления.

Брайан Кули
источник
5
Как бы вы создали представление программно, используя файл макета XML, который вы специально написали для этого нового представления?
SK9
9
@ SK9 Вы бы использовали LayoutInflater, который вы можете получить из контекста, обычно текущей деятельности. Что-то вроде: LayoutInflater myInflater = getLayoutInflater; View myView = myInflater.inflate (R.layout.myLayout, parent, false);
Брайан Кули
1
На самом деле getLayoutInflater () происходит из класса Window (не Context), и это удобный метод в Activity.
Брайан Кули
2
В качестве практики кодирования для findViewById приведите к ViewGroup или всегда к наиболее общей форме объекта, чтобы в случае его изменения с LinearLayout на RelativeLayout у вас не было рефакторинга.
Джоэл Тепли
1
Вот некоторые детали: D
Вивек Соланки,
51

для всех, кто еще заинтересован:

лучший способ, который я нашел, - использовать статический метод надувания View.

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

где yourViewXML что-то вроде R.layout.myView

обратите внимание, что вам нужна ViewGroup, чтобы добавить представление (любой макет, который вы можете придумать)

Итак, в качестве примера предположим, что у вас есть фрагмент, который он просматривает, уже накачан, и вы знаете, что корневое представление является макетом, и вы хотите добавить к нему представление:

    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
источник
Вы также можете написать статический метод, что-то вроде addView(View v){ // your code after get view }этого, которое будет использовать findViewById(int resourceID)или раздутое представление, как ваш inflatedView... просто чтобы расширить ваш пример фрагмента.
zgc7009
22

Это поздно, но это может кому-то помочь :) :) Для добавления вида программно попробуйте как

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

Это создаст весь ваш вид программно. Вы можете добавить любое количество просмотров, как то же самое. Надеюсь, что это может помочь. :)

AndroidOptimist
источник
3

Еще один способ добавить вид из Activity

ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
yoAlex5
источник
0

Идея программной установки ограничений может быть утомительной. Это решение ниже будет работать для любого макета, будь то ограничение, линейное и т. Д. Наилучшим способом было бы установить заполнитель, т.е. FrameLayout с надлежащими ограничениями (или надлежащим размещением в другом макете, например, линейном) в позиции, в которой вы ожидаете программно созданное представление. иметь.

Все, что вам нужно сделать, это раздувать представление программно и в детстве с помощью addChild()метода FrameLayout . Тогда во время выполнения ваш вид будет раздут и помещен в правильное положение. Согласно рекомендациям Android, вы должны добавить только один дочерний элемент в FrameLayout [ссылка] .

Вот как будет выглядеть ваш код, если вы хотите программно создать TextView в определенной позиции:

Шаг 1:

В вашем макете, который будет содержать раздуваемое представление, поместите FrameLayout в правильное положение и присвойте ему идентификатор, скажем, «контейнер».

Шаг 2 Создайте макет с корневым элементом в качестве представления, которое вы хотите раздуть во время выполнения, вызовите файл макета как «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>

Кстати, установите параметры макета вашего frameLayout равными wrap_content, иначе макет кадра станет таким же большим, как родительский элемент, т.е. активность, то есть экран телефона.

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

Если не задано, потому что дочерний вид рамки по умолчанию переходит в левую верхнюю часть макета кадра, поэтому ваш вид просто переместится в левую верхнюю часть экрана.

Шаг 3

В вашем методе oncreate сделайте это:

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

(Обратите внимание, что установка последнего параметра findViewByIdдля nullи добавление представления путем вызова представления addView()контейнера (frameLayout) - это то же самое, что просто присоединение раздутого представления путем передачи trueтретьего параметра параметра findViewById(). Для получения дополнительной информации см. Это .)

Куш
источник
0

Вы, ребята, также должны убедиться, что при переопределении onLayoutвы должны вызывать super.onLayoutвсе свойства, иначе представление не будет раздутым!

Оз Шабат
источник