在Android中使用自定义字体


111

我想为正在创建的android应用程序使用自定义字体。
我可以从Code中单独更改每个对象的字体,但是我有数百个。

所以,

  • 有没有办法从XML做到这一点?[设置自定义字体]
  • 有没有一种方法可以从一个地方的代码做到这一点,也就是说整个应用程序和所有组件都应使用自定义字体而不是默认字体?

stackoverflow.com/questions/5541058/…看这篇文章,我在这里发布了有关此问题的完整代码
Manish Singla 2011年

您可以在主要活动中使用静态变量来保存对嵌入式字体的引用。这将导致存在一组永久字体,GC不会选择它们。
杰克逊(Jacksonkr)2012年

工厂方法。或者是一种可以让您查看并设置所有字体和字体设置的方法。
mtmurdock 2012年

现在,新的支持库26允许您使用XML字体。这是怎么做的在XML字体
维尼休斯·席尔瓦

Answers:


80

有没有办法从XML做到这一点?

不,对不起 您只能通过XML指定内置字体。

有没有一种方法可以从一个地方的代码做到这一点,也就是说整个应用程序和所有组件都应使用自定义字体而不是默认字体?

不是我知道的。

如今,这些选项有很多:

  • 如果使用的是Android SDK中的字体资源和反向移植 appcompat

  • 那些不使用的第三方库appcompat,尽管并非全部都支持在布局资源中定义字体


4
@Codevalley:嗯,在很多方面,更好的答案是不要大惊小怪自定义字体。它们往往很大,使您的下载量更大,并减少了下载并继续使用您的应用程序的人数。
CommonsWare 2010年

22
@CommonsWare:我不一定同意。字体是UI样式不可或缺的一部分,就像处理背景图像等一样。并且尺寸不一定总是很大。例如,在我的情况下,字体仅为19.6KB :)
Codevalley 2010年

2
@Amit:在这个问题上没有变化。周围有很多代码片段可以帮助简化Java中将字体应用于UI的工作,但是无法通过XML来实现。
CommonsWare 2013年

1
@Amit:“但这是否意味着我将必须为自定义字体创建自己的.ttf或.otf文件?” - 不。您可以使用现有的TTF / OTF字体,尽管它们可能无法全部工作。这个问题的问题是如何在整个应用程序中应用这些字体,但这仍然是不可能的,这就是我在评论中所指的内容。
CommonsWare 2013年

1
这个已接受的答案已经过时了,最好对其进行更新或删除。
Sky Kelsey

109

是的,有可能。

您必须创建一个自定义视图,以扩展文本视图。

attrs.xmlvalues文件夹中:

<resources>
    <declare-styleable name="MyTextView">
        <attr name="first_name" format="string"/>
        <attr name="last_name" format="string"/>
        <attr name="ttf_name" format="string"/>
    </declare-styleable>
</resources>

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:lht="http://schemas.android.com/apk/res/com.lht"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView  android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="Hello"/>
    <com.lht.ui.MyTextView  
        android:id="@+id/MyTextView"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="Hello friends"
        lht:ttf_name="ITCBLKAD.TTF"
        />   
</LinearLayout>

MyTextView.java

package com.lht.ui;

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

public class MyTextView extends TextView {

    Context context;
    String ttfName;

    String TAG = getClass().getName();

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            Log.i(TAG, attrs.getAttributeName(i));
            /*
             * Read value of custom attributes
             */

            this.ttfName = attrs.getAttributeValue(
                    "http://schemas.android.com/apk/res/com.lht", "ttf_name");
            Log.i(TAG, "firstText " + firstText);
            // Log.i(TAG, "lastText "+ lastText);

            init();
        }

    }

    private void init() {
        Typeface font = Typeface.createFromAsset(context.getAssets(), ttfName);
        setTypeface(font);
    }

    @Override
    public void setTypeface(Typeface tf) {

        // TODO Auto-generated method stub
        super.setTypeface(tf);
    }

}

4
这将起作用,但仅适用于TextView。对于从TextView需要相同功能的地方继承的每个小部件类,它将需要自定义子类。
CommonsWare

