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.
Related
I need to manually override the value that Google analytics sends for the deviceCategory predefined user dimension (let's say that instead of "mobile", I need It to be "android phone"). But I couldn't find anywhere in the SDK documentation if this is possible or not, and how to do it, other than using a custom dimension, which is not what I want.
Is this even possible?
You can definitely override some of the default dimensions as shown here You could probably follow the same algo to override other dimensions.
Another thing I'd try is looking at the network request and seeing if deviceCategory can be overriden by setting it as an event propery.
Finally, you can always override any field if you use GTM inbetween, but it's kind of an overkill. You don't want to use it just to slightly shift the field value.
I would generally suggest either not touching it at all if you're just renaming it for the comfort of the analyst or using a custom dimension/event propery to track it if it's a separate datapoint.
I am using MVVM android architecture for my application.
I want to implement click event, so, do we need to use data binding architecture components or we can just use activity for handling the click event and validating the user inputs?
What's the best way to implement this?
Well the question would be using the Databinding or not. Here are some pros and cons of Databinding:
Pros:
Makes the code super clean.
Makes the code shorter.
Easy to test.
Cons:
Sometimes it's hard to debug.
It's a little heavy and increases the compile time.
But... since Google has already anounced it as part of the Android Architecture components I believe you should use it.
What's the best way to implement this?
I don't know how familiar you are with the Databinding but you should know something about Binding Adapters, anw in the onClick you won't be needing it. Just add the android:onClick attribute in the XML file. Also you can find this Codelab to properly implement it:
https://codelabs.developers.google.com/codelabs/android-databinding/#0
Example:
First of all make sure you have the Databinding enabled in your build.gradle
android {
...
dataBinding {
enabled true
}
}
After that go to the layout you will use the databinding (and for that make sure it will be an Activity/Fragment), and just type ALT+ TAB in your IDE and than....
After that, define types, for example a ViewModel and it's name. And in the view that will use the click function add what I said above. (android:onClick="#{() -> viewmodel.onLike()}")
You are not finished. You will somehow need to connect your logic to that databinding, so go to your Java/Kotlin code for your Activity/Fragment and:
Replace the setContentView(R.layout.some_activity) with val binding : SomeActivityBinding =
DataBindingUtil.setContentView(this, R.layout.some_activity)
Notice the SomeActivityBinding will be provided by the IDE itself because is handled on the Databinding library according to the xml naming.
That's the most basic. Good luck.
I am using MVVMCross's wrapper around the Xamarin Android AutoCompleteTextView.
I use the PartialTextChanged changed event to signal that I need to call the ViewModel, from the View, to get some more suggestions.
This works fine up to the point the user selects an item from the list. After that point no changes to the text will cause the PartialTextChanged event to fire. It is as if filtering is turned off once a selection has been made.
There is a SetText method on the AutoCompleteTextView that seems to turn filtering on\off but I am unsure of the best way to use that.
The TextChangedEvent still fires on the control as does AfterTextChanged just not PartialTextChanged and it is that which drives the updates.
I have debugged through the MVVMCross source and cannot see a solution. Any have any ideas?
Where can I browse them mondroid\xamarin android code?
Thanks
After attaching the MVVMCross Source Code and debugging all the events I found that under certain circumstances I was not updating the ItemsSource after the PartialText property was being changed
The FilteringAdapter uses a ManualResetEvent around the change to PartialText and that is only signalled\set by the NotifyDataSetChanged method.
After finding this I also found that #slodge also mentions this in this answer, AutoComplete MVVM and Java Castings without using Java.Lang.Object on ViewModel. A constraint that until now had passed me by.
Note that because of the Android threading model it is essential that
every change in PartialText is met by an eventual signalled change in
ItemsSource - and this should be a single change in object collection
rather than lots of small changes.
Thanks
Is there any way to intercept the Android framework's inflation of xml resources (menus and layouts) to change the strings it uses (e.g. for attributes like android:text="#string/button_trade_commit".)
I know it's possible to override getString() as it's called from an Activity. But framework code doesn't seem to use getString(). For example, in MenuInflator.java, strings come from mContext.obtainStyledAttributes(), and obtainStyledAttributes() is final: I can't override it.
Anybody know of another way to accomplish this?
Background: I want to allow non-English-speaking users to localize my app themselves. I imagine an interface that displays the English strings and lets them enter a translation which is then used in place of the English string from then on. I can imagine also providing a "Share translations" button that uploads the translations, and then,
on the server side, incorporating them into a downloadable module that other users of the same language would get. Being able to substitute strings at runtime is the blocking piece that I can't figure out.
I don't believe you can override the systems getString() methods the way you are looking at it.
It might be worth trying to use a custom attribute and handle the work there: http://developer.android.com/training/custom-views/create-view.html#customattr
I don't think you will be able to modify the process Android uses when inflating resources the way you wanted to.
What you can do is to simply not provide any strings (android:text, etc.) in XML files. You can always obtain a reference to any element in your XML file in the code. Once you have a reference, you can provide texts in the code, taking properly localized strings from your custom framework.
I am not sure about this, but i think you can examine the source of Calligraphy library for Android. It is overriding system LayoutInflater to change the FontType, so i imagine you can do the same to change the strings.
I have a view that displays all the levels of my game. These levels are read by the activity and then passed into the view. I could read them from the view, but it's not really its responsibility, and I'm a fan of separation of concerns.
Right now, I'm calling a setter for this:
((GameView) findViewById(R.id.game)).setLevels(loadLevels());
However, I don't like the fact that the view will be dysfunctional if I forget to call the setter. Is there a better way to pass the levels in?
It is also a bit a matter of preference. Theoretically it's perfectly fine to pass the levels as you're doing. Alternatively, if you need more than just set the levels, but provide further functionalities (i.e. also saving of levels) I normally use a separate class responsible for handling such things (i.e. a Repository, some "Manager" class etc...). This class is then passed into the View on the constructor preferably s.t. one is forced to provide it. Of course, in order to separate things, I use interfaces rather than specific implementations s.t. it may then look as follows:
public class MyView {
public MyView(ILevelLoader levelLoader){
this.levelLoader = levelLoader;
}
...
}
Often, this may not work, because the view is something instantiated by the framework directly rather than by the application. In such a situation you're forced to do it through an appropriate setter. It is some sort of MVC/MVP pattern.
Just for your interest, you might also want to take a look at IoC containers and dependency injection. Guice provided by Google is a nice framework I've already used on Android.
I hope I didn't miss the point, but here goes:
Generally you have either a function setting something (like the text for a textview), or an attribute you set in the xml.
Take a look over at this answer I got on a question: How to layout a 'grid' of images in the center of the screen
There are some things the custom view needs, but lets take an example: 'numColumns'.
you can set it using setNumColumns (that would be the equivalent of your loadLevels() ? )
you can ignore it, it'll revert to default.
you can set it as an attribute lik so: app:numColumns="3"
You can try to use the attribute or the default in the class to accomplish this.
Make your view an abstract class with an abstract method getLevels()? This way, when you instantiate the class if you forget to pass the levels in your code won't compile.
Whether or not this is better is a matter of taste I guess :)