Что делает LayoutInflater в Android?


зачем LayoutInflater В Android?

14 284

14 ответов:

при использовании пользовательского представления в ListView вы должны определить формат строки. Вы создаете xml, где вы размещаете виджеты android, а затем в коде адаптера вы должны сделать что-то вроде этого:

public MyAdapter(Context context, List<MyObject> objects) extends ArrayAdapter {
  super(context, 1, objects);
  /* We get the inflator in the constructor */
  mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
  View view;
  /* We inflate the xml which gives us a view */
  view = mInflater.inflate(R.layout.my_list_custom_row, parent, false);

  /* Get the item in the adapter */
  MyObject myObject = getItem(position);

  /* Get the widget with id name which is defined in the xml of the row */
  TextView name = (TextView) view.findViewById(R.id.name);

  /* Populate the row's xml with info from the item */
  name.setText(myObject.getName());

  /* Return the generated view */
  return view;
}

подробнее на официальная документация.

LayoutInflater класс используется для создания экземпляра XML-файла макета в соответствующие объекты представления.

другими словами, он принимает в качестве входных данных XML-файл и строит из него объекты представления.

что значит LayoutInflator делать?

когда я впервые начал Программирование Android, я был действительно смущен LayoutInflater и findViewById. Иногда мы использовали одно, а иногда и другое.

  • LayoutInflater используется для создания новых View (или Layout объект) от одного из ваших XML-макетов.
  • findViewById просто дает вам ссылку на представление, чем уже был создан. Вы можете подумать, что вы еще не создали никаких представлений, но всякий раз, когда вы звоните setContentView на onCreate, макет действия вместе с его подвидами раздувается (создается) за кулисами.

так что если представление уже существует, то используйте findViewById. Если нет, то создайте его с помощью LayoutInflater.

пример

вот мини-проект, который я сделал, который показывает оба LayoutInflater и findViewById в действии. Без специального кода, макет выглядит так.

enter image description here

синий квадрат это пользовательский макет, вставленный в основной макет с include (см. здесь для более). Он был раздут автоматически, потому что он является частью представления содержимого. Как видите, в коде нет ничего особенного.

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

теперь давайте надуем (создадим) еще одну копию нашего пользовательского макета и добавим ее.

enter image description here

LayoutInflater inflater = getLayoutInflater();
View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);

чтобы раздуть новый макет представления, все, что я сделал, это сказал надувателю имя моего xml-файла (my_layout), Родительский макет, который я хочу добавить его в (mainLayout), и что я на самом деле не хотите добавить еще (false). (Я также могу установить родителя в null, но тогда параметры макета корневого представления моего пользовательского макета будут проигнорированы.)

здесь это снова в контексте.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // inflate the main layout for the activity
        setContentView(R.layout.activity_main);

        // get a reference to the already created main layout
        LinearLayout mainLayout = (LinearLayout) findViewById(R.id.activity_main_layout);

        // inflate (create) another copy of our custom layout
        LayoutInflater inflater = getLayoutInflater();
        View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);

        // make changes to our custom layout and its subviews
        myLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.colorAccent));
        TextView textView = (TextView) myLayout.findViewById(R.id.textView);
        textView.setText("New Layout");

        // add our custom layout to the main layout
        mainLayout.addView(myLayout);
    }
}

обратите внимание, как findViewById используется только после того, как макет уже была надута.

Дополнительный Код

вот xml для примера выше.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main_layout"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <!-- Here is the inserted layout -->
    <include layout="@layout/my_layout"/>

</LinearLayout>

my_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@color/colorPrimary">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="5dp"
        android:textColor="@android:color/white"
        android:text="My Layout"/>

</RelativeLayout>

когда вам нужен LayoutInflater

  • наиболее распространенное время, когда большинство людей используют его в RecyclerView. (См.RecyclerView примеры список или решетки.) Вы должны надуть новый макет для каждого видимого элемента в списке или сетке.
  • вы также можете использовать надувной макет если у вас сложный макет, который вы хотите добавить программно (как мы сделали в нашем примере). Вы можете сделать все это в коде, но гораздо проще сначала определить его в xml, а затем просто раздуть его.