嗨,Manish,谢谢您的解决方案。虽然我在使用此工具时遇到问题。我不断收到“在包com.lht.android中找不到属性ttf_name的资源标识符”
Kshitij Aggarwal 2011年

17
这将起作用,但是在ICS之前,它将为您实例化的每个视图的字体分配内存:code.google.com/p/android/issues/detail?id=9904解决此问题的一种方法是创建可全局访问的所有实例化字体的静态哈希图:code.google.com/p/android/issues/detail?
id=9904#c7

为什么我们需要一个循环?,它是否不能与单个调用一起使用?
Guillermo Tobar

1
@AlaksiejN。如果您需要为不同的TextViews设置不同的字体...
尼克

49

我以一种“强力”方式完成了此操作,不需要更改布局xml或“活动”。

在Android版本2.1到4.4上进行了测试。在应用程序启动时,在您的Application类中运行此命令:

private void setDefaultFont() {

    try {
        final Typeface bold = Typeface.createFromAsset(getAssets(), DEFAULT_BOLD_FONT_FILENAME);
        final Typeface italic = Typeface.createFromAsset(getAssets(), DEFAULT_ITALIC_FONT_FILENAME);
        final Typeface boldItalic = Typeface.createFromAsset(getAssets(), DEFAULT_BOLD_ITALIC_FONT_FILENAME);
        final Typeface regular = Typeface.createFromAsset(getAssets(),DEFAULT_NORMAL_FONT_FILENAME);

        Field DEFAULT = Typeface.class.getDeclaredField("DEFAULT");
        DEFAULT.setAccessible(true);
        DEFAULT.set(null, regular);

        Field DEFAULT_BOLD = Typeface.class.getDeclaredField("DEFAULT_BOLD");
        DEFAULT_BOLD.setAccessible(true);
        DEFAULT_BOLD.set(null, bold);

        Field sDefaults = Typeface.class.getDeclaredField("sDefaults");
        sDefaults.setAccessible(true);
        sDefaults.set(null, new Typeface[]{
                regular, bold, italic, boldItalic
        });

    } catch (NoSuchFieldException e) {
        logFontError(e);
    } catch (IllegalAccessException e) {
        logFontError(e);
    } catch (Throwable e) {
        //cannot crash app if there is a failure with overriding the default font!
        logFontError(e);
    }
}

有关更完整的示例,请参见http://github.com/perchrh/FontOverrideExample


这对我来说是最好的解决方案。
伊戈尔K

2
默认对我不起作用。如果我使用等宽字体,然后设置code<style name =“ AppTheme” parent =“ AppBaseTheme”> <item name =“ android:typeface”> monospace </ item> </ style>,code则可以使用,但不能用于粗体。我在扩展Application的类中添加了此代码。那是正确的地方吗?@ P-chan
Christopher Rivera 2014年

2
@ChristopherRivera是的,将其添加到应用程序的Application类中,确保它在onCreate上运行。看一下grepcode.com/file/repository.grepcode.com/java/ext/…我建议您覆盖等宽的附加字段以及上面的示例代码中的那个!
Per Christian Henden 2014年

2
好吧,我换了SERIF领域,它起作用了:)
Abdullah Umer 2014年

3
此答案引用了此答案,并提供了一种更简洁的方法。
adamdport

36

尽管我赞成Manish的回答是最快,最有针对性的方法,但我也看到过一些幼稚的解决方案,它们只是递归地遍历视图层次结构并依次更新所有元素的字体。像这样:

public static void applyFonts(final View v, Typeface fontToSet)
{
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                applyFonts(child, fontToSet);
            }
        } else if (v instanceof TextView) {
            ((TextView)v).setTypeface(fontToSet);
        }
    } catch (Exception e) {
        e.printStackTrace();
        // ignore
    }
}

扩大布局后,您需要在视图上调用此函数,也需要在Activity的onContentChanged()方法中调用此函数。


