2017-02-23 405 views
0

У меня есть форма, поля которой заданы возвратом сервера.Как использовать двустороннюю привязку данных в Android для динамически создаваемых полей

Это код в Управлении.

//returned by server 
String[] attributes = new String[] {"occupation", "salary", "age"}; 

LinearLayout dynamicLayout = (LinearLayout) findViewById(R.id.dynamic_layout); 
for (String attribute : attributes) { 
    EditText text = new EditText(this); 
    text.setLayoutParams(new LayoutParams(
     LayoutParams.WRAP_CONTENT, 
     LayoutParams.WRAP_CONTENT 
    )); 
    text.setText(attribute); 
    dynamicLayout.addView(text); 
} 

У меня есть эта модель класса

class Person { 
    public Map<String, String> attributes; 
} 

В конце концов, я ожидать, что атрибуты выше будет содержать карту между именем атрибута и ввод значений в EditText

Я попытался создал двухсторонняя привязка данных, которая использует EditText, которая предопределена в файле макета. Но мне интересно, можно ли сделать этот динамический атрибут.

ответ

2

Связывание данных на самом деле не работает с сгенерированными кодом макетами. Тем не менее, вы можете использовать привязку данных для этого с помощью Binding Adapter.

Эта статья расскажет вам, как использовать связывание данных со списками:

https://medium.com/google-developers/android-data-binding-list-tricks-ef3d5630555e#.v2deebpgv

Если вы хотите использовать массив вместо списка, это небольшая корректировка. Если вы хотите использовать карту, вам необходимо передать карту в качестве параметра в привязку. Статья предполагает единственную переменную, но вы можете передать ее несколько раз в свой BindingAdapter. Для простой Binding адаптер:

@BindingAdapter({"entries", "layout", "extra"}) 
public static <T, V> void setEntries(ViewGroup viewGroup, 
            T[] entries, int layoutId, 
            Object extra) { 
    viewGroup.removeAllViews(); 
    if (entries != null) { 
     LayoutInflater inflater = (LayoutInflater) 
      viewGroup.getContext()  
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     for (int i = 0; i < entries.length; i++) { 
      T entry = entries[i]; 
      ViewDataBinding binding = DataBindingUtil 
       .inflate(inflater, layoutId, viewGroup, true); 
      binding.setVariable(BR.data, entry); 
      binding.setVariable(BR.extra, extra); 
     } 
    } 
} 

А вы бы связать записи, как это: (предположим entry.xml)

<layout> 
    <data> 
     <variable name="data" type="String"/> 
     <variable name="extra" type="java.util.Map&lt;String, String&gt;"/> 
    </data> 
    <EditText xmlns:android="..." 
     android:text="@={extra[data]}" 
     .../> 
</layout> 

И в вашем содержащей макет, вы будете использовать:

<layout> 
    <data> 
     <variable name="person" type="com.example.Person"/> 
     <variable name="attributes" type="String[]"/> 
    </data> 
    <FrameLayout xmlns:android="..." xmlns:app="..."> 
     <!-- ... --> 
     <LinearLayout ... 
      app:layout="@{@layout/entry}" 
      app:entries="@{attributes}" 
      app:extra="@{person.attributes}"/> 
    </FrameLayout> 
</layout> 
Смежные вопросы