【问题标题】:How to change the font on the TextView?如何更改 TextView 上的字体?
【发布时间】:2011-02-22 17:29:59
【问题描述】:

如何更改TextView 中的字体,默认显示为Arial?怎么改成Helvetica

【问题讨论】:

标签: android fonts textview


【解决方案1】:

首先,默认不是 Arial。默认为 Droid Sans。

其次,要更改为不同的内置字体,请在布局 XML 中使用 android:typeface 或在 Java 中使用 setTypeface()

第三,Android 中没有 Helvetica 字体。内置选项是 Droid Sans (sans)、Droid Sans Mono (monospace) 和 Droid Serif (serif)。虽然您可以将自己的字体与您的应用程序捆绑在一起并通过setTypeface() 使用它们,但请记住字体文件很大,在某些情况下需要许可协议(例如Helvetica, a Linotype font)。

编辑

Android 设计语言依赖于传统的排版工具 例如比例、空间、节奏和与底层网格的对齐。 成功部署这些工具对于帮助用户至关重要 快速了解一屏信息。支持这种使用 排版,冰淇淋三明治引入了一个新的字体家族,名为 Roboto,专为 UI 和 高分辨率屏幕。

当前的 TextView 框架提供了细、轻、规则的 Roboto 和粗体字,以及每个重量的斜体样式。这 框架还提供了常规和粗体的 Roboto Condensed 变体 权重,以及每个权重的斜体样式。

在 ICS 之后,android 包含 Roboto 字体样式, 阅读更多Roboto

编辑 2

随着 Support Library 26 的出现,Android 现在支持自定义字体 默认。您可以在 res/fonts 中插入新字体,这些字体可以在 XML 中或以编程方式单独设置为 TextViews。整个应用的默认字体也可以通过定义styles.xml来改变,android开发者文档对此有明确的指导here

【讨论】:

  • 无法在 XML 中设置字体?为什么?
  • @Jonny 实际上可以。您正在创建一个扩展 TextView 并从构造函数调用 setTypeface 的类。
  • 在XML Layout中怎么做?
  • @usman:你需要一个第三方库,比如 Calligraphy:github.com/chrisjenx/Calligraphy
  • 由于多行,使用 java 代码设置字体很难,我创建了一个库来设置自定义字体。您可以在此答案stackoverflow.com/a/42001474/4446392 中找到库的用法
【解决方案2】:

首先下载你需要的字体的.ttf文件(arial.ttf)。将其放在assets 文件夹中。 (在 assets 文件夹中创建名为 fonts 的新文件夹并将其放入其中。)使用以下代码将字体应用于您的 TextView

Typeface type = Typeface.createFromAsset(getAssets(),"fonts/arial.ttf"); 
textView.setTypeface(type);

【讨论】:

  • 亲爱的 Mayur,关于从哪里获取这些 .ttf 文件有什么建议吗?
  • 亲爱的@lonelearner,您可以在1001freefonts.com 中下载免费字体 (.ttf) 文件,或者只需谷歌“免费字体”
  • 对于那些使用 Android Studio 并且找不到“资产”文件夹的用户,请参阅 this question。简短回答:src/main/assets/fonts/.
【解决方案3】:
Typeface tf = Typeface.createFromAsset(getAssets(),
        "fonts/DroidSansFallback.ttf");
TextView tv = (TextView) findViewById(R.id.CustomFontText);
tv.setTypeface(tf);