差不多了 当时,这是在项目时间表内完成此操作的唯一方法。如果需要,可以使用便捷的快捷方式(:
pospi

23

我能够集中地执行此操作,结果如下:

在此处输入图片说明

我有以下内容Activity,如果需要自定义字体,可以从中进行扩展:

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater.Factory;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class CustomFontActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    getLayoutInflater().setFactory(new Factory() {

        @Override
        public View onCreateView(String name, Context context,
                AttributeSet attrs) {
            View v = tryInflate(name, context, attrs);
            if (v instanceof TextView) {
                setTypeFace((TextView) v);
            }
            return v;
        }
    });
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

private View tryInflate(String name, Context context, AttributeSet attrs) {
    LayoutInflater li = LayoutInflater.from(context);
    View v = null;
    try {
        v = li.createView(name, null, attrs); 
    } catch (Exception e) {
        try {
            v = li.createView("android.widget." + name, null, attrs);
        } catch (Exception e1) {
        }
    }
    return v;
}

private void setTypeFace(TextView tv) {
    tv.setTypeface(FontUtils.getFonts(this, "MTCORSVA.TTF"));
}
}

但是,如果我正在使用支持包中的活动,FragmentActivity则可以使用以下命令Activity

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class CustomFontFragmentActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

// we can't setLayout Factory as its already set by FragmentActivity so we
// use this approach
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    View v = super.onCreateView(name, context, attrs);
    if (v == null) {
        v = tryInflate(name, context, attrs);
        if (v instanceof TextView) {
            setTypeFace((TextView) v);
        }
    }
    return v;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public View onCreateView(View parent, String name, Context context,
        AttributeSet attrs) {
    View v = super.onCreateView(parent, name, context, attrs);
    if (v == null) {
        v = tryInflate(name, context, attrs);
        if (v instanceof TextView) {
            setTypeFace((TextView) v);
        }
    }
    return v;
}

private View tryInflate(String name, Context context, AttributeSet attrs) {
    LayoutInflater li = LayoutInflater.from(context);
    View v = null;
    try {
        v = li.createView(name, null, attrs);
    } catch (Exception e) {
        try {
            v = li.createView("android.widget." + name, null, attrs);
        } catch (Exception e1) {
        }
    }
    return v;
}

private void setTypeFace(TextView tv) {
    tv.setTypeface(FontUtils.getFonts(this, "MTCORSVA.TTF"));
}
}

我没有用 Fragment尚未 s,但希望它能工作。

我的方法FontUtils很简单,也解决了https://code.google.com/p/android/issues/detail?id=9904此处提到的ICS之前的问题:

import java.util.HashMap;
import java.util.Map;

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

public class FontUtils {

private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();

public static Typeface getFonts(Context context, String name) { 
    Typeface typeface = TYPEFACE.get(name);
    if (typeface == null) {
        typeface = Typeface.createFromAsset(context.getAssets(), "fonts/"
                + name);
        TYPEFACE.put(name, typeface);
    }
    return typeface;
}
}

2
这应该获得更多选票。它可以正常工作,并且具有用于演示的屏幕截图
ericn 2014年

10

嘿,我的应用程序中还需要2种不同的字体,以适应不同的寡妇!我用这种方式:

在我的Application类中,我创建一个静态方法:

public static Typeface getTypeface(Context context, String typeface) {
    if (mFont == null) {
        mFont = Typeface.createFromAsset(context.getAssets(), typeface);
    }
    return mFont;
}

字符串字体表示资产文件夹中的xyz.ttf。(我创建了一个常量类)现在您可以在应用程序中的任何地方使用它:

mTextView = (TextView) findViewById(R.id.text_view);
mTextView.setTypeface(MyApplication.getTypeface(this, Constants.TYPEFACE_XY));

唯一的问题是,每个要使用字体的小部件都需要它!但是我认为这是最好的方法。


4

使用pospi的建议并使用Richard等“ tag”属性一样,我创建了一个自定义类,该类加载我的自定义字体并将其根据其标签应用于视图。

因此,基本上,不是使用android:fontFamily属性中的TypeFace,而是使用android:tag attritube并将其设置为已定义的枚举之一。

public class Fonts {
    private AssetManager mngr;

    public Fonts(Context context) {
        mngr = context.getAssets();
    }
    private enum AssetTypefaces {
        RobotoLight,
        RobotoThin,
        RobotoCondensedBold,
        RobotoCondensedLight,
        RobotoCondensedRegular
    }

