问题
I have a form whose fields are set by server return.
This is the code in the 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);
}
I have this model class
class Person {
public Map<String, String> attributes;
}
In the end I expect the attributes above will contain the map between attribute name and the values input in the EditText
I have tried created a two-way data-binding sample that uses EditText that is predefined in the layout file. But I am wondering if this dynamic attribute can be done.
回答1:
Data Binding doesn't really work with code-generated layouts. That said, you can use data binding to do this with a Binding Adapter.
This article tells you how to use data binding with lists:
https://medium.com/google-developers/android-data-binding-list-tricks-ef3d5630555e#.v2deebpgv
If you want to use an array instead of a list, it is a small adjustment. If you want to use a map, you'll have to pass the map as a parameter to the bound layout. The article assumes a single variable, but you can pass in multiple in your BindingAdapter. For a simple Binding Adapter:
@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);
}
}
}
And you would bind the entries like this: (assume 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>
And in your containing layout, you'd use:
<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>
来源:https://stackoverflow.com/questions/42414021/how-to-use-two-way-data-binding-in-android-for-dynamically-created-fields