【讨论】:

    【解决方案4】:

    您可能想要创建包含所有字体的静态类。这样,您就不会多次创建可能严重影响性能的字体。 只需确保在“assets”文件夹下创建一个名为“fonts”的子文件夹

    执行以下操作:

    public class CustomFontsLoader {
    
    public static final int FONT_NAME_1 =   0;
    public static final int FONT_NAME_2 =   1;
    public static final int FONT_NAME_3 =   2;
    
    private static final int NUM_OF_CUSTOM_FONTS = 3;
    
    private static boolean fontsLoaded = false;
    
    private static Typeface[] fonts = new Typeface[3];
    
    private static String[] fontPath = {
        "fonts/FONT_NAME_1.ttf",
        "fonts/FONT_NAME_2.ttf",
        "fonts/FONT_NAME_3.ttf"
    };
    
    
    /**
     * Returns a loaded custom font based on it's identifier. 
     * 
     * @param context - the current context
     * @param fontIdentifier = the identifier of the requested font
     * 
     * @return Typeface object of the requested font.
     */
    public static Typeface getTypeface(Context context, int fontIdentifier) {
        if (!fontsLoaded) {
            loadFonts(context);
        }
        return fonts[fontIdentifier];
    }
    
    
    private static void loadFonts(Context context) {
        for (int i = 0; i < NUM_OF_CUSTOM_FONTS; i++) {
            fonts[i] = Typeface.createFromAsset(context.getAssets(), fontPath[i]);
        }
        fontsLoaded = true;
    
    }
    }
    

    这样,您可以从应用程序中的任何位置获取字体。

    【讨论】:

    • 太棒了!这就是 OOP 的美妙之处。做得好! :)
    • 如何使用这个类?
    • 您需要将此代码放入您的项目中,使其适应您的字体,然后在您的应用程序的任何地方使用 getTypeface(..) 静态方法。
    • 我使用了类似的解决方案,但添加了缓存以提高性能......无论如何,您是否遇到过字体在某些手机上有效而在其他手机上无效的情况?
    【解决方案5】:

    最佳实践

    TextViewPlus.java:

    public class TextViewPlus extends TextView {
        private static final String TAG = "TextView";
    
        public TextViewPlus(Context context) {
            super(context);
        }
    
        public TextViewPlus(Context context, AttributeSet attrs) {
            super(context, attrs);
            setCustomFont(context, attrs);
        }
    
        public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            setCustomFont(context, attrs);
        }
    
        private void setCustomFont(Context ctx, AttributeSet attrs) {
            TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
            String customFont = a.getString(R.styleable.TextViewPlus_customFont);
            setCustomFont(ctx, customFont);
            a.recycle();
        }
    
        public boolean setCustomFont(Context ctx, String asset) {
            Typeface typeface = null;
            try {
                typeface = Typeface.createFromAsset(ctx.getAssets(), asset);
            } catch (Exception e) {
                Log.e(TAG, "Unable to load typeface: "+e.getMessage());
                return false;
            }
    
            setTypeface(typeface);
            return true;
        }
    }
    

    attrs.xml:(放置res/values的位置)

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="TextViewPlus">
            <attr name="customFont" format="string"/>
        </declare-styleable>
    </resources>
    

    使用方法:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:foo="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <com.mypackage.TextViewPlus
            android:id="@+id/textViewPlus1"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:text="@string/showingOffTheNewTypeface"
            foo:customFont="my_font_name_regular.otf">
        </com.mypackage.TextViewPlus>
    </LinearLayout>
    

    希望这会对你有所帮助。

    【讨论】:

    【解决方案6】:

    上面的答案是正确的。如果您正在使用那段代码,请确保在“assets”文件夹下创建一个名为“fonts”的子文件夹。

    【讨论】:

    • 您的评论是多余的。上面的解释正是你所说的,还有更多......
    【解决方案7】:

    另一种整合字体创建的方法...

    public class Font {
      public static final Font  PROXIMA_NOVA    = new Font("ProximaNovaRegular.otf");
      public static final Font  FRANKLIN_GOTHIC = new Font("FranklinGothicURWBoo.ttf");
      private final String      assetName;
      private volatile Typeface typeface;
    
      private Font(String assetName) {
        this.assetName = assetName;
      }
    
      public void apply(Context context, TextView textView) {
        if (typeface == null) {
          synchronized (this) {
            if (typeface == null) {
              typeface = Typeface.createFromAsset(context.getAssets(), assetName);
            }
          }
        }
        textView.setTypeface(typeface);
      }
    }
    

    然后在你的活动中使用......

    myTextView = (TextView) findViewById(R.id.myTextView);
    Font.PROXIMA_NOVA.apply(this, myTextView);
    

    请注意,这种带有 volatile 字段的双重检查锁定习惯用法仅适用于 Java 1.5+ 中使用的内存模型。

    【讨论】:

    • 为什么这个答案只有 1 个赞,而上面的有 15 个?是什么让另一个更好?在我看来,这个使用单例原则更直接......?
    • 刚刚看到您的构造函数是公开的,我会将其设为私有,因为您不需要任何访问权限。无论如何,您都在使用您的内部字体变量...
    • 绝对应该是私有构造函数。很好发现:) 将编辑!
    【解决方案8】:

    最佳做法是使用 Android 支持库 26.0.0 或更高版本。

    第一步:添加字体文件

    1. res 文件夹中创建新的 font 资源字典
    2. 添加字体文件(.ttf.orf

    例如,当字体文件为 helvetica_neue.ttf 时,将生成 R.font.helvetica_neue

    第 2 步:创建字体系列

    1. font 文件夹中添加新的资源文件
    2. 将每个字体文件、样式和粗细属性包含在元素中。

    例如:

    <?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/helvetica_neue" />
    </font-family>
    

    第 3 步:使用它

    在 xml 布局中:

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/my_font"/>
    

    或者在样式中添加字体:

    <style name="customfontstyle" parent="@android:style/TextAppearance.Small">
        <item name="android:fontFamily">@font/lobster</item>
    </style>
    

    有关更多示例,您可以关注文档:

    Working with fonts

    【讨论】:

      【解决方案9】:

      当您的字体存储在 res/asset/fonts/Helvetica.ttf 中时,请使用以下内容:

      Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/Helvetica.ttf"); 
      txt.setTypeface(tf);
      

      或者,如果您的字体文件存储在 res/font/helvetica.ttf 中,请使用以下内容:

      Typeface tf = ResourcesCompat.getFont(this,R.font.helvetica);
      txt.setTypeface(tf);
      

      【讨论】:

      • 谢谢,正在寻找你在 res 文件夹中的那部分!
      【解决方案10】:

      它有点旧,但我对 CustomFontLoader 类进行了一些改进,我想分享它,以便对它有所帮助。只需使用此代码创建一个新类。

       import android.content.Context;
       import android.graphics.Typeface;
      
      public enum FontLoader {
      
      ARIAL("arial"),
      TIMES("times"),
      VERDANA("verdana"),
      TREBUCHET("trbuchet"),
      GEORGIA("georgia"),
      GENEVA("geneva"),
      SANS("sans"),
      COURIER("courier"),
      TAHOMA("tahoma"),
      LUCIDA("lucida");   
      
      
      private final String name;
      private Typeface typeFace;
      
      
      private FontLoader(final String name) {
          this.name = name;
      
          typeFace=null;  
      }
      
      public static Typeface getTypeFace(Context context,String name){
          try {
              FontLoader item=FontLoader.valueOf(name.toUpperCase(Locale.getDefault()));
              if(item.typeFace==null){                
                  item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");                 
              }           
              return item.typeFace;
          } catch (Exception e) {         
              return null;
          }                   
      }
      public static Typeface getTypeFace(Context context,int id){
          FontLoader myArray[]= FontLoader.values();
          if(!(id<myArray.length)){           
              return null;
          } 
          try {
              if(myArray[id].typeFace==null){     
                  myArray[id].typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+myArray[id].name+".ttf");                       
              }       
              return myArray[id].typeFace;    
          }catch (Exception e) {          
              return null;
          }   
      
      }
      
      public static Typeface getTypeFaceByName(Context context,String name){      
          for(FontLoader item: FontLoader.values()){              
              if(name.equalsIgnoreCase(item.name)){
                  if(item.typeFace==null){
                      try{
                          item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");     
                      }catch (Exception e) {          
                          return null;
                      }   
                  }
                  return item.typeFace;
              }               
          }
          return null;
      }   
      
      public static void loadAllFonts(Context context){       
          for(FontLoader item: FontLoader.values()){              
              if(item.typeFace==null){
                  try{
                      item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");     
                  }catch (Exception e) {
                      item.typeFace=null;
                  }   
              }                
          }       
      }   
      }
      

      然后在你的 textview 上使用这个代码:

       Typeface typeFace=FontLoader.getTypeFace(context,"arial");  
       if(typeFace!=null) myTextView.setTypeface(typeFace);
      

      【讨论】:

        【解决方案11】:

        我终于找到了一个非常简单的解决方案。

        1. 应用级gradle中使用这些支持库,

          compile 'com.android.support:appcompat-v7:26.0.2'
          compile 'com.android.support:support-v4:26.0.2'
          
        2. 然后在 res 文件夹中创建一个名为 "font" 的目录

        3. 将 fonts(ttf) 文件放在该字体目录中,记住命名约定 [例如,名称不应包含任何特殊字符、任何大写字符以及任何空格或制表符]
        4. 之后,像这样从 xml 引用该字体

                  <Button
                  android:id="@+id/btn_choose_employee"
                  android:layout_width="140dp"
                  android:layout_height="40dp"
                  android:layout_centerInParent="true"
                  android:background="@drawable/rounded_red_btn"
                  android:onClick="btnEmployeeClickedAction"
                  android:text="@string/searching_jobs"
                  android:textAllCaps="false"
                  android:textColor="@color/white"
                  android:fontFamily="@font/times_new_roman_test"
                  />
          

        在此示例中,times_new_roman_test 是该字体目录中的字体 ttf 文件

        【讨论】:

          【解决方案12】:
          import java.lang.ref.WeakReference;
          import java.util.HashMap;
          
          import android.content.Context;
          import android.graphics.Typeface;
          
          public class FontsManager {
          
              private static FontsManager instance;
          
              private static HashMap<String, WeakReference<Typeface>> typefaces = new HashMap<String, WeakReference<Typeface>>();
          
              private static Context context;
          
              private FontsManager(final Context ctx) {
                  if (context == null) {
                      context = ctx;
                  }
              }
          
              public static FontsManager getInstance(final Context appContext) {
                  if (instance == null) {
                      instance = new FontsManager(appContext);
                  }
                  return instance;
              }
          
              public static FontsManager getInstance() {
                  if (instance == null) {
                      throw new RuntimeException(
                              "Call getInstance(Context context) at least once to init the singleton properly");
                  }
                  return instance;
              }
          
              public Typeface getFont(final String assetName) {
                  final WeakReference<Typeface> tfReference = typefaces.get(assetName);
                  if (tfReference == null || tfReference.get() == null) {
                      final Typeface tf = Typeface.createFromAsset(context.getResources().getAssets(),
                              assetName);
                      typefaces.put(assetName, new WeakReference<Typeface>(tf));
                      return tf;
                  }
                  return tfReference.get();
              }
          
          }
          

          这样,您可以创建一个继承自 TextView 并在其构造函数上调用 setTypeface 的 View。

          【讨论】:

          • 你好,为什么要使用 Wea​​kReference 来保存 TypeFace 对象?
          【解决方案13】:

          从资产中获取字体并设置为所有子项

          public static void overrideFonts(final Context context, final View v) {
              try {
                  if (v instanceof ViewGroup) {
                      ViewGroup vg = (ViewGroup) v;
                      for (int i = 0; i < vg.getChildCount(); i++) {
                          View child = vg.getChildAt(i);
                          overrideFonts(context, child);
                   }
                  } else if (v instanceof TextView ) {
                      ((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(),"DroidNaskh.ttf"));// "BKOODB.TTF"));
                  }
              } catch (Exception e) {
           }
           } 
          

          【讨论】:

            【解决方案14】:
            1. 添加类 FontTextView.java:


            public class FontTextView extends TextView {
                String fonts[] = {"HelveticaNeue.ttf", "HelveticaNeueLight.ttf", "motschcc.ttf", "symbol.ttf"};
            
                public FontTextView(Context context, AttributeSet attrs, int defStyle) {
                    super(context, attrs, defStyle);
                    init(attrs);
                }
            
                public FontTextView(Context context, AttributeSet attrs) {
                    super(context, attrs);
                    if (!isInEditMode()) {
                        init(attrs);
                    }
            
                }
            
                public FontTextView(Context context) {
                    super(context);
                    if (!isInEditMode()) {
                        init(null);
                    }
                }
            
                private void init(AttributeSet attrs) {
                    if (attrs != null) {
                        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FontTextView);
                        if (a.getString(R.styleable.FontTextView_font_type) != null) {
                            String fontName = fonts[Integer.valueOf(a.getString(R.styleable.FontTextView_font_type))];
            
                            if (fontName != null) {
                                Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/" + fontName);
                                setTypeface(myTypeface);
                            }
                            a.recycle();
                        }
                    }
                }
            }
            


            1. 添加到资产库字体


            1. 添加到 attrs.xml , 数字应按数组类中的顺序排列。

              <declare-styleable name="FontTextView">
              <attr name="font_type" format="enum">
                  <enum name="HelveticaNeue" value="0"/>
                  <enum name="HelveticaNeueLight" value="1"/>
                  <enum name="motschcc" value="2"/>
                  <enum name="symbol" value="3"/>
              </attr>
              


            1. 从列表中选择一种字体

            【讨论】:

            • 是否需要在MainActivity中实例化这个类?因为它对我没有任何改变。
            【解决方案15】:

            Android 使用 Roboto 字体,这是一种非常好看的字体,具有多种不同的粗细(常规、轻薄、紧凑),在高密度屏幕上看起来很棒。

            检查以下链接以检查roboto字体:

            How to use Roboto in xml layout

            回到您的问题,如果您想更改 应用中所有 TextView/Button 的字体,请尝试将以下代码添加到您的 styles.xml 以使用 Roboto-light 字体:

            <!-- Base application theme. -->
            <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
                <!-- Customize your theme here. -->
                ......
                <item name="android:buttonStyle">@style/MyButton</item>
                <item name="android:textViewStyle">@style/MyTextView</item>
            </style>
            
            <style name="MyButton" parent="@style/Widget.AppCompat.Button">
                <item name="android:textAllCaps">false</item>
                <item name="android:fontFamily">sans-serif-light</item>
            </style>
            
            <style name="MyTextView" parent="@style/TextAppearance.AppCompat">
                <item name="android:fontFamily">sans-serif-light</item>
            </style>
            

            别忘了在你的 AndroidManifest.xml 中使用“AppTheme”

            <application
                android:allowBackup="true"
                android:icon="@mipmap/ic_launcher"
                android:label="@string/app_name"
                android:roundIcon="@mipmap/ic_launcher_round"
                android:supportsRtl="true"
                android:theme="@style/AppTheme">
                ......
            </application>
            

            【讨论】:

              【解决方案16】:

              也许更简单一点:

              public class Fonts {
                public static HashSet<String,Typeface> fonts = new HashSet<>();
              
                public static Typeface get(Context context, String file) {
                  if (! fonts.contains(file)) {
                    synchronized (this) {
                      Typeface typeface = Typeface.createFromAsset(context.getAssets(), name);
                      fonts.put(name, typeface);
                    }
                  }
                  return fonts.get(file);
                }
              }
              
              // Usage
              Typeface myFont = Fonts.get("arial.ttf");
              

              (请注意,此代码未经测试,但通常这种方法应该可以正常工作。)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-03-28
                • 2011-09-15
                • 2020-09-03
                • 1970-01-01
                • 1970-01-01
                • 2014-01-11
                • 2013-05-07
                相关资源
                最近更新 更多