Search code examples
javaandroiddata-bindingandroid-6.0-marshmallowandroid-databinding

One-line font applying using Android-M data-binding doesn't work


I'm trying to apply some custom font to my TextView with one line as described in a post by Lisa Wray. The TextView is part of an item that goes into a RecyclerView

I've added data binding dependency to my top level build file.

classpath 'com.android.tools.build:gradle:1.3.0'
classpath "com.android.databinding:dataBinder:1.0-rc1"

I have also applied the plugin to my main module:

apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'

Here is the item.xml file that will be added to the RecyclerView.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/tools">

    <data></data>

    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:layout_width="100dp"
        android:layout_height="130dp"
        android:layout_gravity="center"
        card_view:cardCornerRadius="2dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="100dp"/>

            <TextView
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:font="@{@string/font_yekan}"/>

        </LinearLayout>
    </android.support.v7.widget.CardView>
</layout>

I've added a layout root element and app:font="@{@string/font_yekan}" combined with a static setter method:

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName) {
    textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

should do the trick. But when I run the program, the font isn't changed. However, when I remove the above static method, I get the following error:

Cannot find the setter for attribute 'app:font' with parameter type java.lang.String.

So data binding framework has recognized the binding stuff, but the setter method doesn't get called (Logs don't print output).

What is the problem here?


Solution

  • Provided the above layout and setup, assuming following:

    Inside your RecyclerView adapter you have bound the view by one of these ways:

    1. In onCreateViewHolder method of your adapter class

      @Override
      public MyAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.recycler_item,
                  parent, false);
          return new MyHolder(binding.getRoot());
      }
      
    2. Or in its onBindViewHolder method

          @Override
          public void onBindViewHolder(MyAdapter.MyHolder holder, int position) {
              DataBindingUtil.bind(holder.itemView);
              //...
          }
      

    Following resource setup

    Your assets folder should look similar to this:

    assets folder

    Your string resource file should have full qualified name for font:

    <string name="kenyan">kenyan_rg.ttf</string>
    

    With this ensured, it should work (and it does for me)