    private Typeface getTypeface(AssetTypefaces font) {
        Typeface tf = null;
        switch (font) {
            case RobotoLight:
                tf = Typeface.createFromAsset(mngr,"fonts/Roboto-Light.ttf");
                break;
            case RobotoThin:
                tf = Typeface.createFromAsset(mngr,"fonts/Roboto-Thin.ttf");
                break;
            case RobotoCondensedBold:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Bold.ttf");
                break;
            case RobotoCondensedLight:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Light.ttf");
                break;
            case RobotoCondensedRegular:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Regular.ttf");
                break;
            default:
                tf = Typeface.DEFAULT;
                break;
        }
        return tf;
    }
    public void setupLayoutTypefaces(View v) {
        try {
            if (v instanceof ViewGroup) {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++) {
                    View child = vg.getChildAt(i);
                    setupLayoutTypefaces(child);
                }
            } else if (v instanceof TextView) {
                if (v.getTag().toString().equals(AssetTypefaces.RobotoLight.toString())){
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoLight));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedRegular.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedRegular));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedBold.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedBold));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedLight.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedLight));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoThin.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoThin));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            // ignore
        }
    }
}

在您的活动或片段中,您只需调用

Fonts fonts = new Fonts(getActivity());
fonts.setupLayoutTypefaces(mainLayout);

4

我在Lisa Wray的博客上找到了一个不错的解决方案。使用新的数据绑定,可以在XML文件中设置字体。

@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"/>

您能否建议使用数据绑定的示例?那将不胜感激。
克里希纳

3

我认为可以有一种更简便的方法。下面的类将为应用程序的所有组件设置一个自定义字体(每个类都有一个设置)。

/**
 * Base Activity of our app hierarchy.
 * @author SNI
 */
public class BaseActivity extends Activity {

    private static final String FONT_LOG_CAT_TAG = "FONT";
    private static final boolean ENABLE_FONT_LOGGING = false;

    private Typeface helloTypeface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        helloTypeface = Typeface.createFromAsset(getAssets(), "fonts/<your type face in assets/fonts folder>.ttf");
    }

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        View view = super.onCreateView(name, context, attrs);
        return setCustomTypeFaceIfNeeded(name, attrs, view);
    }

    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        View view = super.onCreateView(parent, name, context, attrs);
        return setCustomTypeFaceIfNeeded(name, attrs, view);
    }

    protected View setCustomTypeFaceIfNeeded(String name, AttributeSet attrs, View view) {
        View result = null;
        if ("TextView".equals(name)) {
            result = new TextView(this, attrs);
            ((TextView) result).setTypeface(helloTypeface);
        }

        if ("EditText".equals(name)) {
            result = new EditText(this, attrs);
            ((EditText) result).setTypeface(helloTypeface);
        }

        if ("Button".equals(name)) {
            result = new Button(this, attrs);
            ((Button) result).setTypeface(helloTypeface);
        }

        if (result == null) {
            return view;
        } else {
            if (ENABLE_FONT_LOGGING) {
                Log.v(FONT_LOG_CAT_TAG, "A type face was set on " + result.getId());
            }
            return result;
        }
    }

}

2

LayoutInflater的默认实现不支持从xml指定字体字体。但是,我通过为LayoutInflater提供自定义工厂来看到它在xml中的完成,该工厂将解析xml标记中的此类属性。

基本结构就是这样。

public class TypefaceInflaterFactory implements LayoutInflater.Factory {

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        // CUSTOM CODE TO CREATE VIEW WITH TYPEFACE HERE
        // RETURNING NULL HERE WILL TELL THE INFLATER TO USE THE
        // DEFAULT MECHANISMS FOR INFLATING THE VIEW FROM THE XML
    }

}

public class BaseActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater.from(this).setFactory(new TypefaceInflaterFactory());
    }
}

本文对这些机制以及作者如何尝试以这种方式为字体提供xml布局支持提供了更深入的说明。作者实现的代码可在此处找到。


1

