如何在 Android 中为动态创建的字段使用双向数据绑定
How to use two-way data binding in Android for dynamically created fields
我有一个表单,其字段由服务器设置 return。
这是Activity中的代码。
//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
class Person {
public Map<String, String> attributes;
}
最后我希望上面的属性包含属性名称和 EditText
中输入的值之间的映射
我已经尝试创建一个双向数据绑定示例,该示例使用在布局文件中预定义的 EditText。但是我想知道这个动态属性能不能做。
数据绑定不适用于代码生成的布局。也就是说,您可以使用数据绑定通过绑定适配器来执行此操作。
本文告诉您如何使用列表的数据绑定:
https://medium.com/google-developers/android-data-binding-list-tricks-ef3d5630555e#.v2deebpgv
如果你想使用数组而不是列表,这是一个小的调整。如果要使用地图,则必须将地图作为参数传递给绑定布局。本文假设有一个变量,但您可以在 BindingAdapter 中传入多个。对于简单的绑定适配器:
@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<String, String>"/>
</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>
我有一个表单,其字段由服务器设置 return。
这是Activity中的代码。
//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
class Person {
public Map<String, String> attributes;
}
最后我希望上面的属性包含属性名称和 EditText
我已经尝试创建一个双向数据绑定示例,该示例使用在布局文件中预定义的 EditText。但是我想知道这个动态属性能不能做。
数据绑定不适用于代码生成的布局。也就是说,您可以使用数据绑定通过绑定适配器来执行此操作。
本文告诉您如何使用列表的数据绑定:
https://medium.com/google-developers/android-data-binding-list-tricks-ef3d5630555e#.v2deebpgv
如果你想使用数组而不是列表,这是一个小的调整。如果要使用地图,则必须将地图作为参数传递给绑定布局。本文假设有一个变量,但您可以在 BindingAdapter 中传入多个。对于简单的绑定适配器:
@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<String, String>"/>
</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>