Reputation: 980
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 )
Thanks
Upvotes: 5
Views: 3599
Reputation: 2299
If you used FragmentPagerAdapter, You can use Spannable in getPageTitle for example:
override fun getPageTitle(position: Int): CharSequence? {
val sBuilder = SpannableStringBuilder()
when(position){
0-> sBuilder.append("First Tab")
1-> sBuilder.append("Second Tab")
else-> sBuilder.append("Third Tab")
}
CalligraphyTypefaceSpan(TypefaceUtils.load(getAssets(), "fonts/Roboto-Bold.ttf"))
return sBuilder
}
Upvotes: 0
Reputation: 1297
Hi i think this is easy and best way to do it with calligraphy library. Calligraphy Github
fontName is font name in assets like "fonts/cocon_next_font.ttf".
public static void changeTabsFont(TabLayout tabLayout, String fontName) {
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildsCount = vgTab.getChildCount();
for (int i = 0; i < tabChildsCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
CalligraphyUtils.applyFontToTextView(tabLayout.getContext(), (TextView) tabViewChild, fontName);
}
}
}
}
Upvotes: 3
Reputation: 980
Updated:
See (for now) https://developer.android.com/preview/features/working-with-fonts.html Android O lets you bundle fonts as resources by adding the font file in the res/font/ folder. These fonts are compiled in your R file and are automatically available in Android Studio. You can access the font resources with the help of a new resource type, font. For example, to access a font resource, use @font/myfont, or R.font.myfont.
To add fonts as resources, perform the following steps in the Android Studio:
In the Resource type list, select font, and then click OK. Note: The name of the resource directory must be font.
Add your font files in the font folder. The folder structure below generates R.font.dancing_script, R.font.lobster, and R.font.typo_graphica. Adding the font files in the resource directory
Double-click a font file to preview the file's fonts in the editor.
Create Font family
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<font
android:fontStyle="normal"
android:fontWeight="400"
android:font="@font/lobster_regular" />
<font
android:fontStyle="italic"
android:fontWeight="400"
android:font="@font/lobster_italic" />
</font-family>
-- then textiview like so
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lobster"/>
Upvotes: 1
Reputation: 408
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);
}
}
}
}
Upvotes: 9
Reputation: 11
You can define style for android.support.design.widget.TabLayout and then write your own style for text appearance such like this:
<style name="TextAppearance.FontPath" parent="android:TextAppearance">
<item name="fontPath">fonts/Roboto-Light.ttf</item>
then you have to add item:
<item name="tabTextAppearance">@style/TextAppearance.FontPath</item>
to your style of android.support.design.widget.TabLayout. It should work.
Upvotes: 1
Reputation: 161
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:
Upvotes: 4