【问题标题】:Add custom font for complete android application为完整的 android 应用程序添加自定义字体
【发布时间】:2011-10-19 01:39:09
【问题描述】:

在我的应用程序中,我需要对所有文本视图和编辑文本字段使用 helvetica 字体。除了对每个 textview 使用 settypeface 方法之外,还有什么方法可以做到这一点?任何建议都会有很大帮助。

提前致谢!

【问题讨论】:

标签: android textview custom-font


【解决方案1】:

我自己想通了。这是我使用的代码。我创建了自定义TextView,它具有自定义字体作为默认字体。

public class MyTextView extends TextView {

    public MyTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyTextView(Context context) {
        super(context);
        init();
    }

    private void init() {
        Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "font/chiller.ttf");
        setTypeface(tf ,1);

    }

}

【讨论】:

  • @mxg 你说的我没听懂
  • @mxg 通过覆盖 TextView 他能够在他的布局文件中使用 MyTextView 而无需在活动/片段中以编程方式执行任何操作来实现自定义字体。
  • 这里有一个很好的教程:barebonescoder.com/2010/05/…。如果您想考虑不同的字体系列类型,例如粗体或斜体,您将使用不同的 ttf 文件。您可以处理的方法是在 init 方法中请求 this.getTypeface().getStyle(),并为 textview 使用不同的字体。 HTH
  • 我在上面的链接上只能看到广告和相关链接,没有内容,只有广告
【解决方案2】:

在你的活动中,在你打电话之后

setContentView(R.id.blahblah);

您应该运行一个方法来遍历小部件的整个层次结构并处理字体替换,例如;

setContentView(R.id.blahblah);
Utils.overrideFonts(this, findViewById(android.R.id.content));

并且提到的“overrideFonts”方法应该是这样的;

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(FONT_REGULAR);
        }
    } catch (Exception e) {
        e.printStackTrace();
        // ignore
    }
}

在这个方案中,FONT_REGULAR 应该在某个安全的地方初始化,你可能会喜欢单例或其他方式来确保它被正确初始化......

private static void initializeFonts(final Context context) {
    FONT_REGULAR = Typeface.createFromAsset(context.getAssets(), "fonts/myfont_medium.otf");
    FONT_BOLD = Typeface.createFromAsset(context.getAssets(), "fonts/myfont_bold.otf");
}

如果您使用像 MyAppActivity(扩展 Activity)这样的 Activity 子类,那么您不需要为此类自定义更改每个 Activity 类。相反,您可以切入它并覆盖这样的行为;

public class MyAppActivity extends Activity {
... ...
    @Override
    public void setContentView(final int layoutResID) {
        super.setContentView(layoutResID);
        Utils.overrideFonts(this, findViewById(android.R.id.content));
    }
... ...
}

这样你就可以利用你的任何活动来产生共同的行为;

public class SettingsUI extends MyAppActivity {
... ...
} 

希望对你有帮助... 干杯!

【讨论】:

  • 这是简单布局的好解决方案。但是,如果您的活动中有一个 ListView,这将不起作用。 ListView 中的项是在 setContent 方法之后实例化的,因此列表中的 TextView 不会受此方法的影响
  • 你是对的,那些需要在...ItemAdapter类中处理
  • actionbar的字体呢?
  • 片段内的TextViews也不会修改它们的字体。
【解决方案3】:

创建一个样式并使用它的所有文本属性。

<style name="CustomText">
    <item name="android:typeface">YourFontName</item>
</style>

使用它:

<TextView style="@style/CustomText" />

以上是在所有活动中使用自定义字体进行自定义,您可以使用....

Typeface font = Typeface.createFromAsset(getAssets(), "CustomFontName.ttf");  
txt.setTypeface(font);

试试这个。

【讨论】:

  • android:typeface 字段只允许使用内置字体名称。如何分配资产文件夹中的自定义字体名称?
  • @hanry 您不能在 android:typeface 字段中使用自定义字体名称。您的答案的第二部分会起作用,但样式部分不会。
  • 这不能回答问题。 “除了对每个 textview 使用 settypeface 方法之外,还有什么方法可以做到这一点?”。
【解决方案4】:

