- Two-way Databinding with a custom property in Android
- Let’s code!
- 1. The first method will be responsible to set a listener to the view
- 2. The second method is the one that sets the input with the value coming from the model/presenter.
- 3. Finally the third method is the getter that will call our model/presenter setAttribute
- Android DataBinding basics: one-way, two-way and handler
- Android two-way databinding for methods with parameters
- 2 Answers 2
- Create two-way binding with Android Data Binding
- 6 Answers 6
- Two-Way databinding in EditText
- 6 Answers 6
- variable is string type
- variable is number
Two-way Databinding with a custom property in Android
May 17, 2017 · 3 min read
Learn how to setup two-way databinding with custom properties or custom views.
I know you will try to skim it but I suggest you to read everything to really understand how it works to apply it in your own project, but if you just want the code, you can find it in the end of the article.
Requirement:
The view that you will bind mu s t have a change listener, such as the EditText that has the TextWatcher or the Spinner that has setOnItemSelectedListener . If it is a custom view that doesn’t have it, you’ll need to adapt it, but I won’t cover it in this tutorial.
Let’s code!
1. Create a name for the attribute you want to bind and add it to your xml. Don’t forget the = sign.
In this example I used a customview, but the process is the same for android view. You need to add the prefix app: to the attribute name you decide. The name I chose for mine was app:realValue .
Don’t forget to assign it to a variable that will hold the value (in this example: amount ).
2. Make sure you create the getter and setter for this variable on your presenter or model. In my case:
3. Create a Binder class with the bindingAdapters
You can create this class with any name and location within your project and it doesn’t extend anything. The important part here is the annotation.
I created the CurrencyBinder and added the following methods:
1. The first method will be responsible to set a listener to the view
This method can have any name but it is important to add the annotation @BindingAdapter(value = «realValueAttrChanged») with the value being the name of the attribute with the suffix AttrChanged. Ex: attribute name is selectedItem . So the value you should use is: selectedItemAttrChanged .
The first parameter will be the view you insert your binding and the second parameter must be the final InverseBindingListener listener . When the change occurs you must call the listener.onChange() so it knows that something has changed and calls the 3rd method we will create.
2. The second method is the one that sets the input with the value coming from the model/presenter.
This @BindingAdapter(«realValue») must have the name of the attribute we created before.
This also can have any name but I suggest to keep it like a setter. The first param is the view and the second one is the value that will be sent from the model/presenter. Here you will have to set the new value to the view and it is important to check if the new value is the same as the old one to avoid getting into a loop.
3. Finally the third method is the getter that will call our model/presenter setAttribute
This method must be annotated with @InverseBindingAdapter(attribute = «realValue» . As you can see the attribute is the attribute name we’ve been using since the start.
Источник
Android DataBinding basics: one-way, two-way and handler
Apr 28, 2018 · 3 min read
The following sample, written in kotlin, is a fast, easy guide to use one-way databinding, two-way databinding and handler.
Observable
So now we have to create a class that extends BaseObservable. It’s a special class that can be bound to layout and observe its properties change.
One-Way DataBinding
Now let’s start with one-way databinding! It’s named one-way databinding because there’s only one communication way: from observable to view.
Challenge: I want to set the title only if a flag parameter is true. [dangerously easy]
Two-Way Databin d ing
Now let’s start with two-way databinding. The difference with one-way databinding is that there are two communication ways: from observable to view and viceversa. So you can put both get and set to a variable to accomplish this.
Challenge: While i’m writing in EditText, I want to modify the text written separating each letter with a ‘-’ (hello -> h-e-l-l-o) and I want to show it in a TextView. [easy]
Note:
— I’ve not used a get for EditText because I didn’t need It, but for two-way databinding you can use It;
— BR is a generated class for databinding in which you can find the declared view ids with databinding enabled;
— You have two ways to notify refresh to layout from a baseobservable: notifyChange() and notifyPropertyChanged(id: Int). The function notifyChange() refreshes the entire layout.
Summary on one-way and two-way databinding
Handlers
You can create a class that handles events triggered from a view. A very famous case is the onClick event, in which you could put a function to trigger.
Challenge: I want to show an error text in my TextInputLayout when I click the ‘confirm’ Button and EditText is empty. [very easy]
Note:
— You have to pass views as parameters by their ids. If an id is with ‘_’ you have to write the parameter in camelCase (input_text -> inputText)
Источник
Android two-way databinding for methods with parameters
Setter and getter methods of the model have one parameter, like this:
XML looks like this:
Compiler errors during the building say that we should you use @InverseMethod annotation. I try something like this:
But in this case I have the next error.
So I will be glad to here nice explanation of the whole flow. Thanks
2 Answers 2
Nice to see you’re using the new InverseMethod available in Android Studio 3.0.
You’re using two-way data binding with a method and the expression must understand how to set the value when the user modifies the text. The use is intended for conversion methods, so I don’t know if this applies in your case.
Essentially, data binding uses code like this when setting the text to the View:
And when the text changes, you are asking it to do this:
That’s clearly not going to work and it gives you an error.
There are two things wrong, really. The first is that getPrice() returns an int instead of a CharSequence or String . The second is that setPrice() isn’t really doing a conversion — it takes a different number of parameters and returns a void .
In your case, you’re not trying to convert priceKey into an integer; you’re trying to access a value in a map of some sort. There are a few ways to handle this. I think the easiest way is to use a map directly in your model. Here, I’ll assume that you have a final field, but you could return it as a property using getters and setters:
and then in your expression:
If you want custom conversions, you can do it like this:
And then you would pass the price object in the expression:
I would simplify the conversion methods to make them reusable throughout my application and just convert an integer to String and back:
Источник
Create two-way binding with Android Data Binding
I have implemented the new Android data-binding, and after implementing realised that it does not support two-way binding. I have tried to solve this manually but I am struggling to find a good solution to use when binding to an EditText. In my layout I have this view:
Another view is also showing the results:
In my fragment I create the binding like this:
This works and puts the current value of firstName in the EditText. The problem is how to update the model when the text changes. I tried putting an OnTextChanged-listener on the editText and updating the model. This created a loop killing my app (model-update updates the GUI, which calls textChanged times infinity). Next I tried to only notify when real changes occured like this:
This worked better, but everytime I write a letter, the GUI is updated and for som reason the edit-cursor is moved to the front.
Any suggestions would be welcome
6 Answers 6
EDIT 04.05.16: Android Data binding now supports two way-binding automatically! Simply replace:
in an EditText for instance and you get two-way binding. Make sure you update to the latest version of Android Studio/gradle/build-tools to enable this.
I tried Bhavdip Pathar’s solution, but this failed to update other views I had bound to the same variable. I solved this a different way, by creating my own EditText:
With this solution you can update the model any way you want (TextWatcher, OnTextChangedListener etc), and it takes care of the infinite update loop for you. With this solution the model-setter can be implemented simply as:
This puts less code in the model-class (you can keep the listeners in your Fragment).
I would appreciate any comments, improvements or other/better solutions to my problem
This is now supported in Android Studio 2.1+ when using the gradle plugin 2.1+
Simply change the EditText’s text attribute from @<> to @=<> like this:
@Gober The android data-binding support the two way binding. Therefore you do not need to make it manually. As you tried by putting the OnTextChanged-listener on the editText. It should update the model.
I tried putting an OnTextChanged-listener on the editText and updating the model. This created a loop killing my app (model-update updates the GUI, which calls textChanged times infinity).
It’s worth noting that binding frameworks that implement two-way binding would normally do this check for you…
Here’s the example of modified view model, which does not raise a data binding notification if the change originated in the watcher:
Let’s create a SimpleTextWatcher that only requires only one method to be overridden:
Next, in the view model we can create a method that exposes the watcher. The watcher will be configured to pass the changed value of the control to the view model:
Finally, in the view we can bind the watcher to the EditText using addTextChangeListener:
Here is the implementation of the view Model that resolve the notification infinity.
I hope this is what you are looking and sure can help you. Thanks
Источник
Two-Way databinding in EditText
I have this object
and my AppCompatEditText is like this in xml code:
I’m having this error:
I already have tried just with
but I’m having this error:
Anybody has an example of how to do this?
6 Answers 6
You can do two-way binding on EditText.
Using one-way data binding, you can set a value on an attribute and set a listener that reacts to a change in that attribute
variable is string type
variable is number
« two back apostrophe do binding automatically
- convert number to string when setting it on EditText
- convert string text to number when setting in Model
From documentation you can see, two-way binding can be used for many purpose.
- CheckBox, RadioButton, Switch, ToggleButton
- RadioGroup — android:checkedButton
There is an unpublished trick for simple primitive conversions:
I believe it was only added in Android Studio 2.2.
You can still use the original code for two-way binding.
Custom setter and getter for the attribute
Code in Activity
I make 4 demo with ObservableInt, Observable , normal String resource and binding String resource in the xml.
Thanks to the binding adapters from @LongRanger I was able to advance a lot more in my solution but I had to make some changes on the adapters and in my code. First of all I had to init the ObservableInt member like this:
Second, I had to change the adapters given by @LongRanger to be like this:
That way I avoid the error: Invalid int «», when trying to do Integer.parse(. ) on the @InverseBindingAdapter. After this I had to put the cursor on the end of the EditText with the @BindingAdapter, otherwise the cursor kept moving to the start.
@CommonsWare is right, you should use ObservableField instead of ObservableInt . If you really needit as number, just parse it Integer.valueOf(stringNumber) .
EDITED: Or, as mentioned, write custom @InverseBindingAdapter
Источник