LayoutInflater.inflate () предоставляет средство для преобразования res/layout/*.xml-файл, определяющий представление в фактический объект представления, используемый в исходном коде приложения.

основные два шага: получить надуватель, а затем надуть ресурс

Как сделать насос?

LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Как вы получаете представление, предполагая, что xml-файл " list_item.xml"?

View view = inflater.inflate(R.layout.list_item, parent, false);

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

предположим, что ваш макет строки ListView может иметь переменное количество текстовых представлений. Поэтому сначала вы раздуваете представление Базового элемента (как и в предыдущем примере), а затем динамически добавляете текстовые представления во время выполнения. Использование android: layout_weight дополнительно выравнивает все отлично.

здесь представлены ресурсы, макеты :

list_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" >
    <TextView 
        android:id="@+id/field1"
        android:layout_width="0dp"  
        android:layout_height="wrap_content" 
        android:layout_weight="2"/>
    <TextView 
        android:id="@+id/field2"
        android:layout_width="0dp"  
        android:layout_height="wrap_content" 
        android:layout_weight="1"
/>
</LinearLayout>

schedule_layout.xml

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

переопределить getView метод в расширении класса BaseAdapter

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = activity.getLayoutInflater();
    View lst_item_view = inflater.inflate(R.layout.list_layout, null);
    TextView t1 = (TextView) lst_item_view.findViewById(R.id.field1);
    TextView t2 = (TextView) lst_item_view.findViewById(R.id.field2);
    t1.setText("some value");
    t2.setText("another value");

    // dinamically add TextViews for each item in ArrayList list_schedule
    for(int i = 0; i < list_schedule.size(); i++){
        View schedule_view = inflater.inflate(R.layout.schedule_layout, (ViewGroup) lst_item_view, false);
        ((TextView)schedule_view).setText(list_schedule.get(i));
        ((ViewGroup) lst_item_view).addView(schedule_view);
    }
    return lst_item_view;
}

Примечание различные надувают вызовы метода:

inflater.inflate(R.layout.list_layout, null); // no parent
inflater.inflate(R.layout.schedule_layout, (ViewGroup) lst_item_view, false); // with parent preserving LayoutParams

этот класс используется для создания экземпляра XML-файла макета в соответствующий View объекты. Он никогда не будет использоваться непосредственно -- use getLayoutInflater() или getSystemService(String) чтобы получить стандартный LayoutInflater экземпляр, который уже подключен к текущему контексту и правильно настроен для устройства, на котором вы работаете. Например:

LayoutInflater inflater = (LayoutInflater)context.getSystemService
      (Context.LAYOUT_INFLATER_SERVICE);

Ссылка:http://developer.android.com/reference/android/view/LayoutInflater.html

надувание означает чтение XML-файла, который описывает макет (или элемент GUI) и создает фактические объекты, соответствующие ему, и, таким образом, делает объект видимым в приложении для Android.

final Dialog mDateTimeDialog = new Dialog(MainActivity.this);

// Inflate the root layout
final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);

// Grab widget instance
final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);

этот файл может быть сохранен как date_time_dialog.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/DateTimeDialog" android:layout_width="100px"
    android:layout_height="wrap_content">
    <com.dt.datetimepicker.DateTimePicker
            android:id="@+id/DateTimePicker" android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    <LinearLayout android:id="@+id/ControlButtons"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:layout_below="@+id/DateTimePicker"
            android:padding="5dip">
            <Button android:id="@+id/SetDateTime" android:layout_width="0dip"
                    android:text="@android:string/ok" android:layout_weight="1"
                    android:layout_height="wrap_content"
                   />
            <Button android:id="@+id/ResetDateTime" android:layout_width="0dip"
                    android:text="Reset" android:layout_weight="1"
                    android:layout_height="wrap_content"
                    />
            <Button android:id="@+id/CancelDialog" android:layout_width="0dip"
                    android:text="@android:string/cancel" android:layout_weight="1"
                    android:layout_height="wrap_content"
                     />
    </LinearLayout>

этот файл может быть сохранен как date_time_picker.xml:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="wrap_content" `enter code here`
    android:padding="5dip" android:id="@+id/DateTimePicker">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="true"
android:orientation="horizontal">

    <LinearLayout
    android:id="@+id/month_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="1dp"
    android:layout_marginTop="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="5dp"
    android:gravity="center"
    android:orientation="vertical">
    <Button
        android:id="@+id/month_plus"
        android:layout_width="45dp"
        android:layout_height="45dp"  
        android:background="@drawable/image_button_up_final"/>
    <EditText
        android:id="@+id/month_display"
        android:layout_width="45dp"
        android:layout_height="35dp"
        android:background="@drawable/picker_middle"
        android:focusable="false"
        android:gravity="center"
        android:singleLine="true"
        android:textColor="#000000">
    </EditText>
    <Button
        android:id="@+id/month_minus"
        android:layout_width="45dp"
        android:layout_height="45dp"       
        android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
    android:id="@+id/date_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="0.5dp"
    android:layout_marginTop="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="5dp"
    android:gravity="center"
    android:orientation="vertical">
    <Button
        android:id="@+id/date_plus"
        android:layout_width="45dp"
        android:layout_height="45dp"       
        android:background="@drawable/image_button_up_final"/>
    <EditText
        android:id="@+id/date_display"
        android:layout_width="45dp"
        android:layout_height="35dp"
        android:background="@drawable/picker_middle"
        android:gravity="center"
        android:focusable="false"
        android:inputType="number"
        android:textColor="#000000"
        android:singleLine="true"/>
    <Button
        android:id="@+id/date_minus"
        android:layout_width="45dp"
        android:layout_height="45dp"      
        android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
    android:id="@+id/year_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="0.5dp"
    android:layout_marginTop="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginBottom="5dp"
    android:gravity="center"
    android:orientation="vertical">
    <Button
        android:id="@+id/year_plus"
        android:layout_width="45dp"
        android:layout_height="45dp"       
            android:background="@drawable/image_button_up_final"/>
    <EditText
        android:id="@+id/year_display"
        android:layout_width="45dp"
        android:layout_height="35dp"
        android:background="@drawable/picker_middle"
        android:gravity="center"
        android:focusable="false"
        android:inputType="number"
        android:textColor="#000000"
        android:singleLine="true"/>
    <Button
        android:id="@+id/year_minus"
        android:layout_width="45dp"
        android:layout_height="45dp"       
        android:background="@drawable/image_button_down_final"/>
</LinearLayout>
<LinearLayout
        android:id="@+id/hour_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:gravity="center"
        android:orientation="vertical">
        <Button
            android:id="@+id/hour_plus"
            android:layout_width="45dp"
            android:layout_height="45dp"          
            android:background="@drawable/image_button_up_final"/>
        <EditText
            android:id="@+id/hour_display"
            android:layout_width="45dp"
            android:layout_height="35dp"
            android:background="@drawable/picker_middle"
            android:gravity="center"
            android:focusable="false"
            android:inputType="number"
            android:textColor="#000000"
            android:singleLine="true">
        </EditText>
        <Button
            android:id="@+id/hour_minus"
            android:layout_width="45dp"
            android:layout_height="45dp"       
            android:background="@drawable/image_button_down_final"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/min_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="0.35dp"
        android:layout_marginTop="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="5dp"
        android:gravity="center"
        android:orientation="vertical">
        <Button
            android:id="@+id/min_plus"
            android:layout_width="45dp"
            android:layout_height="45dp"       
            android:background="@drawable/image_button_up_final"/>
        <EditText
            android:id="@+id/min_display"
            android:layout_width="45dp"
            android:layout_height="35dp"
            android:background="@drawable/picker_middle"
            android:gravity="center"
            android:focusable="false"
            android:inputType="number"
            android:textColor="#000000"
            android:singleLine="true"/>
        <Button
            android:id="@+id/min_minus"
            android:layout_width="45dp"
            android:layout_height="45dp"       
            android:background="@drawable/image_button_down_final"/>
    </LinearLayout>

    <LinearLayout 
        android:id="@+id/meridiem_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="0.35dp"
        android:layout_marginTop="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="5dp"
        android:gravity="center"
        android:orientation="vertical">
        <ToggleButton 
            android:id="@+id/toggle_display"
            style="@style/SpecialToggleButton"
            android:layout_width="40dp"
            android:layout_height="32dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="45dp"
            android:layout_marginRight="5dp"
            android:layout_marginBottom="5dp"
            android:padding="5dp"
            android:gravity="center"
            android:textOn="@string/meridiem_AM"
            android:textOff="@string/meridiem_PM"
            android:checked="true"/>

           <!--  android:checked="true" --> 

    </LinearLayout>
</LinearLayout>
</RelativeLayout>

The MainActivity класс сохраняется как MainActivity.java:

public class MainActivity extends Activity {
    EditText editText;
    Button button_click;
    public static Activity me = null;
    String meridiem;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = (EditText)findViewById(R.id.edittext1);
        button_click = (Button)findViewById(R.id.button1);
        button_click.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view){
                final Dialog mDateTimeDialog = new Dialog(MainActivity.this);
                final RelativeLayout mDateTimeDialogView = (RelativeLayout)   getLayoutInflater().inflate(R.layout.date_time_dialog, null);
                final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
                // mDateTimePicker.setDateChangedListener();
                ((Button) mDateTimeDialogView.findViewById(R.id.SetDateTime)).setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        mDateTimePicker.clearFocus();
                        int hour = mDateTimePicker.getHour();
                        String result_string = mDateTimePicker.getMonth() +" "+   String.valueOf(mDateTimePicker.getDay()) + ", " + String.valueOf(mDateTimePicker.getYear())
                        + "  " +(mDateTimePicker.getHour()<=9? String.valueOf("0"+mDateTimePicker.getHour()) : String.valueOf(mDateTimePicker.getHour())) + ":" + (mDateTimePicker.getMinute()<=9?String.valueOf("0"+mDateTimePicker.getMinute()):String.valueOf(mDateTimePicker.getMinute()))+" "+mDateTimePicker.getMeridiem();
                        editText.setText(result_string);
                        mDateTimeDialog.dismiss();
                    }
                });
                // Cancel the dialog when the "Cancel" button is clicked
                ((Button) mDateTimeDialogView.findViewById(R.id.CancelDialog)).setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        mDateTimeDialog.cancel();
                    }
                });
                // Reset Date and Time pickers when the "Reset" button is clicked
                ((Button) mDateTimeDialogView.findViewById(R.id.ResetDateTime)).setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        mDateTimePicker.reset();
                    }
                });

                // Setup TimePicker
                // No title on the dialog window
                mDateTimeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                // Set the dialog content view
                mDateTimeDialog.setContentView(mDateTimeDialogView);
                // Display the dialog
                mDateTimeDialog.show();
            }
        });
    }
}

что насос делает

Он принимает XML-макет в качестве входных данных (скажем) и преобразует его в объект просмотра.

зачем это нужно

давайте подумаем сценарий, где нам нужно создать пользовательский listview. Теперь каждая строка должна быть пользовательской. Но как мы можем это сделать. Невозможно назначить XML-макет для строки listview. Итак, мы создаем объект представления. Таким образом,мы можем получить доступ к элементам в нем (textview, imageview и т. д.), а также назначить объект как строка listview

Итак, всякий раз, когда нам нужно назначить объект типа представления где-то, и у нас есть свой собственный дизайн xml, мы просто преобразуем его в объект с помощью inflater и используем его.

вот пример для получения ссылки на корневое представление макета , надувая его и используя его с setContentView (View view)

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LayoutInflater li=getLayoutInflater();
    View rootView=li.inflate(R.layout.activity_main,null);
    setContentView(rootView);


}

Layout inflater-это класс, который читает описание внешнего вида xml и преобразует их в объекты представления на основе java.

мой список настроек надеюсь, что это иллюстрирует концепцию

public class second extends ListActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.second);
//  TextView textview=(TextView)findViewById(R.id.textView1);
//  textview.setText(getIntent().getExtras().getString("value"));

    setListAdapter(new MyAdapter(this,R.layout.list_item,R.id.textView1, getResources().getStringArray(R.array.counteries)));
}

private class MyAdapter extends ArrayAdapter<String>{

    public MyAdapter(Context context, int resource, int textViewResourceId,
            String[] objects) {
        super(context, resource, textViewResourceId, objects);
        // TODO Auto-generated constructor stub
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row=inflater.inflate(R.layout.list_item,parent,false);
        String[]items=getResources().getStringArray(R.array.counteries);

        ImageView iv=(ImageView) row.findViewById(R.id.imageView1);
        TextView tv=(TextView) row.findViewById(R.id.textView1);
        tv.setText(items[position]);

        if(items[position].equals("unitedstates")){
            iv.setImageResource(R.drawable.usa);
        }else   if(items[position].equals("Russia")){
            iv.setImageResource(R.drawable.russia);
        }else   if(items[position].equals("Japan")){
            iv.setImageResource(R.drawable.japan);
        }
        // TODO Auto-generated method stub
        return row;
    }

}

}

LayoutInflater является фундаментальным компонентом в Android. Вы должны использовать его все время, чтобы превратить xml-файлы в иерархии представлений.

LayoutInflater создает объекты представления на основе макетов, определенных в XML. Существует несколько различных способов использования LayoutInflater, включая создание пользовательских представлений, раздувание представлений фрагментов в представления действий, создание диалоговых окон или просто раздувание представления файла макета в действие.

есть много заблуждений о том, как работает процесс инфляции. Я думаю, что это происходит из-за плохой документации для метода inflate (). Если вы хотите узнать о накачать() метод подробно, я написал сообщение в блоге об этом здесь:

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/

Inflater на самом деле какой-то конвертировать в данные, представления, экземпляры, видимое представление пользовательского интерфейса.. ..таким образом, он использует подачу данных в возможно адаптеры и т. д. программно. затем интегрируя его с xml, который вы определили, это говорит ему, как данные должны быть представлены в UI