要在所有应用程序中应用自定义字体,只需创建以下活动:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FontManager.getInstance().initialize(this, R.xml.fonts);
    setContentView(R.layout.main);
}
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    SimpleFactory factory = new SimpleFactory();
    return factory.onCreateView(name, context, attrs);
}

其中 FontManager 是管理 /xml/fonts.xml 中定义的所有字体的类,而 SimpleFactory 只是创建视图并将自定义字体应用于文本视图实例的每个视图的工厂。

/xml/fonts.xml

<?xml version="1.0" encoding="utf-8"?>
<familyset>
    <family>
        <nameset>
            <!--Font name-->
            <name>HelveticaNeueLTStd</name>
        </nameset>
        <fileset>
            <!--Font styles-->
            <file style="normal">fonts/HelveticaNeueLTStd-LtCn.otf</file>
            <file style="bold">fonts/HelveticaNeueLTStd-MdCn.otf</file>
            <file style="italic">fonts/HelveticaNeueLTStd-LtCnO.otf</file>
            <file style="bold_italic">fonts/HelveticaNeueLTStd-MdCnO.otf</file>
        </fileset>
    </family>
    <family>
        <!--There new font family can be added,
don't forget add font files into /assets/fonts directory and
put the name of the font into /values/string/font.xml-->
    </family>
</familyset>

FontFactory - 抽象类,只是扩展它来创建你自己的工厂

public abstract class FontFactory implements LayoutInflater.Factory{
    public final String TAG = getClass().getSimpleName();

    static final Class<?>[] mConstructorSignature = new Class[] {Context.class, AttributeSet.class};
    final Object[] mConstructorArgs = new Object[2];
    private static final String[] sClassPrefixList = {
            "android.widget.",
            "android.webkit."
    };

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        if("ViewStub".equals(name) || "View".equals(name)){
            return null;
        }
        View view = null;
        Constructor<? extends View> constructor = null;
        Class clazz = null;

        if (view == null) {
            if (-1 == name.indexOf('.')) {
                for (String prefix : sClassPrefixList) {
                    clazz = getClazz(prefix, name);
                    if(clazz != null){
                        break;
                    }
                }
            } else {
                clazz = getClazz("", name);
            }
        }

        if (clazz == null) {
            Log.d(TAG, "View can't be created " + name);
            return null;
        }

