I have an Android Application and use Xamarin and MvvmCross. I have a EditText and would like to call a command everytime the text changes.
The command in the VM:
public MvxCommand<string> SearchContactsCommand => new MvxCommand<string>(SearchContacts);
private void SearchContacts(string searchTerm)
{
// Do search
}
And this is the Edit box:
<android.support.design.widget.TextInputLayout
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
local:MvxLang="Hint SearchPlaceholder"
local:MvxBind="TextChanged SearchContactsCommand" />
</android.support.design.widget.TextInputLayout>
I tried it with different variations of TextChanged without success.
If possible I would like to avoid having a property on the VM for the searchterm and execute the search in the setter of it.
Is there any way how I can achieve that or do I have to write a custom binding?
Version:
- MvvmCross 5.6.3
- MvvmCross.Binding 5.6.3
Currently there is no built in binding that can do that, you'll have to do a custom one. Here you can see almost all of the built bindings there are. The others are in Droid support plugins in the Mvx{NameOfTheDroidSupportPart}SetupHelper.cs files like MvxPreferenceSetupHelper.cs inside MvvmCross.Droid.Support.V7.Preference if you want to see them too.
I'm not sure what you are aiming with that but if you want to do an autocomplete you can use MvxAutoCompleteTextView. Here you have an example. And also look into this that is the binding the autocomplete uses to fire the change every time the value changes you just have to adapt it to trigger a command with the value as the parameter.
Any problem just ask and I'll be glad to help
Related
I just began to learn data binding and I have some troubles in understanding its technique
in my following code, I have enabled data binding in the app Gradle file in order to use it and get rid of the findviewbyid() ... So I've created the binding variable as lateinit before the oncreate() function and then I initialized it in the on create fun like this: binding = DataBindingUtil.setContentView(this, R.layout.activity_main) and I will give you an example of a view in my XML file to complete on ...
<EditText
android:id="#+id/nickName_editText"
style="#android:style/Widget.DeviceDefault.Light.EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/Margin"
android:layout_marginTop="#dimen/Margin"
android:layout_marginRight="#dimen/Margin"
android:hint="#string/hint"
android:inputType="textPersonName"
android:textAlignment="center" />
Back to the kotlin file what is the difference between these two lines of code below (*Both lines are working)
nickName_editText.visibility = View.VISIBLE
binding.nickNameEditText.visibility = View.VISIBLE
I know that we want to get rid of the findviewbyid() to make the app faster but why don't we do it like in the first line and we are not calling findViewById() too
I'm new to android development so I might not be able to understand that complicated answers :‑D
Thanks for helping!
These are both forms of data binding, binding.nicknameEditText is Androids implementation, and the recommended approach. "nickName_editText" is Kotlin data binding and has known bug issues, when you get into more complicated views they'll start to pop up.
Expanded your imports in the MainActivity, you'll notice the following import.
import kotlinx.android.synthetic.main.activity_main.*
The start indicates binding for all views in the layout.
If you "remove kotlinx.android.synthetic.main.activity_main.*" you'll notice that the "nickName_EditText" is now undefined.
You can also view the Kotlin byte code by
clicking on tools/Kotlin/show Kotlin ByteCode
If you click on "nickName_editText" you'll notice the bytecode for this section will be highlighted.
Hopefully, this answers all your questions
I use data binging in a view holder of a recycler view. For showing an inactive row, I set foreground to a color and this is working perfect on my Nexus6 and many other devices.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:foreground="#{subscribed.isAutoRenew() ? #color/transparent : #color/bg_inactive}">
other stuff ...
</RelativeLayout>
The problem is this code is not working on Samsung SM-N900 with android 5.0. I can solve it by using java code instead of data binding. Any suggestion how to solve it by data binding?
Data binding avoids method calls that don't exist on older platforms. If the device that you're testing on is older than API 23 (Marshmallow), then it will refuse to call setForeground(). Data Binding doesn't have a magical way to give the RelativeLayout the foreground capability, so you'll have to do what you do in the Java Code. Give your layout a FrameLayout wrapper and assign the foreground to it.
<FrameLayout ...
android:foreground="#{subscribed.isAutoRenew() ? #color/transparent : #color/bg_inactive}">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white">
other stuff ...
</RelativeLayout>
</FrameLayout>
-- edit --
Based on the comment, I must conclude that there must be a bug in Data Binding in which it detects the version of View.setForeground() and sees that it is API 23, so skips it. It must not be checking FrameLayout.setForegound(). I'll file a bug on this.
In the mean time, you can work around it by creating your own BindingAdapter:
#BindingAdapter("android:foreground")
public static void setForeground(FrameLayout view, Drawable drawable) {
view.setForeground(drawable);
}
Where to see a list of all attributes of all view types in Android?
I got an impression, that ImageButton does not have enabled and pressed attributes. At least, they didn't work when I set them in XML. Also I found a lot of "guides" on how to make these button either disabled and/or pressed.
Simultaneously, when I bound them with data binding
<ImageButton
android:id="#+id/locate_button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_toRightOf="#id/bookmark_button"
android:enabled="#{activity.locateEnabled}"
android:pressed="#{activity.locatePressed}"
android:onClick="#{activity.onLocateClick}"
android:src="#drawable/locate_selector"
android:background="#null"
/>
they just worked. Both pressed and enabled. At the same moment pressed is even reported as unknown property by Android Studion spell checked!
So, what is it?
1) by-design behaviour and I just don't understand something (what?)
2) sugar from data binding library
3) hacking
4) ????
How to know, how poratble is this feature?
The answer is both 1 and 2. Data binding will allow you use an attribute to call any setter on a View. You can look at the data binding guide's section on attribute setters.
When you set the android:enabled attribute, you are using Android data binding's the automatic setters to calls setEnabled(). Android data binding sees the attribute name (enabled) and looks for a setter with that name and finds setEnabled(). The same is true for android:pressed -- there is a setPressed() method. Yay for convention!
android:onClick is a real attribute, but data binding doesn't use it. There is no setOnClick() method, either. Instead, there is a Binding Adapter that sets an OnClickListener to call your onLocateClick() method. There is a bit of magic involved in this that relies on the Annotation Processor that data binding uses to examine your code, but suffice it to say that it does this at compile time instead of using runtime reflection.
All event listeners should have Binding Adapters written for them with the same name as the event (as opposed to the listener name). So, you can also set android:onLongClick, for example. You may also be interested in the lambda syntax for events.
I'm not sure what you mean by "portable." Data Binding is usable at least back to Gingerbread (we claim Froyo, but really, who targets Froyo?), but you won't be able to transfer it to iOS or anything like that. All of Android data binding is done with a small runtime library and generated code. You don't have to worry about specific versions of Android.
I have a list view which binds to an array of strings as such:
<Mvx.MvxListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxBind="ItemsSource StringArray"
local:MvxItemTemplate="#layout/listitem_view" />
My item template is simply just a text view...
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
which bound fine using JSON...
local:MvxBind="{'Text':{'Text':''}}" />
and again using Swiss...
local:MvxBind="Text " />
but after updating Mvx to 3.10 I'm now not getting anything bound to my text view even though the list is still bound to the list view. Has the syntax in Rio binding changed the default behaviour?
There was no intended change to this area in 3.0.10 - although there was a fix for this Error when making bind ObservableCollection<string> for a MvxListView - fix was https://github.com/slodge/MvvmCross/commit/d325fb75eaeeb8e470e0ac551f2b69b441f7b285. I believe this was released and worked in 3.0.10 for a test app.
Has the syntax in Rio binding changed the default behaviour?
I don't know if anyone has seen any issues with these in MethodBinding or FieldBinding as part of the Rio extensions. I've not heard of any.
If this is broken - and depending on whether this is broken due to the binding engine (Tibet) or the Method and Field extensions (Rio) or something else, then possible workarounds include:
switching away from Rio
using the period "." alternative to empty space - e.g. local:MvxBind="Text ."
adding a public object HackSelf { get { return this; } property to the bound object and binding to that local:MvxBind="Text HackSelf"
overriding the registered binding engine (e.g. back to Swiss)
If this is broken - it might also be a good idea to log an issue on github for this - including modules loaded, use case, version used, any suspicious trace output seen and a link back here.
I've been working on the 'Tip Calculator' app for Android and I have a couple of questions.
I'm supposed to (in the process of creating the GUI) use some EditTexts to allow the user to enter the bill amount and read the calculated total bill. In the version I have, there is no EditText anywhere in the Visual Layout Editor, only CheckText. Are these the same?
Whenever I try to edit the Java code for the app, as per the book I have, I keep getting the message:
Thus and such is never used
For example, with
private static final String BILL_TOTAL = "BILL_TOTAL';
or anything from the import Android list, other than the one referring to a bundle. I'm Not sure how to resolve this. I have some experience with C and C++, but Java is new to me.
The warning that tells you that a variable or method or import is not used can be ignored, especially if you just haven't gotten to using it yet. It's a warning and not an error, so your app should compile regardless.
I don't know what you're using to build your layout (eclipse? I use Intellij Idea), but to add an EditText, you can edit the layout file by hand. Add a line similar to:
<EditText android:id="#+id/myEditText android:width="FILL_PARENT" android:height="WRAP_CONTENT"/>
As a general rule, I like to edit these things by hand. Then, when something breaks or doesn't work as I expect it to, I have some grasp of what's in there, and so I can usually fix it. The value gained by learning how to create a layout by hand easily offsets the value of the time that you'll save.
Good luck.