Inverse Boolean using Two Way Databinding - android

Using two-way Android Databinding, is it possible to have a generic inverse boolean converter? For example, I would like to do something like this:
<Switch android:checked="#={!viewModel.myBoolean}" />
When I run this in Android, the switch just rapidly fires back and forth. I tried to create a two way binding app:inverseChecked following some examples from George Mount, but I was not successful (just kept getting error stating cannot find event 'inverseCheckedAttrChanged' on View type 'android.widget.Switch').
As a comparison, using Aurelia this just works as you would expect for two way binding. In WPF, probably the first converter you make is some sort of InverseBooleanConverter to easily tackle these sorts of things. So, am assuming I am just missing something obvious here.

I actually didn't expect it to work at all. I assume, it's switching back and forth all the time, because the bindings don't apply inverse function of your binding expression.
That said, I tested the behavior with the current data binding library version and checked the generated sources. With the simple example of android:checked these show notes how the inverse should look like and apply it appropriately.
Also George Mount wrote a Blog post about it a short while ago: https://medium.com/google-developers/android-data-binding-inverse-functions-95aab4b11873
If you try to implement an app:inverseChecked, you'd also have to implement a #BindingAdapter("inverseChecked") as setter, #InverseBindingAdapter(attribute="inverseChecked") as getter and #BindingAdapter("inverseCheckedAttrChanged") for setting up the change listener.
The latter could look like the following:
#BindingAdapter("inverseCheckedAttrChanged")
public static void setupInverseCheckedAttrChanged(Switch view, InverseBindingListener listener) {
OnCheckedChangeListener newListener = null;
if (listener != null) {
newListener = (v,b) -> listener.onChange();
}
view.setOnCheckedChangeListener(newListener);
}

Related

How can I have 2 different fragment, implementing same methods without writing the code twice?

I have a fragment screen where there is a form that is used to create Questions and Answers for my app. For this fragment, I use data binding, then I created many functions to validate the form, and check other stuffs.
Now, I'm creating a different fragment screen, where I'll be able to edit this Questions and Answers that were created, and for this, I want to use the same functions that were used when I created on the other fragment, for example to validate the fields that the user is editing.
I thought about implementing an Interface, and put these common functions there, so I could use it on both fragments. However, in these functions I use DataBinding, and I don't know how I can use it on the interface, so it would get the correct XML variables regarding to one fragment, or the other one.
On the screenshot bellow, it shows that I'm trying to use the binding, however I can't specify which one I'm using, otherwise the code will work only for a fragment, and not for both. Consequently, I tried to declare as DataBindingUtil but it didn't work.
Screenshot interface
If you want to go with this approach you could add the views as fields in the interface:
interface IQuestionForm {
var newQuestionTextInput: EditText
var answer1TextField: EditText
fun validateAllParametersToCreateNewQuestion(){
var allTextInputSet = true
if (newQuestionTextInput.text.isNullOrEmpty()){
newQuestionTextInput.error = "You have to enter the question"
allTextInputSet = false
}
if (answer1TextField.text.isNullOrEmpty()){
answer1TextField.error = "You have to enter an answer"
allTextInputSet = false
}
....
}
}
Then initialise those fields after creating the binding in the fragment.

Preventing double clicking in components throughout entire app

