如何在TextView上更改字体?


Answers:


342

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

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

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

编辑

Android设计语言依赖于传统的排版工具,例如比例,空间,节奏以及与基础网格的对齐。成功部署这些工具对于帮助用户快速了解信息屏幕至关重要。为了支持这种排版,Ice Cream Sandwich引入了一个名为Roboto的新型系列,专门针对UI和高分辨率屏幕的需求而创建。

当前的TextView框架为Roboto提供了轻巧,常规,粗体的重量,以及每种重量的斜体样式。该框架还提供了常规重量和粗体重量的Roboto Condensed变体,以及每个重量的斜体样式。

ICS后,Android包括Roboto字型风格,了解更多的Roboto

编辑2

随着Support Library 26的到来,Android现在默认支持自定义字体。您可以在res / fonts中插入新字体,这些res / fonts可以分别以XML或以编程方式设置为TextViews。整个应用程序的默认字体也可以通过定义改变了它styles.xml Android开发者文档有一个清晰的指南这里


6
无法在XML中设置字体?为什么?
强尼

5
@Jonny您实际上可以。您正在创建一个扩展TextView并从构造函数调用setTypeface的类。
马克·菲利普

如何在XML布局中做到这一点?
M. Usman Khan 2014年

2
@usman:您将需要一个第三方库,例如Calligraphy:github.com/chrisjenx/Calligraphy
CommonsWare

由于使用多行代码,因此很难使用Java代码设置字体,我创建了一个库来设置自定义字体。您可以在此答案中找到库的用法stackoverflow.com/a/42001474/4446392
Chathura Jayanath,

254

首先下载所需.ttf字体的文件(arial.ttf)。将其放在 assets 文件夹中。(在Assets文件夹内,创建一个名为fonts的新文件夹,并将其放置在其中。)使用以下代码将该字体应用于您的TextView

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

亲爱的Mayur,关于在何处获取这些.ttf文件的任何建议?
lonelearner 2014年

3
亲爱的@lonelearner,您可以在1001freefonts.com中下载免费字体(.ttf)文件,可以在Google中下载“免费字体”
ymerdrengene 2014年

10
对于使用Android Studio且找不到“资产”文件夹的用户,请参见此问题。简短答案:src/main/assets/fonts/
adamdport 2014年

51
Typeface tf = Typeface.createFromAsset(getAssets(),
        "fonts/DroidSansFallback.ttf");
TextView tv = (TextView) findViewById(R.id.CustomFontText);
tv.setTypeface(tf);

33

您可能想要创建将包含所有字体的静态类。这样,您就不会多次创建字体,而这可能会对性能产生严重影响。只要确保您在“ 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;

}
}

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


1
好小子!这就是OOP的美。做得好!:)
约书亚·迈克尔·瓦格纳

我如何使用该课程?
2015年

您需要将此代码放置在您的项目中,使其适应字体,然后在应用程序的任何位置使用getTypeface(..)静态方法。
Daniel L.

我使用了类似的解决方案,但是添加了缓存以提高性能。
RJFares '16

20

有史以来的最佳实践

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>

希望这会帮助你。


1
为什么子类化TextView是最佳实践?
Stealth Rabbi

@Stealth Rabbi,这里我们只能通过xml传递自定义字体,无需为每个textview编写特殊的Java代码。
埃伦·帕特尔

有图书馆。只需将字体添加到资产文件夹下,并以XML声明即可。 github.com/febaisi/CustomTextView
febaisi

您的库看起来不错,但是唯一的问题是它适用于android 21+
loloof64

@febaisi,正如我在您的lib示例中看到的raw.githubusercontent.com/febaisi/CustomTextView/master/wiki/…–
Mr.Q

17

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


1
您的评论是多余的。上面的说明正好说明了您所说的内容,以及更多...
约书亚·迈克尔·瓦格纳

14

巩固字体创作的另一种方法...

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个投票?是什么使另一个更好呢?在我看来,这是使用单例原理更直接的方法……?
Koen Demonie

刚刚看到您的构造函数是公共的,我将其设为私有,因为您不需要任何访问权限。无论如何,您都在使用内部的Font var ...
Koen Demonie

绝对应该是私有构造函数。很好发现:)将编辑!
克里斯·艾奇森

12

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

步骤1:添加字体文件

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

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

步骤2:建立字型

  1. 字体文件夹中添加新的资源文件
  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>

有关更多示例,请遵循文档:

使用字体


7

它有点旧,但是我对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);

5

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

  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)文件放在该字体目录中,请记住命名约定[egname不应包含任何特殊字符,任何大写字符以及任何空格或制表符]
  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文件


4
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的View并在其构造函数上调用setTypeface。


1
您好,为什么要使用WeakReference来保存TypeFace对象?
懒惰的2015年

3

当您的字体存储在内部时,请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);

2
谢谢,正在寻找您在res文件夹中拥有的零件!
Mikkel Larsen

2

从资产获取字体并将其设置为所有子代

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) {
 }
 } 

2
  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中实例化此类吗?因为它对我没有任何改变。
Tobias Mayr

1

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

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

如何在XML布局中使用Roboto

回到您的问题,如果您想更改应用程序中所有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>

0

也许有些简单:

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");

(请注意,此代码未经测试,但总体而言,此方法应能很好地工作。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.