        try {
            constructor = clazz.getConstructor(mConstructorSignature);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        Object[] args = mConstructorArgs;
        args[1] = attrs;

        if(constructor == null){
            return null;
        }

        try {
                view = constructor.newInstance(context, attrs);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        if(view != null){
            onFontApply(context, view);
        }
        return view;
    }

    public abstract void onFontApply(Context context, View view);

    private Class getClazz(String prefix, String name){
        Class clazz = null;
        try {
            clazz = Class.forName(prefix + name);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            return clazz;
        }
    }
}

FontManager - 只需将 /xml/fonts.xml 中定义的字体文件映射到 /assets 目录中的字体文件,然后按字体系列名称和字体样式返回 TypeFace。

public void initialize(Context context, int resId) {
    if(mFonts != null){
        Log.d(TAG,"FontManager have already initialized");
        return;
    }
    XmlResourceParser parser = null;
    try {
        parser = context.getResources().getXml(resId);
        mFonts = new ArrayList<Font>();

        String tag;
        String fontStryleAttr = null;
        int eventType = parser.getEventType();

        Font font = null;

        do {
            tag = parser.getName();

            switch (eventType) {
                case XmlPullParser.START_TAG:
                    if (tag.equals(TAG_FAMILY)) {
                        // one of the font-families.
                        font = new Font();
                    } else if (tag.equals(TAG_NAMESET)) {
                        // a list of font-family names supported.
                        font.families = new ArrayList<String>();
                    } else if (tag.equals(TAG_NAME)) {
                        isName = true;
                    } else if (tag.equals(TAG_FILESET)) {
                        // a list of files specifying the different styles.
                        font.styles = new ArrayList<FontStyle>();
                    } else if (tag.equals(TAG_FILE)) {
                        isFile = true;
                        fontStryleAttr = parser.getAttributeValue(null, ATTR_STYLE);
                    }
                    break;

                case XmlPullParser.END_TAG:
                    if (tag.equals(TAG_FAMILY)) {
                        // add it to the list.
                        if (font != null) {
                            mFonts.add(font);
                            font = null;
                        }
                    } else if (tag.equals(TAG_NAME)) {
                        isName = false;
                    } else if (tag.equals(TAG_FILE)) {
                        isFile = false;
                        fontStryleAttr = null;
                    }
                    break;

                case XmlPullParser.TEXT:
                    String text = parser.getText();
                    if (isName) {
                        // value is a name, add it to list of family-names.
                        if (font.families != null)
                            font.families.add(text);
                    } else if (isFile) {
                        // value is a file, add it to the proper kind.
                        FontStyle fontStyle = new FontStyle();
                        fontStyle.font = Typeface.createFromAsset(context.getAssets(), text);
                        String attr = parser.getAttributeValue(null, ATTR_STYLE);
                        if (fontStryleAttr.equals(STYLE_BOLD))
                            fontStyle.style = Typeface.BOLD;
                        else if (fontStryleAttr.equals(STYLE_ITALIC))
                            fontStyle.style = Typeface.ITALIC;
                        else if (fontStryleAttr.equals(STYLE_BOLD_ITALIC))
                            fontStyle.style = Typeface.BOLD_ITALIC;
                        else
                            fontStyle.style = Typeface.NORMAL;
                        font.styles.add(fontStyle);
                    }
            }

            eventType = parser.next();

        } while (eventType != XmlPullParser.END_DOCUMENT);

    } catch (XmlPullParserException e) {
        throw new InflateException("Error inflating font XML", e);
    } catch (IOException e) {
        throw new InflateException("Error inflating font XML", e);
    } finally {
        if (parser != null)
            parser.close();
    }
}

public Typeface get(String family, int style) {
    for (Font font: mFonts) {
        for (String familyName : font.families) {
            if (familyName.equals(family)) {
                // if no style in specified, return normal style.
                if (style == -1)
                    style = Typeface.NORMAL;
                for (FontStyle fontStyle : font.styles) {
                    if (fontStyle.style == style)
                        return fontStyle.font;
                }
            }
        }
    }
    return mDefaultFont;
}

更多代码和示例请看here

【讨论】:

    【解决方案5】:

    好的,你可以做到,但你本质上想要做的是一个有点地图格式的字体图集(它必须以开始的 unicode 顺序运行!"#$% '()x+,-./)。该函数将做的是接收一个字符串并计算出每个对应字母在图集中的位置。

    这不太容易,但每个字符必须具有相同的长度和宽度,你可以有不同的长度,但这会困难得多。

    【讨论】:

      【解决方案6】:

      您可以在http://bit.ly/1bzjWQn使用 PixlUI

      在您的项目中导入他们的 .jar。在 XML 中使用它

       <com.neopixl.pixlui.components.textview.TextView
          android:id="@+id/textView1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/hello_world"
          pixlui:typeface="MyFont.ttf" />
      

      别忘了实现方案(xmlns:pixlui="http://schemas.android.com/apk/com.neopixl.pixlui")

      【讨论】:

      • 为什么我们需要添加一些 jar 来做我们完全可以用 Android 本身做的事情?
      • Android SDK 不能使用自定义字体
      【解决方案7】:
          setContentView(R.layout.activity_main);
          custfont(this, findViewById(android.R.id.content));
      
      
      
      private void custfont(final Context context, 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(), "fonts/ostrichblack.ttf"));
              }
          }
          catch (Exception e) 
          {
          }
      }
      

      【讨论】:

        【解决方案8】:
        import android.content.Context;
        import android.graphics.Typeface;
        
        /**
         * Created by Sanjeev Kumar on 4/18/2017.
         */
        
        public class FontManager {
            public Context mContext;
        
            public FontManager(Context context) {
                this.mContext = context;
            }
        
            public Typeface getSquarkiFont() {
                return Typeface.createFromAsset(mContext.getAssets(), "fonts/Squarki.ttf");
            }
        
            public Typeface getLazySpringDayFont() {
                return Typeface.createFromAsset(mContext.getAssets(), "fonts/LazySpringDay.ttf");
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-07-10
          • 1970-01-01
          • 2013-07-14
          • 2020-02-07
          • 1970-01-01
          • 2015-07-23
          • 2012-08-30
          • 2016-02-28
          • 1970-01-01
          相关资源
          最近更新 更多