I am using from dataBinding in my project,when I have bellow xml it good work :
<TextView
android:id="#+id/txtDateCreate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{String.format(#string/DateCreate,others.created)}" />
But when I change to bellow get me crash:
<TextView
android:id="#+id/txtDateCreate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{Html.fromHtml(String.format(#string/DateCreate,others.created))}" />
Here in my string.xml :
<resources>
<string name="DateCreate">open : <![CDATA[<b><font color=#FF0000>%s</b>]]></string>
</resources>
Think you need to import html first in the xml
<data>
<import type="android.text.Html"/>
</data>
<TextView
android:id="#+id/txtDateCreate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{Html.fromHtml(String.format(#string/DateCreate,others.created))}" />
I think that the view should not have any logic/transformation to display the data. What I'd recommend to do is creating a BindingAdapter for this:
#BindingAdapter({"android:htmlText"})
public static void setHtmlTextValue(TextView textView, String htmlText) {
if (htmlText == null)
return;
Spanned result;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
result = Html.fromHtml(htmlText, Html.FROM_HTML_MODE_LEGACY);
} else {
result = Html.fromHtml(htmlText);
}
textView.setText(result);
}
Then within the layout call it as usual:
<TextView
android:id="#+id/bid_footer"
style="#style/MyApp.TextView.Footer"
android:htmlText="#{viewModel.bidFooter} />
Where viewModel.bidFooter has the logic to get the String/Spanned/Chars with the text, taking into consideration not having any direct dependence to context, activity, etc
The line below is deprecated in Android N (API level 24).
Html.fromHtml(content)
Now you're supposed to provide two params (content and flag) like below:
Html.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
So I'll suggest you use #BindingAdapter like below:
object BindingUtils {
#JvmStatic
#BindingAdapter("loadHtml")
fun loadHtml(textView: TextView, content: String?){
if (!content.isNullOrEmpty()) {
textView.text = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
Html.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
} else {
Html.fromHtml(content)
}
}
}
}
and in your XML file:
<data>
<import type="com.example.utils.BindingUtils"/>
</data>
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:loadHtml="#{String.format(#string/DateCreate,others.created))}"/>
Related
In data binding adatper, i want to check if int value in my model is not zero. Because hint is never shown, if value is 0 default then 0 is shown as text. I want to show hint if value is zero.
Below works well without checking 0 int value
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/port"
android:inputType="number"
android:text="#={`` + item.port}"
/>
I tried this which does not work
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/port"
android:inputType="number"
android:text='#={item.port != 0 ? `` + item.port : ""}'
/>
item.port is intvalue
Any suggestions to make this work with only data binding?
I think you'll need a BindingAdapter/InverseBindingAdapter or a conversion method. The easiest is probably a conversion method:
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<data>
<import type="com.example.mount.teststuff.Conversion"/>
<variable name="port" type="int"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="#+id/input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#={Conversion.intToString(port, port)}"
android:textSize="40sp"/>
<TextView
android:id="#+id/output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{`` + port}"
android:textSize="40sp"/>
</LinearLayout>
</layout>
And in your Conversion class you'd have something like this:
public class Conversion {
#InverseMethod("stringToInt")
public static String intToString(int oldValue, int value) {
if (value == 0) {
return null;
}
return String.valueOf(value);
}
public static int stringToInt(int oldValue, String value) {
if (value == null || value.isEmpty()) {
return 0;
}
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return oldValue;
}
}
}
I just updated the answer to include my tested layout and code. You can look for more detail on this blog post.
<import type="Integer"/>
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/port"
android:inputType="number"
android:text='#={item.port}'
/>
Dont keep port variable as int as two way binding required String type Setter for port value. Instead convert String value into Integer in XML itself.
Update : Instead of checking null for hint, please change port value from your viewmodel. if port is 0 then you can replace it with empty string "" and then call notifyPropertyChange(BR.port);
In one of my event handler on a button, I am using lambda expression but it evaluate wrong result at the time of event happens. My flow is to check whether a view (In my case it is TextView) is visible or not in the expression. If view is visible then I am printing true else false. But my code is always giving me true response. Blow is my code:
public class MainActivity extends AppCompatActivity implements MethodReferenceHandler, ____ListenerBindingEventHandler {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User kkr = new User();
kkr.setAge("20");
kkr.setName("Vinit Saxena");
activityMainBinding.setUser(kkr);
activityMainBinding.setEventHandler(this);
activityMainBinding.setMethodreferencehandler(this);
TextView textView = (TextView) findViewById(R.id.name_tv);
textView.setVisibility(View.GONE);
activityMainBinding.setView(textView);
}
#Override
public void onClickViaMethodReferenceHandler(View v) {
Log.i(getClass().getName(), "---->onClickViaMethodReferenceHandler");
}
#Override
public void eventHandlerViaListenerBinding() {
Log.i(getClass().getName(), "---->eventHandlerViaListenerBinding");
}
#Override
public void eventHandlerViaListenerBinding(boolean isThisTrue) {
Log.i(getClass().getName(), "---->eventHandlerViaListenerBinding - isThisTrue : " + isThisTrue);
}
}
<data>
<import type="android.view.View" />
<variable
name="user"
type="com.mds.binding.User" />
<variable
name="methodreferencehandler"
type="com.mds.binding.MethodReferenceHandler" />
<variable
name="eventHandler"
type="com.mds.binding.____ListenerBindingEventHandler" />
<variable
name="view"
type="android.view.View" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.mds.binding.MainActivity">
<TextView
android:id="#+id/name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.name}"
android:visibility="visible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.age}" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{methodreferencehandler::onClickViaMethodReferenceHandler}"
android:text="Method Reference" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{(view)-> view.getVisibility() == View.VISIBLE ? eventHandler.eventHandlerViaListenerBinding(true) : eventHandler.eventHandlerViaListenerBinding(false)}"
android:text="Listener Binding" />
</LinearLayout>
Please help where am I doing mistake?
Thanks in advance.
You're not using the binding to its full extend. One purpose is to never use findViewById() again. So the following
TextView textView = (TextView) findViewById(R.id.name_tv);
textView.setVisibility(View.GONE);
should be done as
activityMainBinding.nameTv.setVisibility(View.GONE);
since all views with an id are provieded as a member on the binding.
As a second advantage you can even access this variable within the binding itself. So you could just remove
<variable
name="view"
type="android.view.View" />
all completely and implement the onClick listener as
android:onClick="#{(view) -> eventHandler.eventHandlerViaListenerBinding(nameTv.getVisibility() == View.VISIBLE)}"
Additionally you don't really need the ?: conditional operator.
you can try:
this: android:onClick="#{()-> eventHandler.eventHandlerViaListenerBinding(view.getVisibility() == View.VISIBLE)}"
Because your lambda expression correspond to:
private View view;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {eventHandler.eventHandlerViaListenerBinding(view.getVisibility() == View.VISIBLE);
}
});
In this case, onClick method has 1 argument which is clicked button. And local "view" variable is used instead of global "view" variable. if you name this variable to the other variable name, it's ok.
So you can you your lambda to "#{()->" or "#{(v)->".
I was searching over the internet for how to perform the new cool android data-binding over the RadioGroup and I didn't find a single blog post about it.
Its a simple scenario, based on the radio button selected, I want to attach a callback event using android data binding. I don't find any method on the xml part which allows me to define a callback.
Like here is my RadioGroup:
<RadioGroup
android:id="#+id/split_type_radio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:checkedButton="#+id/split_type_equal"
android:gravity="center"
<!-- which tag ? -->
android:orientation="horizontal">
...
</RadioGroup>
How do I attach a handler method which will be called on RadioGroup's checkChnged event will fire using data-binding?
I have tried using onClick (don't know if it is the same) in layout file and defining method in the Activity and located it using this in the layout file:
<variable
name="handler"
type="com.example.MainActivity"/>
...
<RadioGroup
android:onClick="handler.onCustomCheckChanged"
.. >
And defined method onCustomCheckChanged like this:
public void onCustomCheckChanged(RadioGroup radio, int id) {
// ...
}
But, it gives me the compilation error:
Error:(58, 36) Listener class android.view.View.OnClickListener with method onClick did not match signature of any method handler.onCustomCheckChanged
I have seen many blogs mentioning it is possible with RadioGroup but non of them really say how. How can I handle this with data-binding ?
After digging to the bunch of methods, I found this question on SO which helped me understand how to bind single methods of listeners.
Here is what to do with RadioGroup:
In RadioGroup listener you have a method onCheckedChanged(RadioGroup g, int id). So you can directly bound that method to your handler or your activity by passing an instance of it as a variable in layout file and calling a method with the same signature.
So call on layout file like this:
<RadioGroup
android:id="#+id/split_type_radio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:checkedButton="#+id/split_type_equal"
android:gravity="center"
android:onCheckedChanged="#{handler.onSplitTypeChanged}"
android:orientation="horizontal">
...
</RadioGroup>
And in my activity or handler, I need to simply provide the method with same name and signature like this:
public void onSplitTypeChanged(RadioGroup radioGroup,int id) {
// ...
}
Just make sure method is public.
NOTE: This works for any (most of, I have not tried all) listener methods. Like for EditText you can provide android:onTextChanged and so on.
I am using a string, and in this case I have bindable based on viewModel.getCommuteType() viewModel.setCommuteType(String)
<RadioGroup
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton
android:checked="#{viewModel.commuteType.equals(Commute.DRIVING)}"
android:onClick="#{()->viewModel.setCommuteType(Commute.DRIVING)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="D"/>
<RadioButton
android:checked="#{viewModel.commuteType.equals(Commute.BICYCLE)}"
android:onClick="#{()->viewModel.setCommuteType(Commute.BICYCLE)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"/>
<RadioButton
android:checked="#{viewModel.commuteType.equals(Commute.WALKING)}"
android:onClick="#{()->viewModel.setCommuteType(Commute.WALKING)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="W"/>
<RadioButton
android:checked="#{viewModel.commuteType.equals(Commute.BUS)}"
android:onClick="#{()->viewModel.setCommuteType(Commute.BUS)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="T"/>
After some hours I found easy way: two-way databinding in android. It's base skeleton with livedata and Kotlin. Also you can use ObservableField()
Set your viewmodel to data
Create your radiogroup with buttons as you like. Important: set all radio buttons id !!!
Set in your radio group two-way binding to checked variable (use viewmodel variable)
Enjoy)
layout.xml
<data>
<variable
name="VM"
type="...YourViewModel" />
</data>
<LinearLayout
android:id="#+id/settings_block_env"
...
>
<RadioGroup
android:id="#+id/env_radioGroup"
android:checkedButton="#={VM.radio_checked}">
<RadioButton
android:id="#+id/your_id1"/>
<RadioButton
android:id="#+id/your_id2" />
<RadioButton
android:id="#+id/your_id3"/>
<RadioButton
android:id="#+id/your_id4"/>
</RadioGroup>
</LinearLayout>
class YourViewModel(): ViewModel {
var radio_checked = MutableLiveData<Int>()
init{
radio_checked.postValue(R.id.your_id1)//def value
}
//other code
}
Often you care more about what was actually checked instead of "something was checked". In such case alternative solution is to ignore RadioGroup and bind all items as below:
<RadioGroup (...) >
<RadioButton (...)
android:checked="#={viewModel.optionA}"/>
<RadioButton (...)
android:checked="#={viewModel.optionB}"/>
<RadioButton (...)
android:checked="#={viewModel.optionC}"/>
</RadioGroup>
where optionA, optionB and optionC are defined in ViewModel like below:
public final ObservableBoolean optionA = new ObservableBoolean();
public final ObservableBoolean optionB = new ObservableBoolean();
public final ObservableBoolean optionC = new ObservableBoolean();
This is usually enough, however if you want to react immediately on click then you can add callBacks and use them like that:
OnPropertyChangedCallback userChoosedA = new OnPropertyChangedCallback() {
#Override
public void onPropertyChanged(Observable sender, int propertyId) {
(...) // basically propertyId can be ignored in such case
}
};
optionA.addOnPropertyChangedCallback(userChoosedA);
Advantage of such approach is that you don't need to compare and track "id".
In my current project, I did it like this.
I have three currency in the project and I choose one of them via RadioGroup.
It's enum with currencies:
enum class Currency(val value: Byte) {
USD(0),
EUR(1),
RUB(2);
companion object Create {
fun from(sourceValue: Byte): Currency = values().first { it.value == sourceValue }
fun from(sourceValue: String): Currency = values().first { it.toString() == sourceValue }
}
}
A piece of my ViewModel:
class BaseCurrencyViewModel : ViewModelBase<BaseCurrencyModelInterface>() {
/**
* Selected currency
*/
val currency: MutableLiveData<Currency> = MutableLiveData()
/**
*
*/
init {
currency.value = Currency.USD // Init value
}
}
Part of my layout (pay attention to binding in RadioGroup and tags of RadioButton):
<RadioGroup
android:id="#+id/currencySwitchers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:selectedCurrency = "#{viewModel.currency}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintEnd_toEndOf="parent">
<RadioButton
android:id="#+id/usdSwitcher"
android:text="USD"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:tag="USD"
/>
<RadioButton
android:id="#+id/eurSwitcher"
android:text="EUR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:tag="EUR"
/>
<RadioButton
android:id="#+id/rubSwitcher"
android:text="RUB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:tag="RUB"
/>
</RadioGroup>
And the final part - binding adapter.
#BindingAdapter("selectedCurrency")
fun setSelectedCurrency(view: View, value: MutableLiveData<Currency>?) {
view.getParentActivity()?.let { parentActivity ->
value?.observe(parentActivity, Observer { value ->
view.findViewWithTag<RadioButton>(value.toString())
?.also {
if(!it.isChecked) {
it.isChecked = true
}
}
}
)
(view as RadioGroup).setOnCheckedChangeListener { radioGroup, checkedId ->
val currency = Currency.from(radioGroup.findViewById<RadioButton>(checkedId).tag as String)
if(value != null && value.value != currency) {
value.value = currency
}
}
}
}
In this way, I got two-way binding between RadioGroup and a property in my ViewModel.
I want to set the text of my TextView conditionally to either one or the other.
Android Data Binding documentation suggests that you can set the text conditionally if the text is a property of the view model. e.g.
android:text="#{user.displayName != null ? user.displayName : user.lastName}"
But is there any way to set the text from the strings.xml rather than adding it in my view model? I want something like this-
android:text="#{viewModel.expanded ? #string/collapse : #string/expand}"
The XML looks somewhat like this:
<?xml version="1.0" encoding="UTF-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:bind="http://schemas.android.com/apk/res-auto">
<data class="TravellerInfoBinding">
<import type="android.view.View" />
<variable name="viewModel" type="com.myproject.viewmodel.TravellerInfoViewModel" />
</data>
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="#drawable/expandable_arrow_blue" />
<TextView style="#style/primary_pair_element_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{viewModel.expanded ? #string/taxes_fees_detail : #string/hide_taxes_fees_detail}"
android:textSize="12sp" />
</LinearLayout>
</layout>
And this is my View Model-
package com.myproject.viewmodel;
imports...
public class TravellerInfoViewModel extends BaseObservable {
#Bindable
private final TaxDetailsViewModel taxDetailsViewModel;
#Bindable
private boolean expanded;
Constructor....
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
notifyPropertyChanged(BR.expanded);
}
public void toggleExpanded() {
setExpanded(!expanded);
}
}
Actually, this works fine for me
<TextView
android:id="#+id/btnEdit"
style="#style/Common.Toolbar.Action.Text"
android:onClickListener="#{onEditClick}"
android:text="#{vm.editMode ? #string/contacts_done : #string/contacts_edit}"
tools:text="#string/contacts_edit"/>
Where vm - it's a ViewModel and editMode - it's ObservableBoolean
Here's a fix/work-around :
define a duplicate Xml definition of the layout where you want a conditional value
for each block, set one of the condition values
set the visibility of each Xml definition according to the data binding boolean value
Not the ideal solution, not very pretty .. but functionally equivalent - and works in the interim until proper solution is found.
Here's how I solved it for android:textStyle, where I had a special case requirement for showing values in bold.
<variable
name="viewModel"
type="com.demo.app.SomeViewModel"/>
...
<TextView
style="#style/RowValue"
android:visibility="#{ ! viewModel.boldRow ? View.VISIBLE : View.GONE}"
android:text="#{viewModel.currentValue}"
/>
<TextView
style="#style/RowValue"
android:visibility="#{ viewModel.boldRow ? View.VISIBLE : View.GONE}"
android:text="#{viewModel.currentValue}"
android:textStyle="bold"
/>
Pretty basic, I want to make a title of a message bold based on whether the text it is read or not. I can't seem to find a solution for this.
Here is my XML code:
<TextView
android:text="#{message.title}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="#+id/timestamp"
android:textSize="18sp"
android:textStyle='#{message.isRead() ? "bold" : "normal"}'
android:textColor='#{message.isRead() ? 0xff313131 : 0xff0662ab}' />
Th colorchange is working great, only the bold text is giving me some problems.
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Cannot find the setter for attribute 'android:textStyle' with parameter type java.lang.String on android.widget.TextView.
file:D:......xml
loc:39:41 - 39:79
****\ data binding error ****
An easy way
public class TextViewBindingAdapter {
#BindingAdapter("isBold")
public static void setBold(TextView view, boolean isBold) {
if (isBold) {
view.setTypeface(null, Typeface.BOLD);
} else {
view.setTypeface(null, Typeface.NORMAL);
}
}
}
XML:
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:isBold="#{item.bold}"/>
I ended up using the following code, it implements DataBinding.
public abstract class BindingAdapter {
#android.databinding.BindingAdapter("android:typeface")
public static void setTypeface(TextView v, String style) {
switch (style) {
case "bold":
v.setTypeface(null, Typeface.BOLD);
break;
default:
v.setTypeface(null, Typeface.NORMAL);
break;
}
}
}
And the XML
<TextView
android:text="#{bericht.titel}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="#+id/timestamp"
android:textSize="18sp"
android:textColor='#{bericht.isGelezen() ? 0xff313131 : 0xff0662ab}'
android:typeface='#{bericht.isGelezen() ? "normal" : "bold"}' />
You can do this without creating an adapter.
Import Typeface to your XML
<data>
<import type="android.graphics.Typeface" />
...
</data>
Use the attribute android:typeface with Typeface.defaultFromStyle:
android:typeface="#{Typeface.defaultFromStyle(message.isRead() ? Typeface.BOLD : Typeface.NORMAL)}"
Saif Bechan is correct in his answer, I made a slight change to facilitate databinding from a view model.
public abstract class BindingAdapter {
#android.databinding.BindingAdapter("app:textStyle")
public static void setTextStyle(TextView v, int style) {
v.setTypeface(null, style);
}
}
Then you bring in the app namespace to your XML
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
...
</layout>
Create a binding in the view model
#Bindable
public int getValueFormat() {
String message = getMyObject().getValue();
if (message == MyObject.DEFAULT_VALUE)
return Typeface.ITALIC;
return Typeface.NORMAL;
}
Now you can bind this directly
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:textStyle="#{viewModel.valueFormat}"
android:text="#{viewModel.value}" />
you just has to import Typeface to the xml file and make your check like this
<variable
name="vm"
type="com.example.VM" />
<import type="android.graphics.Typeface" />
<TextView
android:id="#+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="#{vm.isBold ? Typeface.BOLD : Typeface.NORMAL}"/>
So, I had the same problem this week, I was trying to use the view.setTypeface() method, but I wanted to keep the font style in my case. It turns out that the bold style worked when I passed null in the setTypeFace method, but...passing null can make changes in the font style (was not looking at the same). When I tried to use the same font style and set the view to bold it was not working.
To achieve what I wanted, since I was not succeeding in using this method I just change the font style when the bold is required, see my code:
#BindingAdapter("boldOrRegular")
#JvmStatic
fun TextView.boldOrRegular(isBold: Boolean) {
typeface = if (isBold) {
ResourcesCompat.getFont(context, R.font.myfont_bold)
} else {
ResourcesCompat.getFont(context, R.font.myfont_regular)
}
}
I hope that this can help someone :)
You need to create getMessageStyle into your message Object :
public String getMessageStyle() {
return isRead() ? "bold" : "normal";
}
then use as below into your code :
<TextView
android:text="#{message.title}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="#+id/timestamp"
android:textSize="18sp"
android:textStyle="#{message.getMessageStyle()}"
android:textColor="#{message.isRead() ? 0xff313131 : 0xff0662ab}" />