小智 109
对的,这是可能的.
您必须创建一个扩展文本视图的自定义视图.
在attrs.xml在values文件夹中:
<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>
Run Code Online (Sandbox Code Playgroud)
在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>
Run Code Online (Sandbox Code Playgroud)
在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);
}
}
Run Code Online (Sandbox Code Playgroud)
Com*_*are 80
有没有办法从XML中执行此操作?
不,对不起 您只能通过XML指定内置字体.
有没有办法从一个地方的代码中做到这一点,说整个应用程序和所有组件应该使用自定义字体而不是默认字体?
不是我知道的.
现在有很多种选择:
如果您使用Android SDK中的字体资源和反向移植 appcompat
那些不使用的第三方库appcompat虽然不是全部都支持在布局资源中定义字体
Per*_*den 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);
}
}
Run Code Online (Sandbox Code Playgroud)
有关更完整的示例,请参阅http://github.com/perchrh/FontOverrideExample
pos*_*spi 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
}
}
Run Code Online (Sandbox Code Playgroud)
在膨胀布局和Activity的onContentChanged()方法之后,您需要在视图上调用此函数.
M-W*_*eEh 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"));
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用支持包中的活动,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"));
}
}
Run Code Online (Sandbox Code Playgroud)
我还没有用Fragments 测试过这段代码,但希望它会起作用.
我FontUtils很简单也解决了此处提到的ICS前问题https://code.google.com/p/android/issues/detail?id=9904:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Inf*_*0re 10
嘿我在我的应用程序中还需要2种不同的字体用于不同的小部件!我用这种方式:
在我的Application类中,我创建了一个静态方法:
public static Typeface getTypeface(Context context, String typeface) {
if (mFont == null) {
mFont = Typeface.createFromAsset(context.getAssets(), typeface);
}
return mFont;
}
Run Code Online (Sandbox Code Playgroud)
String字体表示资产文件夹中的xyz.ttf.(我创建了一个常量类)现在你可以在你的应用程序中随处使用它:
mTextView = (TextView) findViewById(R.id.text_view);
mTextView.setTypeface(MyApplication.getTypeface(this, Constants.TYPEFACE_XY));
Run Code Online (Sandbox Code Playgroud)
唯一的问题是,对于要使用Font的每个小部件都需要这个!但我认为这是最好的方式.