自定义字体和XML布局(Android)

我想在Android中使用XML文件来定义一个GUI布局。 据我所知,没有办法指定你的小部件应该在XML文件中使用一个自定义的字体(例如你放置在assets / font /中的字体),你只能使用系统安装的字体。

我知道,在Java代码中,我可以使用唯一ID手动更改每个小部件的字体。 另外,我可以迭代Java中的所有小部件来做这个改变,但是这可能会很慢。

我还有什么其他的选择? 有没有更好的方法来制作自定义外观的小部件? 我不特别想要手动更改我添加的每个新小部件的字体。

你可以扩展TextView来设置自定义字体,就像我在这里学到的一样。

TextViewPlus.java:

package com.example; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Typeface; import android.util.AttributeSet; import android.util.Log; import android.widget.TextView; 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 tf = null; try { tf = Typeface.createFromAsset(ctx.getAssets(), asset); } catch (Exception e) { Log.e(TAG, "Could not get typeface: "+e.getMessage()); return false; } setTypeface(tf); 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> 

main.xml中:

 <?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/com.example" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.example.TextViewPlus android:id="@+id/textViewPlus1" android:layout_height="match_parent" android:layout_width="match_parent" android:text="@string/showingOffTheNewTypeface" foo:customFont="saxmono.ttf"> </com.example.TextViewPlus> </LinearLayout> 

你会把“saxmono.ttf”放在assets文件夹中。

更新8/1/13

这种方法存在严重的记忆问题。 见下面的chedabob的评论 。

我晚了3年(但是,这可能会有用的人可能会偶然发现这个职位。

我已经编写了一个缓存字体的库,并允许您从XML中指定自定义字体。 你可以在这里找到图书馆。

这是您的XML布局在使用时的样子。

 <com.mobsandgeeks.ui.TypefaceTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" geekui:customTypeface="fonts/custom_font.ttf" /> 

这可能有点晚,但是你需要创建一个返回自定义字体的单例类,以避免内存泄漏。

TypeFace类:

 public class OpenSans { private static OpenSans instance; private static Typeface typeface; public static OpenSans getInstance(Context context) { synchronized (OpenSans.class) { if (instance == null) { instance = new OpenSans(); typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf"); } return instance; } } public Typeface getTypeFace() { return typeface; } } 

自定义TextView:

 public class NativelyCustomTextView extends TextView { public NativelyCustomTextView(Context context) { super(context); setTypeface(OpenSans.getInstance(context).getTypeFace()); } public NativelyCustomTextView(Context context, AttributeSet attrs) { super(context, attrs); setTypeface(OpenSans.getInstance(context).getTypeFace()); } public NativelyCustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setTypeface(OpenSans.getInstance(context).getTypeFace()); } } 

通过xml:

 <com.yourpackage.views.NativelyCustomTextView android:id="@+id/natively_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_margin="20dp" android:text="@string/natively" android:textSize="30sp" /> 

编程方式:

 TextView programmaticallyTextView = (TextView) findViewById(R.id.programmatically_text_view); programmaticallyTextView.setTypeface(OpenSans.getInstance(this) .getTypeFace()); 

老问题,但我确实希望在我开始自己的搜索一个好的解决方案之前,我阅读这个答案。 书法扩展了android:fontFamily属性,以便在资产文件夹中添加对自定义字体的支持,如下所示:

 <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="fonts/Roboto-Bold.ttf"/> 

你必须做的唯一的事情就是把它附加到你正在使用的Activity的上下文中:

 @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(new CalligraphyContextWrapper(newBase)); } 

您也可以指定自己的自定义属性来替换android:fontFamily

它也适用于主题,包括AppTheme。

如果您只想添加一个字体,并且想要编写较少的代码,则可以为您的特定字体创建专用的TextView。 看下面的代码。

 package com.yourpackage; import android.content.Context; import android.graphics.Typeface; import android.util.AttributeSet; import android.widget.TextView; public class FontTextView extends TextView { public static Typeface FONT_NAME; public FontTextView(Context context) { super(context); if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf"); this.setTypeface(FONT_NAME); } public FontTextView(Context context, AttributeSet attrs) { super(context, attrs); if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf"); this.setTypeface(FONT_NAME); } public FontTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf"); this.setTypeface(FONT_NAME); } } 

在main.xml中,你现在可以像这样添加你的textView:

 <com.yourpackage.FontTextView android:id="@+id/tvTimer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> 

使用DataBinding

 @BindingAdapter({"bind:font"}) public static void setFont(TextView textView, String fontName){ textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName)); } 

在XML中:

 <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 

字体文件必须在assets/fonts/

扩展TextView并给它一个自定义的属性,或者只是使用android:tag属性来传递一个你想要使用什么字体的字符串。 你将需要选择一个约定,并坚持下去,例如我将把所有的字体放在res / assets / fonts /文件夹中,以便你的TextView类知道在哪里找到它们。 然后在你的构造函数中,你只需在超级调用之后手动设置字体。

使用自定义字体的唯一方法是通过源代码。

请记住,Android运行在资源非常有限的设备上,字体可能需要大量的RAM。 内置的Droid字体是专门制作的,如果您注意到,缺少许多字符和装饰。

最好的办法就是这样
1.)右键单击res文件夹并转到新建> Android资源目录 。 新的
资源目录窗口出现。
2.)在资源类型列表中选择字体 ,然后单击确定。
3.) 将字体文件添加到字体文件夹中 。下面的文件夹结构生成R.font.dancing_script,R.font.la_la和R.font.ba_ba。
4.) 双击字体文件,在编辑器中预览文件的字体。

