How Do We Get SpannedString Objects From String Resources Using Data Binding?
Florina Muntenescu wrote up a cool post about using <annotation>
in string resources for being able to have flexible markup that you can process in your app using custom spans. I am trying to leverage it in data binding, but I cannot quite figure out how to get a SpannedString
edition of the string resource from data binding.
In my layout, I have app:thingy="@{@string/my_annotated_string}"
as an attribute on a TextView
. I have a binding adapter set up to handle thingy
attributes. However, the data binding system seems to insist that my value is a String
.
I have tried:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: SpannedString) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: Spanned) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
In all cases, I get Cannot find the setter for attribute 'app:thingy' with parameter type java.lang.String on android.widget.TextView
build errors.
If I use String
or CharSequence
for the thingy
parameter type, it builds, but then I get passed a String
and I do not have my annotation spans from the string resource.
So, how can I either:
- Get the
SpannedString
corresponding to my string resource (i.e., what you get fromgetText()
instead ofgetString()
), or - Get the string resource ID of my string resource, so I can call
getText()
myself to get mySpannedString
android android-resources android-databinding
|
show 3 more comments
Florina Muntenescu wrote up a cool post about using <annotation>
in string resources for being able to have flexible markup that you can process in your app using custom spans. I am trying to leverage it in data binding, but I cannot quite figure out how to get a SpannedString
edition of the string resource from data binding.
In my layout, I have app:thingy="@{@string/my_annotated_string}"
as an attribute on a TextView
. I have a binding adapter set up to handle thingy
attributes. However, the data binding system seems to insist that my value is a String
.
I have tried:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: SpannedString) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: Spanned) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
In all cases, I get Cannot find the setter for attribute 'app:thingy' with parameter type java.lang.String on android.widget.TextView
build errors.
If I use String
or CharSequence
for the thingy
parameter type, it builds, but then I get passed a String
and I do not have my annotation spans from the string resource.
So, how can I either:
- Get the
SpannedString
corresponding to my string resource (i.e., what you get fromgetText()
instead ofgetString()
), or - Get the string resource ID of my string resource, so I can call
getText()
myself to get mySpannedString
android android-resources android-databinding
What is theattr
type forthingy
?
– Ben P.
Nov 1 '18 at 18:15
@BenP.: There is noattr
forthingy
. When the data binding compiler encounters a data binding expression, it looks for binding adapters based on the attribute name.
– CommonsWare
Nov 1 '18 at 18:18
Hm, ok. I'm not too familiar with data binding... so how does the system "know" the type to expect? Do you have aString getThingy()
method?
– Ben P.
Nov 1 '18 at 18:22
Well, I thought it used reflection to examine the method/function signature of the binding adapter implementation. It seems to do that in other places. In the above code snippets, the first parameter is the type of the widget you are using the binding expression on (TextView
) and the second parameter is the type of the attribute value from the binding expression (Int
,String
, etc.). Perhaps it is just not that flexible when it comes to string resources. That's kinda the point of this question.
– CommonsWare
Nov 1 '18 at 18:25
2
i'm afraid the only thing you could do is to pass a"my_annotated_string"
string to yourhandleThingy
adapter and use infamousResources#getIdentifier()
method
– pskink
Nov 1 '18 at 18:35
|
show 3 more comments
Florina Muntenescu wrote up a cool post about using <annotation>
in string resources for being able to have flexible markup that you can process in your app using custom spans. I am trying to leverage it in data binding, but I cannot quite figure out how to get a SpannedString
edition of the string resource from data binding.
In my layout, I have app:thingy="@{@string/my_annotated_string}"
as an attribute on a TextView
. I have a binding adapter set up to handle thingy
attributes. However, the data binding system seems to insist that my value is a String
.
I have tried:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: SpannedString) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: Spanned) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
In all cases, I get Cannot find the setter for attribute 'app:thingy' with parameter type java.lang.String on android.widget.TextView
build errors.
If I use String
or CharSequence
for the thingy
parameter type, it builds, but then I get passed a String
and I do not have my annotation spans from the string resource.
So, how can I either:
- Get the
SpannedString
corresponding to my string resource (i.e., what you get fromgetText()
instead ofgetString()
), or - Get the string resource ID of my string resource, so I can call
getText()
myself to get mySpannedString
android android-resources android-databinding
Florina Muntenescu wrote up a cool post about using <annotation>
in string resources for being able to have flexible markup that you can process in your app using custom spans. I am trying to leverage it in data binding, but I cannot quite figure out how to get a SpannedString
edition of the string resource from data binding.
In my layout, I have app:thingy="@{@string/my_annotated_string}"
as an attribute on a TextView
. I have a binding adapter set up to handle thingy
attributes. However, the data binding system seems to insist that my value is a String
.
I have tried:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: SpannedString) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, thingy: Spanned) { /* stuff goes here */ }
and:
@BindingAdapter("thingy")
@JvmStatic
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
In all cases, I get Cannot find the setter for attribute 'app:thingy' with parameter type java.lang.String on android.widget.TextView
build errors.
If I use String
or CharSequence
for the thingy
parameter type, it builds, but then I get passed a String
and I do not have my annotation spans from the string resource.
So, how can I either:
- Get the
SpannedString
corresponding to my string resource (i.e., what you get fromgetText()
instead ofgetString()
), or - Get the string resource ID of my string resource, so I can call
getText()
myself to get mySpannedString
android android-resources android-databinding
android android-resources android-databinding
edited Nov 1 '18 at 21:14
asked Nov 1 '18 at 18:07
CommonsWare
764k13818641915
764k13818641915
What is theattr
type forthingy
?
– Ben P.
Nov 1 '18 at 18:15
@BenP.: There is noattr
forthingy
. When the data binding compiler encounters a data binding expression, it looks for binding adapters based on the attribute name.
– CommonsWare
Nov 1 '18 at 18:18
Hm, ok. I'm not too familiar with data binding... so how does the system "know" the type to expect? Do you have aString getThingy()
method?
– Ben P.
Nov 1 '18 at 18:22
Well, I thought it used reflection to examine the method/function signature of the binding adapter implementation. It seems to do that in other places. In the above code snippets, the first parameter is the type of the widget you are using the binding expression on (TextView
) and the second parameter is the type of the attribute value from the binding expression (Int
,String
, etc.). Perhaps it is just not that flexible when it comes to string resources. That's kinda the point of this question.
– CommonsWare
Nov 1 '18 at 18:25
2
i'm afraid the only thing you could do is to pass a"my_annotated_string"
string to yourhandleThingy
adapter and use infamousResources#getIdentifier()
method
– pskink
Nov 1 '18 at 18:35
|
show 3 more comments
What is theattr
type forthingy
?
– Ben P.
Nov 1 '18 at 18:15
@BenP.: There is noattr
forthingy
. When the data binding compiler encounters a data binding expression, it looks for binding adapters based on the attribute name.
– CommonsWare
Nov 1 '18 at 18:18
Hm, ok. I'm not too familiar with data binding... so how does the system "know" the type to expect? Do you have aString getThingy()
method?
– Ben P.
Nov 1 '18 at 18:22
Well, I thought it used reflection to examine the method/function signature of the binding adapter implementation. It seems to do that in other places. In the above code snippets, the first parameter is the type of the widget you are using the binding expression on (TextView
) and the second parameter is the type of the attribute value from the binding expression (Int
,String
, etc.). Perhaps it is just not that flexible when it comes to string resources. That's kinda the point of this question.
– CommonsWare
Nov 1 '18 at 18:25
2
i'm afraid the only thing you could do is to pass a"my_annotated_string"
string to yourhandleThingy
adapter and use infamousResources#getIdentifier()
method
– pskink
Nov 1 '18 at 18:35
What is the
attr
type for thingy
?– Ben P.
Nov 1 '18 at 18:15
What is the
attr
type for thingy
?– Ben P.
Nov 1 '18 at 18:15
@BenP.: There is no
attr
for thingy
. When the data binding compiler encounters a data binding expression, it looks for binding adapters based on the attribute name.– CommonsWare
Nov 1 '18 at 18:18
@BenP.: There is no
attr
for thingy
. When the data binding compiler encounters a data binding expression, it looks for binding adapters based on the attribute name.– CommonsWare
Nov 1 '18 at 18:18
Hm, ok. I'm not too familiar with data binding... so how does the system "know" the type to expect? Do you have a
String getThingy()
method?– Ben P.
Nov 1 '18 at 18:22
Hm, ok. I'm not too familiar with data binding... so how does the system "know" the type to expect? Do you have a
String getThingy()
method?– Ben P.
Nov 1 '18 at 18:22
Well, I thought it used reflection to examine the method/function signature of the binding adapter implementation. It seems to do that in other places. In the above code snippets, the first parameter is the type of the widget you are using the binding expression on (
TextView
) and the second parameter is the type of the attribute value from the binding expression (Int
, String
, etc.). Perhaps it is just not that flexible when it comes to string resources. That's kinda the point of this question.– CommonsWare
Nov 1 '18 at 18:25
Well, I thought it used reflection to examine the method/function signature of the binding adapter implementation. It seems to do that in other places. In the above code snippets, the first parameter is the type of the widget you are using the binding expression on (
TextView
) and the second parameter is the type of the attribute value from the binding expression (Int
, String
, etc.). Perhaps it is just not that flexible when it comes to string resources. That's kinda the point of this question.– CommonsWare
Nov 1 '18 at 18:25
2
2
i'm afraid the only thing you could do is to pass a
"my_annotated_string"
string to your handleThingy
adapter and use infamous Resources#getIdentifier()
method– pskink
Nov 1 '18 at 18:35
i'm afraid the only thing you could do is to pass a
"my_annotated_string"
string to your handleThingy
adapter and use infamous Resources#getIdentifier()
method– pskink
Nov 1 '18 at 18:35
|
show 3 more comments
4 Answers
4
active
oldest
votes
As an expression, @string/my_annotated_string
evaluates to a string. Eventhough it resembles a string resource reference in XML, it's actually only a String
value.
It would be nice to have a @text/my_annotated_string
version as well, but as of the documentation this is not available.
Instead you'd have to use the actual resource within your binding expression:
app:thingy="@{string.my_annotated_string}"
app:thingy="@{context.getText(string.my_annotated_string)}"
This is assuming the import of the string
class:
<import type="path.to.R.string"/>
add a comment |
Here is a maybe slightly less icky way:
Define the annotated string.
<string name="my_annotated_string">A <annotation font="title_emphasis">cool</annotation> annotation <annotation font="title_emphasis">thingy</annotation>.</string>
Place a reference to that string resource into a TypedArray
:
<resources>
<array name="annotated_text">
<item>@string/my_annotated_string</item>
</array>
</resources>
Reference the TypedArray
in the layout:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thingy="@{@typedArray/annotated_text}" />
Finally, set a BindingAdapter
to capture the SpannedString
with the annotations:
@BindingAdapter("thingy")
public static void setThingy(TextView textView, TypedArray strings) {
SpannedString ss = (SpannedString) strings.getText(0);
Object spans = ss.getSpans(0, ss.length(), Object.class);
}
Although a little involved, this works. If there are multiple strings, the array can be expanded.
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
@CommonsWare Maybe, but it is just an introduction of aTypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.
– Cheticamp
Nov 5 '18 at 23:01
add a comment |
Use this binding adapter:
@BindingAdapter("thingy")
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
and instead of using app:thingy="@{@string/my_annotated_string}"
pass resource into binding: thingy="@string/my_annotated_string"
(without app:
).
1
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
add a comment |
one can define just any data-type with <import>
:
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
and then obtain the text from it:
android:text="@{sparse[index]}"
to define a thingy
with data-type SpannedString
(or one that extends SpannedString
):
<data>
<import type="com.acme.model.BindableSpannedString"/>
<variable name="thingy" type="BindableSpannedString"/>
<variable name="index" type="int"/>
</data>
the getter annotated with @Bindable
should be index access:
android:text="@{thingy.getSpanAt(index)}"
SpannedString lacks the getter required to bind it, nor can one add annotations to framework classes.
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows aloadImage()
function as a@BindingAdapter
. Thanks, though!
– CommonsWare
Nov 10 '18 at 14:14
@CommonsWare that example usesapp:
namespace (the default demands@Bindable
getters and setters, which notify). the@BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.
– Martin Zeitler
Nov 10 '18 at 15:07
"that example uses app: namespace" -- that is my use case as well. For example,thingy
is not a standard Android attribute. Your point about@BindingConversion
is interesting -- I might be able to set one up that maps a string resourceInt
to aSpannedString
and address the problem that way. Thanks!
– CommonsWare
Nov 10 '18 at 15:20
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some classBindableSpannedString extends SpannedString
in order add@Bindable
getters should make the data-binding work - and nested values accessible.
– Martin Zeitler
Nov 12 '18 at 11:57
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as aSpannable
,SpannedString
, whatever) for processing in the binding adapter.
– CommonsWare
Nov 12 '18 at 12:33
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53106939%2fhow-do-we-get-spannedstring-objects-from-string-resources-using-data-binding%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
As an expression, @string/my_annotated_string
evaluates to a string. Eventhough it resembles a string resource reference in XML, it's actually only a String
value.
It would be nice to have a @text/my_annotated_string
version as well, but as of the documentation this is not available.
Instead you'd have to use the actual resource within your binding expression:
app:thingy="@{string.my_annotated_string}"
app:thingy="@{context.getText(string.my_annotated_string)}"
This is assuming the import of the string
class:
<import type="path.to.R.string"/>
add a comment |
As an expression, @string/my_annotated_string
evaluates to a string. Eventhough it resembles a string resource reference in XML, it's actually only a String
value.
It would be nice to have a @text/my_annotated_string
version as well, but as of the documentation this is not available.
Instead you'd have to use the actual resource within your binding expression:
app:thingy="@{string.my_annotated_string}"
app:thingy="@{context.getText(string.my_annotated_string)}"
This is assuming the import of the string
class:
<import type="path.to.R.string"/>
add a comment |
As an expression, @string/my_annotated_string
evaluates to a string. Eventhough it resembles a string resource reference in XML, it's actually only a String
value.
It would be nice to have a @text/my_annotated_string
version as well, but as of the documentation this is not available.
Instead you'd have to use the actual resource within your binding expression:
app:thingy="@{string.my_annotated_string}"
app:thingy="@{context.getText(string.my_annotated_string)}"
This is assuming the import of the string
class:
<import type="path.to.R.string"/>
As an expression, @string/my_annotated_string
evaluates to a string. Eventhough it resembles a string resource reference in XML, it's actually only a String
value.
It would be nice to have a @text/my_annotated_string
version as well, but as of the documentation this is not available.
Instead you'd have to use the actual resource within your binding expression:
app:thingy="@{string.my_annotated_string}"
app:thingy="@{context.getText(string.my_annotated_string)}"
This is assuming the import of the string
class:
<import type="path.to.R.string"/>
answered Nov 4 '18 at 21:14
tynn
19.4k54375
19.4k54375
add a comment |
add a comment |
Here is a maybe slightly less icky way:
Define the annotated string.
<string name="my_annotated_string">A <annotation font="title_emphasis">cool</annotation> annotation <annotation font="title_emphasis">thingy</annotation>.</string>
Place a reference to that string resource into a TypedArray
:
<resources>
<array name="annotated_text">
<item>@string/my_annotated_string</item>
</array>
</resources>
Reference the TypedArray
in the layout:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thingy="@{@typedArray/annotated_text}" />
Finally, set a BindingAdapter
to capture the SpannedString
with the annotations:
@BindingAdapter("thingy")
public static void setThingy(TextView textView, TypedArray strings) {
SpannedString ss = (SpannedString) strings.getText(0);
Object spans = ss.getSpans(0, ss.length(), Object.class);
}
Although a little involved, this works. If there are multiple strings, the array can be expanded.
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
@CommonsWare Maybe, but it is just an introduction of aTypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.
– Cheticamp
Nov 5 '18 at 23:01
add a comment |
Here is a maybe slightly less icky way:
Define the annotated string.
<string name="my_annotated_string">A <annotation font="title_emphasis">cool</annotation> annotation <annotation font="title_emphasis">thingy</annotation>.</string>
Place a reference to that string resource into a TypedArray
:
<resources>
<array name="annotated_text">
<item>@string/my_annotated_string</item>
</array>
</resources>
Reference the TypedArray
in the layout:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thingy="@{@typedArray/annotated_text}" />
Finally, set a BindingAdapter
to capture the SpannedString
with the annotations:
@BindingAdapter("thingy")
public static void setThingy(TextView textView, TypedArray strings) {
SpannedString ss = (SpannedString) strings.getText(0);
Object spans = ss.getSpans(0, ss.length(), Object.class);
}
Although a little involved, this works. If there are multiple strings, the array can be expanded.
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
@CommonsWare Maybe, but it is just an introduction of aTypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.
– Cheticamp
Nov 5 '18 at 23:01
add a comment |
Here is a maybe slightly less icky way:
Define the annotated string.
<string name="my_annotated_string">A <annotation font="title_emphasis">cool</annotation> annotation <annotation font="title_emphasis">thingy</annotation>.</string>
Place a reference to that string resource into a TypedArray
:
<resources>
<array name="annotated_text">
<item>@string/my_annotated_string</item>
</array>
</resources>
Reference the TypedArray
in the layout:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thingy="@{@typedArray/annotated_text}" />
Finally, set a BindingAdapter
to capture the SpannedString
with the annotations:
@BindingAdapter("thingy")
public static void setThingy(TextView textView, TypedArray strings) {
SpannedString ss = (SpannedString) strings.getText(0);
Object spans = ss.getSpans(0, ss.length(), Object.class);
}
Although a little involved, this works. If there are multiple strings, the array can be expanded.
Here is a maybe slightly less icky way:
Define the annotated string.
<string name="my_annotated_string">A <annotation font="title_emphasis">cool</annotation> annotation <annotation font="title_emphasis">thingy</annotation>.</string>
Place a reference to that string resource into a TypedArray
:
<resources>
<array name="annotated_text">
<item>@string/my_annotated_string</item>
</array>
</resources>
Reference the TypedArray
in the layout:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:thingy="@{@typedArray/annotated_text}" />
Finally, set a BindingAdapter
to capture the SpannedString
with the annotations:
@BindingAdapter("thingy")
public static void setThingy(TextView textView, TypedArray strings) {
SpannedString ss = (SpannedString) strings.getText(0);
Object spans = ss.getSpans(0, ss.length(), Object.class);
}
Although a little involved, this works. If there are multiple strings, the array can be expanded.
edited Nov 5 '18 at 18:19
answered Nov 5 '18 at 18:07
Cheticamp
25.6k42859
25.6k42859
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
@CommonsWare Maybe, but it is just an introduction of aTypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.
– Cheticamp
Nov 5 '18 at 23:01
add a comment |
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
@CommonsWare Maybe, but it is just an introduction of aTypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.
– Cheticamp
Nov 5 '18 at 23:01
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
That's an interesting approach -- thanks! IMHO, it is more complicated than what I had suggested in the question comments, which is more or less what tynn has in another answer.
– CommonsWare
Nov 5 '18 at 22:56
@CommonsWare Maybe, but it is just an introduction of a
TypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.– Cheticamp
Nov 5 '18 at 23:01
@CommonsWare Maybe, but it is just an introduction of a
TypedArray
which is in the data binding universe as is the entire solution - nothing odd. Multiple strings, if needed, can be collected in the same array.– Cheticamp
Nov 5 '18 at 23:01
add a comment |
Use this binding adapter:
@BindingAdapter("thingy")
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
and instead of using app:thingy="@{@string/my_annotated_string}"
pass resource into binding: thingy="@string/my_annotated_string"
(without app:
).
1
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
add a comment |
Use this binding adapter:
@BindingAdapter("thingy")
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
and instead of using app:thingy="@{@string/my_annotated_string}"
pass resource into binding: thingy="@string/my_annotated_string"
(without app:
).
1
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
add a comment |
Use this binding adapter:
@BindingAdapter("thingy")
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
and instead of using app:thingy="@{@string/my_annotated_string}"
pass resource into binding: thingy="@string/my_annotated_string"
(without app:
).
Use this binding adapter:
@BindingAdapter("thingy")
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
and instead of using app:thingy="@{@string/my_annotated_string}"
pass resource into binding: thingy="@string/my_annotated_string"
(without app:
).
answered Nov 8 '18 at 10:11
Matt Twig
23115
23115
1
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
add a comment |
1
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
1
1
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
Thanks! However, this does not work. The binding adapter does not get invoked. AFAIK, data binding only works on attributes with binding expressions. Tested on AS 3.2.1.
– CommonsWare
Nov 8 '18 at 12:15
add a comment |
one can define just any data-type with <import>
:
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
and then obtain the text from it:
android:text="@{sparse[index]}"
to define a thingy
with data-type SpannedString
(or one that extends SpannedString
):
<data>
<import type="com.acme.model.BindableSpannedString"/>
<variable name="thingy" type="BindableSpannedString"/>
<variable name="index" type="int"/>
</data>
the getter annotated with @Bindable
should be index access:
android:text="@{thingy.getSpanAt(index)}"
SpannedString lacks the getter required to bind it, nor can one add annotations to framework classes.
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows aloadImage()
function as a@BindingAdapter
. Thanks, though!
– CommonsWare
Nov 10 '18 at 14:14
@CommonsWare that example usesapp:
namespace (the default demands@Bindable
getters and setters, which notify). the@BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.
– Martin Zeitler
Nov 10 '18 at 15:07
"that example uses app: namespace" -- that is my use case as well. For example,thingy
is not a standard Android attribute. Your point about@BindingConversion
is interesting -- I might be able to set one up that maps a string resourceInt
to aSpannedString
and address the problem that way. Thanks!
– CommonsWare
Nov 10 '18 at 15:20
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some classBindableSpannedString extends SpannedString
in order add@Bindable
getters should make the data-binding work - and nested values accessible.
– Martin Zeitler
Nov 12 '18 at 11:57
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as aSpannable
,SpannedString
, whatever) for processing in the binding adapter.
– CommonsWare
Nov 12 '18 at 12:33
|
show 2 more comments
one can define just any data-type with <import>
:
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
and then obtain the text from it:
android:text="@{sparse[index]}"
to define a thingy
with data-type SpannedString
(or one that extends SpannedString
):
<data>
<import type="com.acme.model.BindableSpannedString"/>
<variable name="thingy" type="BindableSpannedString"/>
<variable name="index" type="int"/>
</data>
the getter annotated with @Bindable
should be index access:
android:text="@{thingy.getSpanAt(index)}"
SpannedString lacks the getter required to bind it, nor can one add annotations to framework classes.
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows aloadImage()
function as a@BindingAdapter
. Thanks, though!
– CommonsWare
Nov 10 '18 at 14:14
@CommonsWare that example usesapp:
namespace (the default demands@Bindable
getters and setters, which notify). the@BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.
– Martin Zeitler
Nov 10 '18 at 15:07
"that example uses app: namespace" -- that is my use case as well. For example,thingy
is not a standard Android attribute. Your point about@BindingConversion
is interesting -- I might be able to set one up that maps a string resourceInt
to aSpannedString
and address the problem that way. Thanks!
– CommonsWare
Nov 10 '18 at 15:20
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some classBindableSpannedString extends SpannedString
in order add@Bindable
getters should make the data-binding work - and nested values accessible.
– Martin Zeitler
Nov 12 '18 at 11:57
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as aSpannable
,SpannedString
, whatever) for processing in the binding adapter.
– CommonsWare
Nov 12 '18 at 12:33
|
show 2 more comments
one can define just any data-type with <import>
:
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
and then obtain the text from it:
android:text="@{sparse[index]}"
to define a thingy
with data-type SpannedString
(or one that extends SpannedString
):
<data>
<import type="com.acme.model.BindableSpannedString"/>
<variable name="thingy" type="BindableSpannedString"/>
<variable name="index" type="int"/>
</data>
the getter annotated with @Bindable
should be index access:
android:text="@{thingy.getSpanAt(index)}"
SpannedString lacks the getter required to bind it, nor can one add annotations to framework classes.
one can define just any data-type with <import>
:
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
and then obtain the text from it:
android:text="@{sparse[index]}"
to define a thingy
with data-type SpannedString
(or one that extends SpannedString
):
<data>
<import type="com.acme.model.BindableSpannedString"/>
<variable name="thingy" type="BindableSpannedString"/>
<variable name="index" type="int"/>
</data>
the getter annotated with @Bindable
should be index access:
android:text="@{thingy.getSpanAt(index)}"
SpannedString lacks the getter required to bind it, nor can one add annotations to framework classes.
edited Nov 12 '18 at 12:12
answered Nov 10 '18 at 13:54
Martin Zeitler
14.3k33863
14.3k33863
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows aloadImage()
function as a@BindingAdapter
. Thanks, though!
– CommonsWare
Nov 10 '18 at 14:14
@CommonsWare that example usesapp:
namespace (the default demands@Bindable
getters and setters, which notify). the@BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.
– Martin Zeitler
Nov 10 '18 at 15:07
"that example uses app: namespace" -- that is my use case as well. For example,thingy
is not a standard Android attribute. Your point about@BindingConversion
is interesting -- I might be able to set one up that maps a string resourceInt
to aSpannedString
and address the problem that way. Thanks!
– CommonsWare
Nov 10 '18 at 15:20
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some classBindableSpannedString extends SpannedString
in order add@Bindable
getters should make the data-binding work - and nested values accessible.
– Martin Zeitler
Nov 12 '18 at 11:57
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as aSpannable
,SpannedString
, whatever) for processing in the binding adapter.
– CommonsWare
Nov 12 '18 at 12:33
|
show 2 more comments
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows aloadImage()
function as a@BindingAdapter
. Thanks, though!
– CommonsWare
Nov 10 '18 at 14:14
@CommonsWare that example usesapp:
namespace (the default demands@Bindable
getters and setters, which notify). the@BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.
– Martin Zeitler
Nov 10 '18 at 15:07
"that example uses app: namespace" -- that is my use case as well. For example,thingy
is not a standard Android attribute. Your point about@BindingConversion
is interesting -- I might be able to set one up that maps a string resourceInt
to aSpannedString
and address the problem that way. Thanks!
– CommonsWare
Nov 10 '18 at 15:20
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some classBindableSpannedString extends SpannedString
in order add@Bindable
getters should make the data-binding work - and nested values accessible.
– Martin Zeitler
Nov 12 '18 at 11:57
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as aSpannable
,SpannedString
, whatever) for processing in the binding adapter.
– CommonsWare
Nov 12 '18 at 12:33
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows a
loadImage()
function as a @BindingAdapter
. Thanks, though!– CommonsWare
Nov 10 '18 at 14:14
"the name of the method matters" -- no, it does not. For example, in the documentation that you linked to, it shows a
loadImage()
function as a @BindingAdapter
. Thanks, though!– CommonsWare
Nov 10 '18 at 14:14
@CommonsWare that example uses
app:
namespace (the default demands @Bindable
getters and setters, which notify). the @BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.– Martin Zeitler
Nov 10 '18 at 15:07
@CommonsWare that example uses
app:
namespace (the default demands @Bindable
getters and setters, which notify). the @BindingConversion
annotation might probably be suitable for the use case, hence there is some kind of conversion required.– Martin Zeitler
Nov 10 '18 at 15:07
"that example uses app: namespace" -- that is my use case as well. For example,
thingy
is not a standard Android attribute. Your point about @BindingConversion
is interesting -- I might be able to set one up that maps a string resource Int
to a SpannedString
and address the problem that way. Thanks!– CommonsWare
Nov 10 '18 at 15:20
"that example uses app: namespace" -- that is my use case as well. For example,
thingy
is not a standard Android attribute. Your point about @BindingConversion
is interesting -- I might be able to set one up that maps a string resource Int
to a SpannedString
and address the problem that way. Thanks!– CommonsWare
Nov 10 '18 at 15:20
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some class
BindableSpannedString extends SpannedString
in order add @Bindable
getters should make the data-binding work - and nested values accessible.– Martin Zeitler
Nov 12 '18 at 11:57
@CommonsWare extended on my answer, because generally it's a custom data-type. developer.android.com/reference/android/text/SpannedString does not really have any getter for a span at an index. adding some class
BindableSpannedString extends SpannedString
in order add @Bindable
getters should make the data-binding work - and nested values accessible.– Martin Zeitler
Nov 12 '18 at 11:57
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as a
Spannable
, SpannedString
, whatever) for processing in the binding adapter.– CommonsWare
Nov 12 '18 at 12:33
Thanks, but I am not looking for nested values. I am looking for a binding adapter to be handed the spanned value (as a
Spannable
, SpannedString
, whatever) for processing in the binding adapter.– CommonsWare
Nov 12 '18 at 12:33
|
show 2 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53106939%2fhow-do-we-get-spannedstring-objects-from-string-resources-using-data-binding%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What is the
attr
type forthingy
?– Ben P.
Nov 1 '18 at 18:15
@BenP.: There is no
attr
forthingy
. When the data binding compiler encounters a data binding expression, it looks for binding adapters based on the attribute name.– CommonsWare
Nov 1 '18 at 18:18
Hm, ok. I'm not too familiar with data binding... so how does the system "know" the type to expect? Do you have a
String getThingy()
method?– Ben P.
Nov 1 '18 at 18:22
Well, I thought it used reflection to examine the method/function signature of the binding adapter implementation. It seems to do that in other places. In the above code snippets, the first parameter is the type of the widget you are using the binding expression on (
TextView
) and the second parameter is the type of the attribute value from the binding expression (Int
,String
, etc.). Perhaps it is just not that flexible when it comes to string resources. That's kinda the point of this question.– CommonsWare
Nov 1 '18 at 18:25
2
i'm afraid the only thing you could do is to pass a
"my_annotated_string"
string to yourhandleThingy
adapter and use infamousResources#getIdentifier()
method– pskink
Nov 1 '18 at 18:35