Android:想为整个应用程序设置自定义字体,而不是运行时


Answers

有一个相当简单的方法可以通过XML来完成。 你只需要创建自己的扩展TextView的小部件。

首先,在res / values / attrs.xml中使用以下内容创建一个文件:

<resources>
    <declare-styleable name="TypefacedTextView">
        <attr name="typeface" format="string" />
    </declare-styleable>
</resources>

之后,创建您的自定义小部件:

package your.package.widget;

public class TypefacedTextView extends TextView {

    public TypefacedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //Typeface.createFromAsset doesn't work in the layout editor. Skipping...
        if (isInEditMode()) {
            return;
        }

        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TypefacedTextView);
        String fontName = styledAttrs.getString(R.styleable.TypefacedTextView_typeface);
        styledAttrs.recycle();

        if (fontName != null) {
            Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontName);
            setTypeface(typeface);
        }
    }

}

如您所见,上面的代码将会读取资产/文件夹中的字体。 在这个例子中,我假设资产文件夹中有一个名为“custom.ttf”的文件。 最后,在XML中使用小部件:

<your.package.widget.TypefacedTextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:your_namespace="http://schemas.android.com/apk/res/your.package"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Custom fonts in XML are easy"
    android:textColor="#FFF"
    android:textSize="14dip"
    your_namespace:typeface="custom.ttf" />

注意:您将无法在Eclipse的布局编辑器中看到自定义字体。 这就是为什么我把isInEditMode()检查。 但是如果你运行你的应用程序,自定义字体将像魅力一样工作。

希望能帮助到你!

Question

是否可以在应用程序的每个控件中设置任何自定义字体? 而不一定是运行时? (即如果可能的话,从xml中或者在JAVA文件中只对整个应用程序执行一次)

我可以从这段代码中为一个控件设置字体。

public static void setFont(TextView textView) {
    Typeface tf = Typeface.createFromAsset(textView.getContext()
            .getAssets(), "fonts/BPreplay.otf");

    textView.setTypeface(tf);

}

这个代码的问题是每个控件都应该被调用。 我想调用这个或任何类似的方法一次,或者如果可能的话在xml中设置属性。 可能吗?




不幸的是,Android不提供您想要更改整个应用的字体的快速,简单和干净的方式。 但最近我研究了这个问题,并创建了一些工具,允许您在没有任何编码的情况下更改字体(您可以通过xml,样式甚至文本显示完成所有工作)。 他们基于类似的解决方案,就像你在这里的其他答案中看到的一样,但考虑到更多的灵活性。 你可以在这个博客上阅读关于它的所有信息,并在here看到github项目。

以下是如何应用这些工具的示例。 把所有的字体文件放在assets/fonts/ 。 然后,在xml文件中声明这些字体(例如res/xml/fonts.xml ),并使用TypefaceManager.initialize(this, R.xml.fonts);在应用程序的早期加载该文件TypefaceManager.initialize(this, R.xml.fonts); (例如,在您的应用程序类的onCreate中)。 这个xml文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<familyset>

    <!-- Some Font. Can be referenced with 'someFont' or 'aspergit' -->
    <family>
        <nameset>
            <name>aspergit</name>
            <name>someFont</name>
        </nameset>
        <fileset>
            <file>Aspergit.ttf</file>
            <file>Aspergit Bold.ttf</file>
            <file>Aspergit Italic.ttf</file>
            <file>Aspergit Bold Italic.ttf</file>
        </fileset>
    </family>

    <!-- Another Font. Can be referenced with 'anotherFont' or 'bodoni' -->
    <family>
        <nameset>
            <name>bodoni</name>
            <name>anotherFont</name>
        </nameset>
        <fileset>
            <file>BodoniFLF-Roman.ttf</file>
            <file>BodoniFLF-Bold.ttf</file>
        </fileset>
    </family>

</familyset>

现在,您可以在您的xml布局中使用自定义UI元素com.innovattic.font.FontTextView ,在您的样式或xml中使用这些字体(假设您使用上述工具)。 在下面,您可以看到如何通过编辑res/values/styles.xml来将字体应用于整个应用中的所有文本:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

随附res/layout/layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

不要忘记在Android清单中应用主题。




这太晚了,但我的帮助对方
我已经创建了CustomTextView,它有一个名为typeFace的属性,它处理的是无缓存的字体加载的内存泄漏问题

首先是Fonts类,它只从资产中加载一次字体

 import android.content.Context;
import android.graphics.Typeface;

import java.util.Hashtable;

/**
 * Created by tonyhaddad on 7/19/15.
 */
public class Fonts {
    private Context context;

