Android:想要为整个应用程序而不是运行时设置自定义字体 [英] Android: Want to set custom fonts for whole application not runtime

查看:26
本文介绍了Android:想要为整个应用程序而不是运行时设置自定义字体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to set any custom font in every control of the application? And not necessarily runtime ? (i.e. from xml if possible or only once for whole application in JAVA file)

我可以通过这段代码为一个控件设置字体.

I can set the font for one control from this code.

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

    textView.setTypeface(tf);

}

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

And the problem with this code is it should be called for every control. And i want to call this or any similar method once, or if possible set the property in xml. Is it possible?

推荐答案

EDIT:所以已经有一段时间了,我想补充一下我认为最好的方法,并且通过 XML 也不少!

EDIT: So it's been a while, and I'd like to add what I think is the best way to do this, and through XML no less!

因此,首先,您需要创建一个新类来覆盖您想要自定义的任何视图.(例如,想要一个带有自定义字体的按钮?扩展 Button).举个例子:

So first, you're going to want to make a new class that overrides whatever View you want to customize. (e.g. want a Button with a custom typeface? Extend Button). Let's make an example:

public class CustomButton extends Button {
    private final static int ROBOTO = 0;
    private final static int ROBOTO_CONDENSED = 1;

    public CustomButton(Context context) {
        super(context);
    }

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        parseAttributes(context, attrs); //I'll explain this method later
    }

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        parseAttributes(context, attrs);
    }
}

现在,如果您没有,请在 res/values/attrs.xml 下添加一个 XML 文档,并添加:

Now, if you don't have one, add an XML document under res/values/attrs.xml, and add:

<resources>
    <!-- Define the values for the attribute -->
    <attr name="typeface" format="enum">
        <enum name="roboto" value="0"/>
        <enum name="robotoCondensed" value="1"/>
    </attr>

    <!-- Tell Android that the class "CustomButton" can be styled, 
         and which attributes it supports -->
    <declare-styleable name="CustomButton">
        <attr name="typeface"/>
    </declare-styleable>
</resources>

好的,让我们回到之前的 parseAttributes() 方法:

Okay, so with that out of the way, let's get back to the parseAttributes() method from earlier:

private void parseAttributes(Context context, AttributeSet attrs) {
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton);

    //The value 0 is a default, but shouldn't ever be used since the attr is an enum
    int typeface = values.getInt(R.styleable.CustomButton_typeface, 0);

    switch(typeface) {
        case ROBOTO: default:
            //You can instantiate your typeface anywhere, I would suggest as a 
            //singleton somewhere to avoid unnecessary copies
            setTypeface(roboto); 
            break;
        case ROBOTO_CONDENSED:
            setTypeface(robotoCondensed);
            break;
    }

    values.recycle();
}

现在你已经准备好了.您可以为任何内容添加更多属性(您可以为 typefaceStyle 添加另一个属性——粗体、斜体等),但现在让我们看看如何使用它:

Now you're all set. You can add more attributes for about anything (you could add another one for typefaceStyle -- bold, italic, etc.) but now let's see how to use it:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.yourpackage.name"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.yourpackage.name.CustomButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me!"
        custom:typeface="roboto" />

</LinearLayout>

xmlns:custom 行实际上可以是任何内容,但约定是上面显示的内容.重要的是它是唯一的,这就是使用包名称的原因.现在您只需为您的属性使用 custom: 前缀,为 android 属性使用 android: 前缀.

The xmlns:custom line can really be anything, but the convention is what's shown above. What matters is that it is unique, and that's why the package name is used. Now you just use the custom: prefix for your attributes, and the android: prefix for android attributes.

最后一件事:如果你想在一个样式中使用它(res/values/styles.xml),你应该不要添加xmlns:自定义 行.只引用没有前缀的属性名称:

One last thing: if you want to use this in a style (res/values/styles.xml), you should not add the xmlns:custom line. Just reference the name of the attribute with no prefix:

<style name="MyStyle>
    <item name="typeface">roboto</item>
</style>

<小时>

                               (PREVIOUS ANSWER)

在 Android 中使用自定义字体

这应该会有所帮助.基本上,没有办法在 XML 中做到这一点,据我所知,没有更简单的方法在代码中做到这一点.你总是可以有一个 setLayoutFont() 方法来创建一次字体,然后为每个运行 setTypeface() .每次向布局添加新项目时,您只需更新它.类似于以下内容:

This should help. Basically, there's no way to do this in XML, and as far as I can tell, no easier way to do it in code. You could always have a setLayoutFont() method that creates the typeface once, then runs setTypeface() for each. You'd just have to update it each time you add a new item to a layout. Something like below:

public void setLayoutFont() {
    Typeface tf = Typeface.createFromAsset(
        getBaseContext().getAssets(), "fonts/BPreplay.otf");
    TextView tv1 = (TextView)findViewById(R.id.tv1);
    tv1.setTypeface(tf);

    TextView tv2 = (TextView)findViewById(R.id.tv2);
    tv2.setTypeface(tf);

    TextView tv3 = (TextView)findViewById(R.id.tv3);
    tv3.setTypeface(tf);
}

编辑:所以我自己才开始实现这样的东西,我最终是如何实现这样的功能的:

EDIT: So I just got around to implementing something like this myself, and how I ended up doing it was making a function such as this:

public static void setLayoutFont(Typeface tf, TextView...params) {
    for (TextView tv : params) {
        tv.setTypeface(tf);
    }
}

然后,只需使用 onCreate() 中的此方法,并传递所有要更新的 TextView:

Then, just use this method from onCreate(), and pass all the TextViews you want to update:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
//find views by id...
setLayoutFont(tf, tv1, tv2, tv3, tv4, tv5);

编辑 9/5/12:

因此,由于这仍然获得观点和投票,我想添加一个更好更完整的方法:

So since this is still getting views and votes, I'd like to add a much better and more complete method:

Typeface mFont = Typeface.createFromAsset(getAssets(), "fonts/BPreplay.otf");
ViewGroup root = (ViewGroup)findViewById(R.id.myrootlayout);
setFont(root, mFont);

/*
 * Sets the font on all TextViews in the ViewGroup. Searches
 * recursively for all inner ViewGroups as well. Just add a
 * check for any other views you want to set as well (EditText,
 * etc.)
 */
public void setFont(ViewGroup group, Typeface font) {
    int count = group.getChildCount();
    View v;
    for(int i = 0; i < count; i++) {
        v = group.getChildAt(i);
        if(v instanceof TextView || v instanceof Button /*etc.*/)
            ((TextView)v).setTypeface(font);
        else if(v instanceof ViewGroup)
            setFont((ViewGroup)v, font);
    }
}

如果您将布局的根传递给它,它将递归检查该布局中的 TextViewButton 视图(或您添加到该 if 语句的任何其他视图), 并设置字体而无需通过 ID 指定它们.这当然是假设您要将字体设置为每个视图.

If you pass it the root of your layout, it will recursively check for TextView or Button views (or any others you add to that if statement) within that layout, and set the font without you having to specify them by ID. This of course is assuming you want to set the font to every view.

这篇关于Android:想要为整个应用程序而不是运行时设置自定义字体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