Trying to implement two way binding
As mentioned:
Data Binding Library
Two-way Android Data Binding - How to use two-way Data Binding to manage a layout
2-way Data Binding on Android!
However on
<variable type="com.example.gideonsassoon.avariel.datamodels.Player" name="name"/>
I am getting the following message.:
"Attribute is missing the Android namespace prefix less... (Ctrl+F1)
Most Android views have attributes in the Android namespace. When
referencing these attributes you must include the namespace prefix, or
your attribute will be interpreted by aapt as just a custom attribute.
Similarly, in manifest files, nearly all attributes should be in the
android: namespace."
If I try to build it puts all the R. in my file in red and state they don't exist etc.
I have edited my build gradle file to have
dataBinding.enabled = true
Full code up to the point relevant below
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:windowSoftInputMode="adjustPan"
tools:context="com.example.gideonsassoon.avariel.ui.MainFragmentActivity">
<data>
<variable type="com.example.gideonsassoon.avariel.datamodels.Player" name="name"/>
</data>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v4.view.PagerTabStrip
android:id="#+id/viewpagerStrip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"/>
</android.support.v4.view.ViewPager>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="7dp"
android:layout_marginTop="34dp">
<TextView
android:id="#+id/tv_character_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/name_colon"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textIsSelectable="false" />
<EditText
android:id="#+id/et_character_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#={player.name}"
android:layout_alignBaseline="#+id/tv_character_name"
android:layout_marginStart="15dp"
android:layout_toEndOf="#+id/tv_character_name"
android:ems="12"
android:hint="#string/character_name"
android:inputType="textPersonName" />
Ahh it appears to be that I have it as relativeLayout. It can't be "binding" so it can only be layout. Not sure how that's gonna affect my files as a whole but I guess we'll just have to see how it plays out. Here's my source. However if anyone wants to answer to that effect it would be most appreciated.
Using data binding in Android - Tutorial
Related
I recently migrate binding method from Kotlin synthetics to Jetpack view binding. I have AutofitTextView (by grantland) in my fragment and I set some text to the textview. After I started the activity and attached the fragment, the app crash. The error said
java.lang.ClassCastExceptioni: androidx.appcompt.widget.AppCompatTextView cannot be cast to me.grantland.widget.AutofitTextView
So, I decided to change from AutoFitTextView to AppCompatTextView but I face another issue. I cannot build the app because there is an error
Unresolve reference: setText
I tried various settext methods but none of them works. It seems that the TextView is seen as a View so it does not have a setText method.
========
Config details
Android Studio 4.1.2
buildToolsVersion 28.0.3
jvmTarget 1.8
com.android.databinding:compiler 3.1.4
androidx.appcommpat:appcompat:1.2.0
==========
fragment_main.xml
<FrameLayout
.... >
<LinearLayout
.... >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<me.grantland.widget.AutofitTextView
android:id="#+id/myTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="This is textview" />
....
</LinearLayout>
</LinearLayout>
</FrameLayout>
Set text
FragmentMainBinding.myTextView.text = "The new text"
I found the cause!! It's my mistake. I have 2 layouts with the same name, one for portrait and another one for landscape. I migrate the views in portrait layout but not in landscape layout so when binding class is generated, it generate the two different TextViews as View and View does not have "text" attribute. That's what the error said.
Try this sample.
val binder = FragmentMainBinding.bind(View.inflate(requireContext(), R.layout.fragment_main, null))
binder.myTextView.text = "The new text"
So if that is your entire xml for fragment_main.xml, you need to wrap all of it with <layout> tag. That's the only way the compiler knows to build the binding classes.
<layout
...>
<FrameLayout
.... >
<LinearLayout
.... >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<me.grantland.widget.AutofitTextView
android:id="#+id/myTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="This is textview" />
....
</LinearLayout>
</LinearLayout>
</FrameLayout>
</layout>
I'm creating an ordered list with a custom styling which is used in multiple places. I try to avoid extra code and to create a re-usable layout file for the list item, which can be included to ordered list with certain parameters. How I could do that?
What I have now is following:
layout_ordered_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="order"
type="java.lang.String" />
<variable
name="text"
type="java.lang.String" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/order"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginBottom="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="#{order}"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:text="#{text}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
Then I would like to use that layout like following:
layout_ordered_list.xml
<LinearLayout>
<include layout="#layout/layout_ordered_list_item"
bind:order="1"
bind:text="First text content"/>
<include layout="#layout/layout_ordered_list_item"
bind:order="2"
bind:text="Second text content"/>
etc.
</LinearLayout>
Note that I'm not interested about setting variables in code dynamically. I use these layouts only with hard-coded values (or with string resources) like in my example. But since I'm using these so many times, I don't want to copy-paste list item again and again just to alter order and text content. I also know that my example is not working, it's here just to demonstrate how I would like it to work.
I've already searched the answer from Android documents but there is no example like that.
https://developer.android.com/training/improving-layouts/reusing-layouts.html
https://developer.android.com/topic/libraries/data-binding/index.html#includes
Pretty much identical question has been also asked before in SO but there is no usable answer either: How to Re-using Layouts with <include/> with parameters?
You should be able to achieve what you want by using the databinding library to inflate the including layout, and then passing in the hard coded text using a databinding statement.
Details on the databinding expression language can be found here.
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<LinearLayout>
<include layout="#layout/layout_ordered_list_item"
bind:order="#{`1`}"
bind:text="#{`First text content`}"/>
<include layout="#layout/layout_ordered_list_item"
bind:order="#{`2`}"
bind:text="#{`Second text content`}"/>
</LinearLayout>
</layout>
I have 2 layouts: one for v19+ and another for earlier versions. They contain different views with different ids. How can I say Android DataBinding framework that I want to work with both layouts? It generates views only for one layout (selects randomly).
layout/temp_view.xml :
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="block"
type="ru.temp.model.content.blocks.WebMediaBlock" />
<import type="ru.temp.model.Types.ProviderTypes" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:background="#android:color/white">
<ImageView
android:id="#+id/provider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingTop="#dimen/size5"
android:src="#{ProviderTypes.fromString(block.provider).getResId()}" />
</FrameLayout>
</layout>
layout-v19/temp_view.xml :
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="block"
type="ru.temp.model.content.blocks.WebMediaBlock" />
<import type="ru.temp.model.Types.ProviderTypes" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:background="#android:color/white">
<ru.temp.utils.EmbedView
android:id="#+id/media_embed"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ru.temp.structure.static_material.CreditsView
android:id="#+id/credits_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</layout>
Update:
Finally I've found out the root of the problem. I don't know why but it does not generate *BindingImpl files when use minSdkVersion 21. If specify earlier versions it works as said #yigit
Data binding will generate a base class that serves as a common interface for both (the variables). Data binding will take care of creating the right instance when you call DataBindingUtil.setContentView(activity, R.layout.tmp_view).
For instance, in your example, it will generate
TempViewBinding, TempViewBindingImpl and TempViewBindingV19Impl.
You can check these classes inside <app module>/build/intermediates/classes/<your package>/databinding/ after you compile.
TempViewBinding is the base class and it will have the combination of variables and views for each layout.
If you are not seeing them in the IDE, might be an auto-completion bug in AS (please file a bug).
I pulled this section of code from: https://github.com/slodge/MvvmCross-Tutorials/blob/master/MoreControls/MoreControls.Droid/Resources/Layout/FirstView.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Mvx.MvxSpinner
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
local:MvxBind="ItemsSource Shapes; SelectedItem Current" />
<!--
could be customised using
local:MvxDropDownItemTemplate="#layout/spinner_dropdownitem_shape"
local:MvxItemTemplate="#layout/spinner_item_shape"
-->
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
local:MvxBind="Text Current" />
<MC.ShapeView
android:layout_width="fill_parent"
android:layout_height="300dp"
local:MvxBind="Shape Current" />
</LinearLayout>
The comment mentions it is possible to customize the look by passing MvxDropDownItemTemplate and MvxItemTemplate a layout. Let's assume we are going to use this simple layout for both templates:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res/Project.Ui.Droid"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
local:MvxBind="Text ???????" />
</FrameLayout>
The MvxSpinner displays the enumerated name (Circle, Square, Triangle) as the text for each item. Without changing the view model, is it possible to create a binding, in the template, that displays the same thing the MvxSpinner displays by default when no template is used? If so, what would that binding look like? If that's not possible, what is the best way to accomplish this outcome?
in the template, that displays the same thing the MvxSpinner displays by default when no template is used? If so, what would that binding look like? If that's not possible, what is the best way to accomplish this outcome?
The default template uses ToString() on the object.
To achieve the same thing, you can use the Whole Object binding. From the wiki, you should be able to specify using an empty Path or a single Period for the Path. Since we've seen some issues reported recently with empty Path binding, I recommend using a Period:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res/Project.Ui.Droid"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
local:MvxBind="Text ." />
</FrameLayout>
i would like to know why eclipse is showing warning "[I18N] Hardcoded string "TextView", should use #string resource" in the xml code below .Actually i am trying to get the text written by user in an edit Text in an activity to this current activity.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="0.01"
android:text="TextView" />
</LinearLayout>
The reason that you are receiving a warning, is due to the fact that you are trying to hardcode a string which is not good convention in Android programming due to possible redundancy:
<TextView
...
android:text="TextView" />
You should rather create a reference to a string in the .../res/values/strings.xml file like so:
<TextView
...
android:text="#string/TextView" />
.. and define it in your strings.xml file:
<string name="TextView">TextView</string>
Hope this helps.
As it says, you are using a "hard-coded" string which is less efficient than using the String resource. Simply remove
android:text="TextView"
if you don't want the warning to show. If you want it there then disregard the warning or add it to the String resource file. The Text property isn't needed. If you are expecting user input then you should change it to an EditText anyway unless you have a reason for using TextView
<EditText
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="0.01" />
Then if you want it to display something such as "Enter input here" in the View then you can add android:hint"Text to display". But this will give you the same warning if you don't add it to the strings.xml and use android:hint="#string/nameInStringsFile".
But these warnings are just that. Suggesting possibly more efficient methods or ways of implementing whatever you are doing.
Change the XML to the following to remove the warning
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="0.01" />
</LinearLayout>
The reason you are seeing the warning is because you had set the text to "TextView" inside the XML layout file. It is Android best practice to put all Strings inside the strings.xml file in your res/values folder which creates string resources. One you have a string in a resource file you can reference it from your layout file using the syntax "#string/string_name".