    public Fonts(Context context) {
        this.context = context;
    }
    private static Hashtable<String, Typeface> sTypeFaces = new Hashtable<String, Typeface>(
            4);
    public static Typeface getTypeFace(Context context, String fileName) {
        Typeface tempTypeface = sTypeFaces.get(fileName);

        if (tempTypeface == null) {
            String fontPath=null;
            if(fileName=="metabold")
                fontPath ="fonts/Meta-Bold.ttf";

            else if(fileName=="metanormal")
                fontPath="fonts/Meta-Normal.ttf";
            else if(fileName=="gsligh")
                fontPath="fonts/gesslight.ttf";
            else if(fileName=="bold")
                fontPath="fonts/Lato-Bold.ttf";
            else if(fileName=="rcr")
                fontPath="fonts/RobotoCondensed-Regular.ttf";

            else if(fileName=="mpr")
                fontPath="fonts/MyriadPro-Regular.otf";
            else if(fileName=="rr")
                fontPath="fonts/Roboto-Regular.ttf";

            tempTypeface = Typeface.createFromAsset(context.getAssets(), fontPath);
            sTypeFaces.put(fileName, tempTypeface);
        }

        return tempTypeface;
    }
}

那么你需要在attrs.xml添加一个自定义属性添加这个

<declare-styleable name="CustomFontTextView">
        <attr name="typeFace" format="string" />

    </declare-styleable>

然后自定义类

 package package_name;

/**
 * Created by tonyhaddad on 8/26/15.
 */

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

import package_name.R;

public class CustomFontTextView extends TextView {

    String typeFace;


    public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (isInEditMode()) {
            return;
        }
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomFontTextView,
                0, 0);
        try {
            typeFace = a.getString(0);
        } finally {
            a.recycle();
        }

        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }

        init();
    }

    public CustomFontTextView(Context context) {
        super(context);



        if(typeFace!=null && !typeFace.equalsIgnoreCase(""))
        {
            Typeface tf = Fonts.getTypeFace(context, typeFace);
            setTypeface(tf);
        }
        init();
    }


    private void init() {

    }

    public String getTypeFace() {
        return typeFace;
    }

    public void setTypeFace(String typeFace) {
        this.typeFace = typeFace;
        invalidate();
        requestLayout();
    }
}

最后添加文本视图

  <package_name.CustomFontTextView
            xmlns:custom="http://schemas.android.com/apk/res-auto/package_name"
            android:id="@+id/txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="41dp"
            android:gravity="center_vertical"
            android:text="text"
            android:textColor="#000"
            android:textSize="23sp"
            custom:typeFace="metanormal"/>

您可以使用setTypeFace方法更改字体编程
如果您想在此视图中使用多个布局,也可以将自定义名称空间移动到您的父级布局

快乐编码:)




如果您正在寻找更通用的编程解决方案,我创建了一个静态类,可用于设置整个视图的字体(活动UI)。 请注意,我正在使用Mono(C#),但您可以使用Java轻松实现它。

您可以将此类传递给您想要自定义的布局或特定视图。 如果你想超级高效,你可以使用Singleton模式来实现它。

public static class AndroidTypefaceUtility 
{
    static AndroidTypefaceUtility()
    {
    }
    //Refer to the code block beneath this one, to see how to create a typeface.
    public static void SetTypefaceOfView(View view, Typeface customTypeface)
    {
    if (customTypeface != null && view != null)
    {
            try
            {
                if (view is TextView)
                    (view as TextView).Typeface = customTypeface;
                else if (view is Button)
                    (view as Button).Typeface = customTypeface;
                else if (view is EditText)
                    (view as EditText).Typeface = customTypeface;
                else if (view is ViewGroup)
                    SetTypefaceOfViewGroup((view as ViewGroup), customTypeface);
                else
                    Console.Error.WriteLine("AndroidTypefaceUtility: {0} is type of {1} and does not have a typeface property", view.Id, typeof(View));
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("AndroidTypefaceUtility threw:\n{0}\n{1}", ex.GetType(), ex.StackTrace);
                    throw ex;
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / view parameter should not be null");
            }
        }

        public static void SetTypefaceOfViewGroup(ViewGroup layout, Typeface customTypeface)
        {
            if (customTypeface != null && layout != null)
            {
                for (int i = 0; i < layout.ChildCount; i++)
                {
                    SetTypefaceOfView(layout.GetChildAt(i), customTypeface);
                }
            }
            else
            {
                Console.Error.WriteLine("AndroidTypefaceUtility: customTypeface / layout parameter should not be null");
            }
        }

    }

在你的活动中,你将需要创建一个Typeface对象。 我使用放置在我的资源/资产/目录中的.ttf文件在OnCreate()中创建我的。 确保该文件的属性中标记为Android资产。

protected override void OnCreate(Bundle bundle)
{               
    ...
    LinearLayout rootLayout = (LinearLayout)FindViewById<LinearLayout>(Resource.Id.signInView_LinearLayout);
    Typeface allerTypeface = Typeface.CreateFromAsset(base.Assets,"Aller_Rg.ttf");
    AndroidTypefaceUtility.SetTypefaceOfViewGroup(rootLayout, allerTypeface);
}



我在这个链接上找到了一步一步的信息,链接: https://github.com/jaydipumaretiya/CustomTypeface/https://github.com/jaydipumaretiya/CustomTypeface/

有很多方法可以在android中正确使用字体,您必须直接将您的字体文件放在主文件夹下的assets文件夹中,并且可以使用它运行时。

其他最简单的方法是使用默认库在xml文件中设置字体。 我更喜欢这个自定义字体库来设置字体为android中的TextView,EditText,Button,CheckBox,RadioButton和AutoCompleteTextView以及其他wedget。