Android自定义字体教程
在本教程中,我们将说明如何在应用程序的TextViews和Buttons中设置android自定义字体。
Android自定义字体
Android SDK带有一组标准字体,可以使用一些XML属性来设置样式。
让我们看看它们。
- android:fontFamily:用于更改应用程序的默认字体。
我们可以从以下类型中选择字体。
默认的fontFamily是sans-serif
。
android:fontFamily要求的最低API级别为16。
android:typeface:如果已经使用了fontFamily,则此XML属性无效(除非API级别小于15,在这种情况下,fontFamily属性将被忽略)。
normal或者sans是此属性的默认类型。
以下是可接受的值。android:textStyle:此属性可以单独或者结合使用值:粗体,斜体和正常,例如android:textStyle =" bold | italic""。
让我们合并" android:fontFamily"和" android:textStyle",并显示TextView的不同变体。
下面给出了包含不同样式变体的styles.xml。
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="Regular"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="Italic"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="Bold"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="BoldItalic"> <item name="android:fontFamily">sans-serif</item> <item name="android:textStyle">bold|italic</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif</item> </style> <style name="RegularCondensed"> <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif-condensed</item> </style> <style name="ItalicCondensed"> <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif-condensed</item> </style> <style name="BoldCondensed"> <item name="android:fontFamily">sans-serif-condensed</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">sans-serif-condensed</item> </style> <style name="Casual"> <item name="android:fontFamily">casual</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">Casual</item> </style> <style name="Cursive"> <item name="android:fontFamily">cursive</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">Cursive</item> </style> <style name="RegularMono"> <item name="android:fontFamily">monospace</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">mono space</item> </style> <style name="ItalicMono"> <item name="android:fontFamily">monospace</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">monospace</item> </style> <style name="BoldMono"> <item name="android:fontFamily">monospace</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">monospace</item> </style> <style name="RegularMonoSerif"> <item name="android:fontFamily">serif-monospace</item> <item name="android:textStyle">normal</item> <item name="android:textSize">28sp</item> <item name="android:text">serif-monospace</item> </style> <style name="ItalicMonoSerif"> <item name="android:fontFamily">serif-monospace</item> <item name="android:textStyle">italic</item> <item name="android:textSize">28sp</item> <item name="android:text">serif-monospace</item> </style> <style name="BoldMonoSerif"> <item name="android:fontFamily">serif-monospace</item> <item name="android:textStyle">bold</item> <item name="android:textSize">28sp</item> <item name="android:text">serif-monospace</item> </style> </resources>
下面给出activity_main.xml。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.theitroad.customfonts.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Regular" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Italic" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Bold" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularCondensed" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/ItalicCondensed" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/BoldCondensed" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Casual" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/Cursive" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularMono" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/ItalicMono" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/BoldMono" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/RegularMonoSerif" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/ItalicMonoSerif" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/BoldMonoSerif" </LinearLayout>
若要在TextView/Button/EditText对象上设置自定义字体,请使用Typeface属性。
Typeface类指定字体的字体和固有样式。
要在TextView上设置字体,我们调用方法setTypeface()。
以下是可以使用的Typeface常量。
- BOLD
- BOLD_ITALIC
- ITALIC
- NORMAL
要在我们的视图上设置自定义字体,我们首先需要将字体文件导入到我们的项目中。
字体文件通常以.ttf(真字体)和.otf(开放字体)两种类型出现。
Android自定义字体代码
我们创建了另一个布局,即" activity_custom_fonts.xml",用于在视图上设置自定义字体。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.theitroad.customfonts.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Bold" android:textSize="28sp" android:id="@+id/ambleBold" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Light" android:textSize="28sp" android:id="@+id/ambleLight" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Regular" android:textSize="28sp" android:id="@+id/ambleRegular" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans Regular" android:textSize="28sp" android:id="@+id/opRegular" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans-Italic" android:id="@+id/opItalic" android:textSize="28sp" <Button android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Pacifico" android:id="@+id/pacifico" </LinearLayout>
我们正在Java代码中设置自定义字体。
MainActivity.java在下面给出
public class MainActivity extends AppCompatActivity { TextView ambleBold, ambleLight, ambleRegular, openSansItalic, openSansRegular; Button btn; private String A_BOLD= "Amble-Bold.ttf"; private String A_LIGHT="Amble-Light.ttf"; private String A_REGULAR= "Amble-Regular.ttf"; private String O_ITALIC= "OpenSans-Italic.ttf"; private String O_REGULAR="OpenSans-Regular.ttf"; private String P_REGULAR="Pacifico.ttf"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_fonts); ambleBold=(TextView)findViewById(R.id.ambleBold); ambleLight=(TextView)findViewById(R.id.ambleLight); ambleRegular=(TextView)findViewById(R.id.ambleRegular); openSansRegular=(TextView)findViewById(R.id.opRegular); openSansItalic=(TextView)findViewById(R.id.opItalic); btn=(Button)findViewById(R.id.pacifico); ambleBold.setTypeface(Typeface.createFromAsset(getAssets(), A_BOLD)); ambleLight.setTypeface(Typeface.createFromAsset(getAssets(), A_LIGHT)); ambleRegular.setTypeface(Typeface.createFromAsset(getAssets(), A_REGULAR)); openSansRegular.setTypeface(Typeface.createFromAsset(getAssets(), O_REGULAR)); openSansItalic.setTypeface(Typeface.createFromAsset(getAssets(), O_ITALIC)); btn.setTypeface(Typeface.createFromAsset(getAssets(), P_REGULAR)); } }
在上面的代码中,我们在Typeface类上调用createFromAsset()方法来创建Typeface的新实例。
通过将getAssets()作为第一个参数来调用应用程序AssetManager的实例。
自定义字体资产文件路径在第二个参数中作为字符串传递。
由于我们已将字体文件放置在资产目录的根目录中,因此只需传递字体文件名即可。
注意:使用android:typeface设置外部字体无效
当应用程序运行时,我们最终得到以下输出。
为每个视图分别设置字体是一项耗时且冗长的工作吗?我们需要更好的选择。
我们的答案在于自定义视图。
在下一节中,我们将创建一个Custom TextView类并定义自定义XML属性,以在XML布局本身中设置外部字体。
我们更新的项目结构如下
在实现CustomTextView.java之前,让我们看一下" TypeFactory.java"类,如下所示。
public class TypeFactory { private String A_BOLD= "Amble-Bold.ttf"; private String A_LIGHT="Amble-Light.ttf"; private String A_REGULAR= "Amble-Regular.ttf"; private String O_ITALIC= "OpenSans-Italic.ttf"; private String O_REGULAR="OpenSans-Regular.ttf"; Typeface ambleBold; Typeface ambleLight; Typeface ambleRegular; Typeface openSansItalic; Typeface openSansRegular; public TypeFactory(Context context){ ambleBold = Typeface.createFromAsset(context.getAssets(),A_BOLD); ambleLight = Typeface.createFromAsset(context.getAssets(),A_LIGHT); ambleRegular = Typeface.createFromAsset(context.getAssets(),A_REGULAR); openSansItalic = Typeface.createFromAsset(context.getAssets(),O_ITALIC); openSansRegular = Typeface.createFromAsset(context.getAssets(),O_REGULAR); } }
上面的代码实际上为每个字体文件创建了一个自定义字体。
现在,我们可以在CustomTextView中使用类变量来相应地设置字体。
下面给出了CustomTextView.java类。
public class CustomTextView extends TextView { private int typefaceType; private TypeFactory mFontFactory; public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); applyCustomFont(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); applyCustomFont(context, attrs); } public CustomTextView(Context context) { super(context); } private void applyCustomFont(Context context, AttributeSet attrs) { TypedArray array = context.getTheme().obtainStyledAttributes( attrs, R.styleable.CustomTextView, 0, 0); try { typefaceType = array.getInteger(R.styleable.CustomTextView_font_name, 0); } finally { array.recycle(); } if (!isInEditMode()) { setTypeface(getTypeFace(typefaceType)); } } public Typeface getTypeFace(int type) { if (mFontFactory == null) mFontFactory = new TypeFactory(getContext()); switch (type) { case Constants.A_BOLD: return mFontFactory.ambleBold; case Constants.A_LIGHT: return mFontFactory.ambleLight; case Constants.A_REGULAR: return mFontFactory.ambleRegular; case Constants.O_LIGHT: return mFontFactory.openSansItalic; case Constants.O_REGULAR: return mFontFactory.openSansRegular; default: return mFontFactory.ambleBold; } } public interface Constants { int A_BOLD = 1, A_LIGHT = 2, A_REGULAR = 3, O_LIGHT = 4, O_REGULAR=5; } }
如下所示,在attrs.xml文件中定义了" R.styleable.CustomTextView"。
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomTextView"> <attr name="font_name"> <enum value="1" name="ambleBold" <enum value="2" name="ambleLight" <enum value="3" name="ambleRegular" <enum value="4" name="openSansItalic" <enum value="5" name="openSansRegular" </attr> </declare-styleable> </resources>
属性font_name是我们将在XML布局中使用的自定义属性。
下面是更新后的activity_custom_fonts.xml
布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" xmlns:app="https://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.theitroad.customfonts.MainActivity"> <com.theitroad.customfonts.CustomTextView app:font_name="ambleBold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Bold" android:textSize="28sp" android:id="@+id/ambleBold" <com.theitroad.customfonts.CustomTextView app:font_name="ambleLight" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Light" android:textSize="28sp" android:id="@+id/ambleLight" <com.theitroad.customfonts.CustomTextView app:font_name="ambleRegular" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Amble Regular" android:textSize="28sp" android:id="@+id/ambleRegular" <com.theitroad.customfonts.CustomTextView app:font_name="openSansRegular" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans Regular" android:textSize="28sp" android:id="@+id/opRegular" <com.theitroad.customfonts.CustomTextView app:font_name="openSansItalic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="OpenSans-Italic" android:id="@+id/opItalic" android:textSize="28sp" <Button android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Pacifico" android:id="@+id/pacifico" </LinearLayout>
现在,MainActivity.java代码仅需要设置Button字体。
注意:可以通过类似方式创建CustomButton自定义视图。