Most popular MVVM-frameworks allow some kind of loops for list type properties. For example Knockout has the foreach-binding. It allows you to loop through the elements of the list property and for each element the markup contained in the foreach-loop is duplicated. Inside the copy, the current element is used as the context for data-binding.
I was looking for something similar in Android, but I only saw the possibility to bind a list to a specific ui-element. But this is bad with respect to declarativeness because I need to create a UI element in code.
Is there a way to simulate something similar using the data binding features from Android? If not, is there a workaround? Or a way to extend the binding syntax?
As #tynn answered, this kind of api is not available.
To achieve the same result, you can setup an adapter for RecyclerView in XML itself. I have implemented this feature in my MVVM library. See Setup RecyclerView from XML itself.
Your XML will look as follows:
<android.support.v7.widget.RecyclerView
bind:items="#{vm.itemVms}"
bind:layout_vertical="#{true}"
bind:view_provider="#{#layout/row_item}" />
<!-- Same arguments for ViewPager-->
<android.support.v4.widget.ViewPager
bind:items="#{vm.itemVms}"
bind:view_provider="#{#layout/row_item}" />
Additionally, there is support for displaying different kinds of child views based on your ViewModel. See Using different types of child views
It's not possible as is. The android databinding library uses static XML layout and binds values to attributes. Creating static layout dynamically is not supported and I assume won't ever be. If you want to create a view hierarchy dynamically you still should use views with adapters. That's something you can do with databindings. Just create your own databinding adapter for binding a list to a RecyclerVier. You could bind to a pair of binding:iterator and binding:layout attributes for example and set the RecyclerVier.Adapter inside the databinding adapter.
Related
I am generating an dynamic layout from API JSON response. Once the layout is created I need to fetch values from a model class and assign it to the dynamically generated view. The problem is how can I achieve this in runtime? I know this is possible with reflection but is there any other alternative approaches. Since reflection is very slow this might affect app performance.
I saw some articles when Data Binding was announced have titles like this "Time To Leave findViewById", for some reason I thought it's going to be a replacement for libs like butterknife but when I looked at it and it seemed to me that it's only links model classes to view (title -> R.id.title) so when change title in view or in code it will reflect on the other end.
Is that all to it or am I missing something else?
That is one aspect, but it isn't the biggest. You can add expressions to do XML and have the data assigned directly to the View. For example, if you have a TextView showing the first name, you might have an expression like:
<TextView android:text="#{user.firstName}" .../>
This helps eliminate the boilerplate code linking data to the UI. It is another reason not to need findViewById.
Another convenience is that you can assign event listeners to your views in the XML. It appears similar to android:onClick, though it doesn't have the performance overhead of reflection.
There are other conveniences, but the major one is the data linking to the UI.
When finding most views in Android, one can usually use findViewById(R.id.my_id) where the id looks like android:id="#+id/my_id" in the XML file.
When using any kind of ListView, we have to use findViewById(android.R.id.my_id) and in the XML we use android:id="#android:id/my_id".
Can someone please explain to me why this is and why it makes a difference?
Thanks!
When using any kind of ListView, we have to use findViewById(android.R.id.my_id) and in the XML we use android:id="#android:id/my_id".
No, you do not. In fact, what you have there most likely will not compile.
If you are inheriting from classes like ListActivity or ListFragment, then you need to use a framework-defined #android:id/list / android.R.id.list identifier for the ListView that those classes will manage. That is so ListActivity or ListFragment can find the ListView that you want it to manage for you.
In any other circumstance, you are welcome to name your ListView whatever you like, as with any other widget or container.
In your custom views you usually define you own ids #+id/your_own_id. Elements from libraries use the same notation. However elements from the SDK use the android prefix.
If you include a ListView in your layout it is common to give it a standard id #android:id/list. Some SDK classes expect standard ids. For example if you had a custom layout for a ListFragment the layout HAS TO include a ListView element with a standard id.
The Android documentation implies that I should prefer to use XML when declaring the UI: http://developer.android.com/guide/topics/ui/declaring-layout.html
Regardless of whether you agree that it implies this, my personal preference is to use XML when possible.
However, for ListView the documentation only explains how to populate it programmatically: http://developer.android.com/guide/topics/ui/layout/listview.html
How do I, say, create a ListView with three elements using only the XML layout file? Is this impossible or undesirable?
Being used to developing for the Desktop, I am not accustomed to being required to manually create elements of UI containers, so I am confused as to whether I am missing something or things are different in Android.
ListView and similar Views will, in general, receive data coming from a dynamic source (like a SQLite database). In that case, the only way to populate it is programmatically.
However, if you have a static list of elements, you can populate it via XML with the following attribute: android:entries. The value would be an array resource.
Example:
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="#array/your_array"
/>
ListView uses ListAdapter which provide a View for each Item in ListView. The template for this item view you can very well define as another XML layout. As far as data is concerned, you can place it in an XML file in res/values folder as a String Array etc. Or even parse from some other file.
A totally hardcoded layout will that be of a LinearLayout placed inside a ScrollView. Then you can add many child elements to LinearLayout.
The page layout is like:
An header image first
a table or list with one record each line
for each record, it has an image and 2 text view
how can I design this layout and populate the data dynamically, e.g. via web download or an data file(xml/text format)?
I can't figure out how the binding works and should I use a table layout with table row or just list view with some customizations?
Actually, this is going to be a broad question because you are asking about to fetch data from web and also need to customize the listview to display data.
To fetch data from Web: You haven't mentioned whether it is SOAP or RESTful webservice? Also what you will receive in response i.e. XML or JSON? For best, i would suggest RESTful with JSON.
To customize ListView: I can give you answer for customizing ListView, for that you can create a custom adapter class by extending BaseAdapter, implement the onView() method with inflation of custom row layout file (1 ImageView + 2 TextViews), check this: Android custom adapter for ListView
The page layout is... it has an image and 2 text view.
Elaborating on jitendra's answer: Yes, a ListView seems ideal for this set up. A TableView is doable, but is really more ideal for a rows/columns structure and that does not sound like what you need.
How can I design this layout ... ?
You would use the android XML to name and style the elements. The best practice is to make a layout file for the screen containing the list itself. Make a second layout file to house a generic record. In other words, you typically design the record separately from the list and its containers. There are several great tutorial on Layouts on the Android Developer's website.
How can I... populate the data dynamically?
There are two parts to this question. First, in code you will need an Adapter of some kind to convert the Data to the actual Views. The ListView will be linked to the Adapter. The Adapter will inflate the Layout XML that you create for the Record. Different Adapters have different guidelines for customizing the Views. As mentioned by Paresh, a BaseAdapter is a great class, but you really should look at the different Adapters provided and see if they already meet your need.
Second, to get the data...1) from the web depends a lot on your web server and how it distributes data. Without more information, you are unlikely to get any solid answers. We can only make recommendations. 2) If you are going via a data file, things change considerably. You can make an Array of objects from a custom Class designed around your data. If you need Sorting, a Tree might be better. If each record has a unique key, a Set or List might do you well. Based on your question, I find myself assuming that you are unfamiliar with Android development, so I would recommend a datafile loaded into an Array with an ArrayAdapter. This will at least help you get a little more familiar with your own project and how it relates to the Android environment.
I can't figure out how the binding works
Unfortunately, it depends on your View and its Adapter. A CursorAdapter does most of its data binding in the bindView() method of the Adapter, but inflates the View in the getView() method. A BaseAdapter does this in the onView() method. If you need to get more familiar with Adapters and their capabilities, read the Android Developer Resources. They have great samples and code. Also, do a search there for "custom adapter" and you will be linked to a ton of other tutorials.
At this point, I recommend strongly, two actions for you. 1) Make a few decisions. Either you get the data from the web or a data file. If you want to do the other later, great. Get a handle on one, that way we can help you more effectively. 2) Use both Google and Android Developer Resources search functionality with the phrases that define your project. If you add the word tutorial or example, you'll be sure to find plenty to help you make those decisions so that we can tailor a solution that meets your needs.
Hope this helps!
FuzzicalLogic
According to your requirements ListView would be good, and you would need to use adapter to bind data with view.
Please read about listview and adapter to implement these.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:background="#drawable/img_list_background_repeater"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/empty_category"/>
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
No one will give you all java class and xml both.
You frame a xml. Then using adapter try to implent data to the list view.
If then you have any problem, provide your code. Then that can be solved.