Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use Calligraphy with TabLayout in Android Design Support Library for custom Font in xml?

How do I use calligraphy to apply a custom font to TabLayout from design support library please?

I have gotten it to work in java which most of the answers seem to refer to. (e.g. Change the font of tab text in android design support TabLayout )

I'd prefer not to make a custom class, I'd like to just use Calligraphy. (https://github.com/chrisjenx/Calligraphy )

  • If I use a custom style for tabTextAppearance I can change textSize but fontPath doesn't have any effect.

Thanks

like image 650
nAndroid Avatar asked Jan 15 '16 22:01

nAndroid


2 Answers

I used the approach of extend the TabLayout. In this way you can simply define the fontPath in the TabLayout;

<com.mypackage.base.widget.FontAwareTabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        fontPath="@string/common_fonts_sans_condensed_bold"
/>

Here the class code:

 /**
 * Simple helper class which extends a TabLayout to allow us to customize the font of the tab.
 * https://gist.github.com/tmtrademarked/09926077a406959be15fc8a824a52751
 * https://github.com/chrisjenx/Calligraphy/issues/180
 */
public final class FontAwareTabLayout extends TabLayout {

  private String fontPath;

  public FontAwareTabLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    fontPath = pullFontPathFromView(context, attrs, new int[] { R.attr.fontPath });
  }

  /**
   * Tries to pull the Custom Attribute directly from the TextView.
   *
   * @param context Activity Context
   * @param attrs View Attributes
   * @param attributeId if -1 returns null.
   * @return null if attribute is not defined or added to View
   */
  static String pullFontPathFromView(Context context, AttributeSet attrs, int[] attributeId) {
    if (attributeId == null || attrs == null) return null;

    final String attributeName;
    try {
      attributeName = context.getResources().getResourceEntryName(attributeId[0]);
    } catch (Resources.NotFoundException e) {
      // invalid attribute ID
      return null;
    }

    final int stringResourceId = attrs.getAttributeResourceValue(null, attributeName, -1);
    return stringResourceId > 0 ? context.getString(stringResourceId)
        : attrs.getAttributeValue(null, attributeName);
  }

  @Override
  public void addTab(@NonNull Tab tab, int position, boolean setSelected) {
    super.addTab(tab, position, setSelected);

    ViewGroup mainView = (ViewGroup) getChildAt(0);
    ViewGroup tabView = (ViewGroup) mainView.getChildAt(tab.getPosition());
    int tabChildCount = tabView.getChildCount();
    for (int i = 0; i < tabChildCount; i++) {
      View tabViewChild = tabView.getChildAt(i);
      if (tabViewChild instanceof TextView) {
        CalligraphyUtils.applyFontToTextView(getContext(), (TextView) tabViewChild, fontPath);
      }
    }
  }
}
like image 183
Luigi Papino Avatar answered Oct 20 '22 23:10

Luigi Papino


There is a way to use custom font in xml for TabLayout, but it's a little bit hacky. You have to provide your own custom layout for Tabs and in that layout you can style your TextViews whatever you like.

So basically you need to have this setup:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Get the ViewPager and set it's PagerAdapter so that it can display items
    ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
    SampleFragmentPagerAdapter pagerAdapter = 
        new SampleFragmentPagerAdapter(getSupportFragmentManager(), MainActivity.this);
    viewPager.setAdapter(pagerAdapter);

    // Give the TabLayout the ViewPager
    TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
    tabLayout.setupWithViewPager(viewPager);

    // Iterate over all tabs and set the custom view
    for (int i = 0; i < tabLayout.getTabCount(); i++) {
        TabLayout.Tab tab = tabLayout.getTabAt(i);
        tab.setCustomView(pagerAdapter.getTabView(i));
    }
}

//...
}

And then the PagerAdapter:

public class SampleFragmentPagerAdapter extends FragmentPagerAdapter {

    private Context context;
    private String tabTitles[] = new String[] { "Tab1", "Tab2" };

    // ...

    public View getTabView(int position) {
        // Given you have a custom layout in `res/layout/custom_tab.xml` with a TextView
        View v = LayoutInflater.from(context).inflate(R.layout.custom_tab, null);
        TextView tv = (TextView) v.findViewById(R.id.textView);
        tv.setText(tabTitles[position]);
        return v;
    }
}

This is custom_tab.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    fontPath="fonts/CustomFont.otf"
    tools:ignore="MissingPrefix" />

Some things are missing in the code, but I think you can fill in the missing parts, this is just a gist of it. This is just a segment of the blog post in the references with the added addition of Calligraphy. You can take a look at it for more details.

References:

  • https://guides.codepath.com/android/Google-Play-Style-Tabs-using-TabLayout
like image 30
JKMirko Avatar answered Oct 21 '22 00:10

JKMirko