Android自定义字体教程

时间:2020-02-23 14:28:51  来源:igfitidea点击:

在本教程中,我们将说明如何在应用程序的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自定义视图。