问题
I have Spinner
and some count of EditText
at layout. I want to bind type of EditText
to state of Spinner
. I.e.
- for FLOAT state of
Spinner
input type of allEditText
components must be changed to floating point numbers - for INTEGER input type must be integer
To achive this I define binding adapter below:
@BindingAdapter(value = {"bind:selectedValueAttrChanged", "bind:relatedInputs"}, requireAll = false)
public static void setMeasurementUnit(final Spinner spinner, final InverseBindingListener listener, final AppCompatEditText... relatedInputs){
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
listener.onChange();
String selectedUnit = (String) spinner.getSelectedItem();
for (EditText editText : relatedInputs) {
if (editText == null) continue;
if (selectedUnit.equals("INTEGER"))
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
else if(selectedUnit.equals("FLOAT"))
editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
listener.onChange();
}
});
}
And bind EditText
to Spinner
at layout file:
<LinearLayout>
<android.support.v7.widget.AppCompatEditText
android:id="@+id/edit_text_1"/>
<android.support.v7.widget.AppCompatSpinner
bind:relatedInputs="@{editText1}"/>
</LinearLayout>
It's produce the error at compile time:
data binding error ****msg:Cannot find the setter for attribute 'bind:relatedInputs' with parameter type android.support.v7.widget.AppCompatEditText on android.support.v7.widget.AppCompatSpinner.
When I tried declare and pass array of EditText
<android.support.v7.widget.AppCompatSpinner
bind:relatedInputs="@{new AppCompatEditText[]{editText1, editText2}}"/>
I'm got syntax error:
data binding error ****msg:Syntax error: extraneous input 'AppCompatEditText' expecting {<EOF>, ',', '.', '::', '[', '+', '-', '*', '/', '%', '<<', '>>>', '>>', '<=', '>=', '>', '<', 'instanceof', '==', '!=', '&', '^', '|', '&&', '||', '?', '??'}
How I can pass variable number of arguments to databinding adapter?
or
How to declare array for databinding at layout file?
P.S. this example very simplified and can contain logical errors, but it fully explain, what I want to achive.
回答1:
Android Data Binding doesn't let you pass in varargs. You may have only have one value for each attribute. You may pass lists or arrays as attribute values, but you can't create them on the fly (new
is not allowed in the expression language).
It is better to invert the problem and assign the android:inputType
attribute to an expression based on the selected item.
<LinearLayout>
<android.support.v7.widget.AppCompatEditText
android:inputType="@{Converters.getInputType(spinner1.selectedItem)}"/>
<android.support.v7.widget.AppCompatSpinner
android:id="@+id/spinner1"/>
</LinearLayout>
You'll need the Converters class also:
public class Converters {
public static int getInputType(Object obj) {
if (!(obj instanceof String)) {
return InputType.TYPE_CLASS_TEXT; // Don't know what to do
}
String selectedUnit = (String) obj;
if (selectedUnit.equals("INTEGER")) {
return InputType.TYPE_CLASS_NUMBER;
} else if(selectedUnit.equals("FLOAT")) {
return InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL;
}
return InputType.TYPE_CLASS_TEXT; // Don't know what to do
}
}
回答2:
Another approach would be:
//create a Observable for the input type:
public final ObservableInt decOrInt = new ObservableInt(InputType.TYPE_NUMBER_FLAG_DECIMAL);
Add a listener to your spinner:
binding.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
decOrInt.set(i != 0 ?
InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL :
InputType.TYPE_CLASS_NUMBER);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
decOrInt.set(InputType.TYPE_CLASS_NUMBER);
}
});
And in your xml, for every EditText
you want:
<!-- act would be the class where you store your decOrInt-->
<EditText
android:id="@+id/edit_text"
android:inputType="@{act.decOrInt}" />
A decimal input corresponds to InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL
, an integer input corresponds to InputType.TYPE_CLASS_NUMBER
.
It is possible to enter a float and change the selection to int - you'll need to add an error or something to prevent this.
来源:https://stackoverflow.com/questions/42257367/how-to-pass-variable-number-of-arguments-to-databinding-adapter