将自定义字体设置为常规的ProgressDialog / AlertDialog:

font=Typeface.createFromAsset(getAssets(),"DroidSans.ttf");

ProgressDialog dialog = ProgressDialog.show(this, "titleText", "messageText", true);
((TextView)dialog.findViewById(Resources.getSystem().getIdentifier("message", "id", "android"))).setTypeface(font);
((TextView)dialog.findViewById(Resources.getSystem().getIdentifier("alertTitle", "id", "android"))).setTypeface(font);

1

是的,可以通过覆盖默认字体来实现。我遵循了解决方案,并且只需进行一次更改,它就可以像所有TextViews和ActionBar文本一样吸引人。

public class MyApp extends Application {

  @Override
  public void onCreate() {
    TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/Roboto-Regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
  }
}

styles.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/pantone</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
    <item name="android:windowDisablePreview">true</item>
    <item name="android:typeface">serif</item>
</style>

我没有在上面的链接中提到themes.xml,而是在默认的应用程序主题标签中的styles.xml中覆盖了要覆盖的默认字体。可以覆盖的默认字体是serif,sans,monospace和normal。

TypefaceUtil.java

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {
            Log.e("Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

最初,我不知道要覆盖的字体是固定的,还是一组定义的值,但是最终,它帮助我了解了Android如何处理字体和字体及其默认值,这是一个不同的观点。


0

我不知道它是否会改变整个应用程序,但是我设法更改了一些其他原本无法更改的组件:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lucida Sans Unicode.ttf");
Typeface.class.getField("DEFAULT").setAccessible(true);
Typeface.class.getField("DEFAULT_BOLD").setAccessible(true);
Typeface.class.getField("DEFAULT").set(null, tf);
Typeface.class.getField("DEFAULT_BOLD").set(null, tf);

2
不幸的是,这不再起作用:java.lang.IllegalAccessException:在java.lang.reflect.Field.setField(Native Method)的java.lang.reflect.Field.setField(Native Method)将该字段标记为“ final”。 556)
董事会2012年

0

我喜欢pospi的建议。为什么不全力以赴使用视图的'tag'属性(您可以在XML中指定-'android:tag')来指定您在XML中无法执行的其他样式。我喜欢JSON,因此可以使用JSON字符串指定键/值集。该课程完成工作-只需Style.setContentView(this, [resource id])参加您的活动即可。

public class Style {

  /**
   * Style a single view.
   */
  public static void apply(View v) {
    if (v.getTag() != null) {
      try {
        JSONObject json = new JSONObject((String)v.getTag());
        if (json.has("typeface") && v instanceof TextView) {
          ((TextView)v).setTypeface(Typeface.createFromAsset(v.getContext().getAssets(),
                                                             json.getString("typeface")));
        }
      }
      catch (JSONException e) {
        // Some views have a tag without it being explicitly set!
      }
    }
  }

  /**
   * Style the passed view hierarchy.
   */
  public static View applyTree(View v) {
    apply(v);
    if (v instanceof ViewGroup) {
      ViewGroup g = (ViewGroup)v;
      for (int i = 0; i < g.getChildCount(); i++) {
        applyTree(g.getChildAt(i));
      }
    }
    return v;
  }

  /**
   * Inflate, style, and set the content view for the passed activity.
   */
  public static void setContentView(Activity activity, int resource) {
    activity.setContentView(applyTree(activity.getLayoutInflater().inflate(resource, null)));
  }
}

显然,您不仅仅需要处理字体,而且值得使用JSON。

“标记”属性的一个好处是,您可以将其设置为用作主题的基本样式,从而使其自动应用于所有视图。编辑:这样做会导致Android 4.0.3膨胀期间崩溃。您仍然可以使用样式并将其分别应用于文本视图。

您会在代码中看到一件事-有些视图具有未显式设置的标记-奇怪的是字符串'Αποκοπή'-根据希腊语翻译,在希腊语中是“ cut”!我勒个去...?


0

@majinboo的答案已针对性能和内存管理进行了修订。通过将构造函数本身作为参数,任何不止一种字体需要相关的Activity都可以使用此Font类。

@Override
public void onCreate(Bundle savedInstanceState)
{
    Font font = new Font(this);
}

修订后的字体类如下:

public class Fonts
{
    private HashMap<AssetTypefaces, Typeface> hashMapFonts;

    private enum AssetTypefaces
    {
        RobotoLight,
        RobotoThin,
        RobotoCondensedBold,
        RobotoCondensedLight,
        RobotoCondensedRegular
    }

    public Fonts(Context context)
    {
        AssetManager mngr = context.getAssets();

        hashMapFonts = new HashMap<AssetTypefaces, Typeface>();
        hashMapFonts.put(AssetTypefaces.RobotoLight, Typeface.createFromAsset(mngr, "fonts/Roboto-Light.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoThin, Typeface.createFromAsset(mngr, "fonts/Roboto-Thin.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedBold, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Bold.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedLight, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Light.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedRegular, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Regular.ttf"));
    }

    private Typeface getTypeface(String fontName)
    {
        try
        {
            AssetTypefaces typeface = AssetTypefaces.valueOf(fontName);
            return hashMapFonts.get(typeface);
        }
        catch (IllegalArgumentException e)
        {
            // e.printStackTrace();
            return Typeface.DEFAULT;
        }
    }

    public void setupLayoutTypefaces(View v)
    {
        try
        {
            if (v instanceof ViewGroup)
            {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++)
                {
                    View child = vg.getChildAt(i);
                    setupLayoutTypefaces(child);
                }
            }
            else if (v instanceof TextView)
            {
                ((TextView) v).setTypeface(getTypeface(v.getTag().toString()));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            // ignore
        }
    }
}

0

适用于Xamarin.Android:

类:

public class FontsOverride
{
    public static void SetDefaultFont(Context context, string staticTypefaceFieldName, string fontAssetName)
    {
        Typeface regular = Typeface.CreateFromAsset(context.Assets, fontAssetName);
        ReplaceFont(staticTypefaceFieldName, regular);
    }

    protected static void ReplaceFont(string staticTypefaceFieldName, Typeface newTypeface)
    {
        try
        {
            Field staticField = ((Java.Lang.Object)(newTypeface)).Class.GetDeclaredField(staticTypefaceFieldName);
            staticField.Accessible = true;
            staticField.Set(null, newTypeface);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

应用实施:

namespace SomeAndroidApplication
{
    [Application]
    public class App : Application
    {
        public App()
        {

        }

        public App(IntPtr handle, JniHandleOwnership transfer)
            : base(handle, transfer)
        {

        }

        public override void OnCreate()
        {
            base.OnCreate();

            FontsOverride.SetDefaultFont(this, "MONOSPACE", "fonts/Roboto-Light.ttf");
        }
    }
}

样式:

<style name="Theme.Storehouse" parent="Theme.Sherlock">
    <item name="android:typeface">monospace</item>
</style>

0

看起来Android O使得使用自定义字体变得容易,您基本上可以使用xml来实现这一点。我已附上Android官方文档的链接以供参考,希望这对仍需要此解决方案的人有所帮助。在Android中使用自定义字体


0

知道从Android 8.0(API级别26)开始可以使用XML中的自定义字体可能会很有用。

简而言之,您可以按照以下方式进行操作。

  1. 将字体放在文件夹中res/font

  2. 在小部件的属性中使用它

<Button android:fontFamily="@font/myfont"/>

或放进去 res/values/styles.xml

<style name="MyButton" parent="android:Widget.Button">
    <item name="android:fontFamily">@font/myfont</item>
</style>

并将其用作样式

<Button style="@style/MyButton"/>

0

直接在xml文件中使用“ fontPath”属性。

用于style.xml

<item name =“ fontPath”>字体/ProximaNovaSemibold.ttf </ item>

用于直接布局文件

fontPath =“ fonts / ProximaNovaBold.ttf”

(注意:无需在前缀中使用app / android属性)


-6

绝对有可能。有很多方法可以做到。最快的方法是使用try-catch方法创建条件。尝试您的特定字体样式条件,捕获错误并定义其他字体样式。


7
您可以提供一个演示来证明您的答案吗?
标记
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.