接下来我们必须创建一个字体系列

1.)右键点击字体文件夹并转到新建>字体资源文件 。 出现“新建资源文件”窗口。
2.)输入文件名,然后单击确定 。 新的字体资源XML在编辑器中打开。
3.)在字体标签元素中包含每个字体文件,样式和重量属性。 以下XML说明了在字体资源XML中添加与字体相关的属性:

 <?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/hey_regular" /> <font android:fontStyle="italic" android:fontWeight="400" android:font="@font/hey_bababa" /> </font-family> 

将字体添加到TextView中:

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

从文档

与字体一起使用

所有的步骤都是正确的。

对于这个问题,我可能会有一个简单的答案,而不需要扩展TextView并实现一个长的代码。

代码:

  TextView tv = (TextView) findViewById(R.id.textview1); tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf")); 

像往常一样将自定义字体文件放在资产文件夹中,然后试试这个 它适用于我。 我不明白为什么彼得为这个简单的东西给了这样一个巨大的代码,或者他在旧版本中给出了他的答案。

也可以在不创建自定义类的情况下在xml中定义

style.xml

 <style name="ionicons" parent="android:TextAppearance"> <!-- Custom Attr--> <item name="fontPath">fonts/ionicons.ttf</item> </style> 

activity_main.xml中

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/ionicons" android:text=""/> </LinearLayout> 

一个简短的说明,因为我总是忘记在哪里把字体,它的字体必须在assets ,这个文件夹驻留在相同的水平, ressrc ,在我的情况下它的assets/fonts/ionicons.ttf

更新已添加的根布局,因为此方法需要xmlns:app="http://schemas.android.com/apk/res-auto"才能工作

更新2忘记了我之前安装的名为“ 书法”的图书馆

有两种方法可以自定义字体:

! 我的资产/字体/ iran_sans.ttf中的自定义字体

方法1: Refrection Typeface.class

最好的办法

调用FontsOverride.setDefaultFont()类扩展应用程序,此代码将导致所有的软件字体被改变,甚至Toasts字体

AppController.java

 public class AppController extends Application { @Override public void onCreate() { super.onCreate(); //Initial Font FontsOverride.setDefaultFont(getApplicationContext(), "MONOSPACE", "fonts/iran_sans.ttf"); } } 

FontsOverride.java

 public class FontsOverride { public static void setDefaultFont(Context context, String staticTypefaceFieldName, String fontAssetName) { final Typeface regular = Typeface.createFromAsset(context.getAssets(), fontAssetName); replaceFont(staticTypefaceFieldName, regular); } private static void replaceFont(String staticTypefaceFieldName, final Typeface newTypeface) { try { final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName); staticField.setAccessible(true); staticField.set(null, newTypeface); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } 

方式2:使用setTypeface

对于特殊的视图只需调用setTypeface()来改变字体。

CTextView.java

 public class CTextView extends TextView { public CTextView(Context context) { super(context); init(context,null); } public CTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context,attrs); } public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context,attrs); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context,attrs); } public void init(Context context, @Nullable AttributeSet attrs) { if (isInEditMode()) return; // use setTypeface for change font this view setTypeface(FontUtils.getTypeface("fonts/iran_sans.ttf")); } } 

FontUtils.java

 public class FontUtils { private static Hashtable<String, Typeface> fontCache = new Hashtable<>(); public static Typeface getTypeface(String fontName) { Typeface tf = fontCache.get(fontName); if (tf == null) { try { tf = Typeface.createFromAsset(AppController.getInstance().getApplicationContext().getAssets(), fontName); } catch (Exception e) { e.printStackTrace(); return null; } fontCache.put(fontName, tf); } return tf; } } 

彼得的答案是最好的,但是可以通过使用Android的styles.xml来为你的应用程序中的所有文字视图自定义你的字体。

我的代码在这里

这里有一个教程,告诉你如何设置一个自定义字体,如@皮特描述: http ://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html

它也考虑了潜在的内存泄漏阿拉http://code.google.com/p/android/issues/detail?id=9904 。 在教程中也是一个在按钮上设置自定义字体的示例。

Fontinator是一个Android库使得它很容易,使用自定义字体。 https://github.com/svendvd/Fontinator

您无法扩展TextView以创建小部件或在小部件布局中使用它: http : //developer.android.com/guide/topics/appwidgets/index.html