I know how to prevent double-clicking on a component. What I want to know if there is some way to avoid this behaviour "by default" when adding a component. Do I have to go every single item that can be clicked in an app and write the same code for every single component?
I know I could subclass, say, Button class, write the code for preventing double-clicking there, and only use my Button class in the app. What is the point of it? Why isn't something like that in the default Android Button class? I haven't seen any intended double-clicking behaviour in ANY app. Do I have to write a subclass of every single View that is susceptible of being clicked in order to prevent this? is there something I am missing?
Just to clarify, my question is about something like disableDoubleClick() method or something like that. I already said I know how to prevent this, but is a bit of a hassle to do it for every single clickable item in an app.
You can use Kotlin with its extensions in conjunction with reactive bindings of RxJava.
for the general view it will look something like:
fun View.clickWithDebounce(debounceTime: Long = 600L, action: () -> Unit): Disposable =
RxView.clicks(this)
.debounce(debounceTime, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { action() }
Use it like this:
button.clickWithDebounce{
//do stuff
}
textView.clickWithDebounce{
//do other stuff
}
imageView.clickWithDebounce{
//do some completely unrelated with the previous two stuff
}
floatingButton.clickWithDebounce(100000000){
//do some stuff and wait 100000 seconds before the next click
}
For more info: Kotlin Extensions, RxJava RxBinding
Hope it helps.

Best practice to access property in kotlin

I comes from Java background and working first time on Kotlin. For most of the people it will be basic question, but it may help people who start working first time on Kotlin and comes from Java background
So, let say I have listadapter and I want to set list of item in that. I have two options now.
1) create a private property which stores list of items and then create a setter for it, which set the list and call notifydatasetChanged()
2) create a property with set property function and then access like instance.property
Which will be better option in Kotlin out of above two options.
A property in Kotlin is nothing else then a getter and setter for a value. If you don't want to provide a getter, you have to use a fun setData(data: List).
Otherwise it's also possible to handle everything with the property
var data = listOf()
set(data: List) {
field = data
notifydatasetChanged()
}
But eventually it's even better to use an implementation with DiffUtil.

Find multiple elements in web view with espresso

I'm testing a hybrid app, where each view has a web view.
In one of these web views I have a list of elements with the same attribute. They have the same xpath locator that is something like:
//h4[contains(#data-role, 'product-name')]
I want to create a list of these elements and iterate through them, count them, get their attributes.
In the documentation, I found two similar methods:
findElement(locator, value)
and
findMultipleElements(locator, value)
Though it's totally unclear to me how to use it. I tried to find examples on it but with no success.
Could someone help me with this?
Here is the solution that I have found.
#kaqqao is right that findMultipleItems call returns Atom<List<ElementReference>> that is not usable with onWebView() because there you have only withElement() that accepts either Atom<ElementReference> or just ElementReference
What you can do though is perform your action that find multiple items and just get results from your Atom. This is how it works internally if you check the source of doEval method inside Web.java for espresso.
val elements = with(AtomAction(findMultipleElements(
Locator.XPATH,
"YOUR_COMPLEX_XPATH"
), null, null)) {
onView(ViewMatchers.isAssignableFrom(WebView::class.java)).perform(this)
this.get()
}
This code will give you List<ElementMatcher>.
Then just run it as
elements.forEach {
onWebView().forceJavascriptEnabled().withElement(it).perform(webClick())
}
Can you try something like that? Since what you should care about is really the ElementReference and you can iterate the lsit returned from findMultipleElements with simple for/foreach statement:
yourList = findMultipleElements(locator, value);
yourList.size(); //this will get you the count of found elements with that locator
for(Atom<ElementReference> item : yourList ){
item.getAttribute...
//and whatever you want
}

include tag in xml file of Android Programming

I have a question regarding the tag. Actually I am new to the Android Programming and I want to use the Concept of Reusability in my Application at several places. I get to know that it is possible by the tag but I don't know how to use that. I have refered some of it's examples from the net but didn't found them quite satisfactory.
Can anybody please make me understand it with a Clear and appearant example!
Thanks
john
Let's say on an activity you have several buttons, all almost doing similar stuff onClick. Now you can use an onClick method, but since you cannot pass parameters in the onClick attribute, you need to put it somewhere else, which is where tag comes in handy.
In your layout you might have:
<Button android:id="#+id/btn1"
android:tag="paramValue1"
android:onClick="myOnClick"/>
<Button android:id="#+id/btn2"
android:tag="paramValue2"
android:onClick="myOnClick"/>
Then you can use one central custom onClickListener (especially if you want to reuse amonst multiple activities) or like in my case just a method in my activity for your buttons that handle the actions for it.
public void myOnClick(View v) {
String param = (String) v.getTag();
....
}
This is especially useful for generic actions, and also if you want to reuse code (i.e. same button listener) amongst multiple classes/activities.
This way you don't rely on a switch/case and checking your button (view) id; staying more independent from your activity itself.

Categories

Resources