我正在尝试在Android中使用XML文件定义GUI布局。据我所知,无法在XML文件中指定小部件应使用自定义字体(例如放置在assets / font /中的字体),您只能使用系统安装的字体。
我知道,在Java代码中,我可以使用唯一ID手动更改每个小部件的字体。或者,我可以在Java中迭代所有小部件以进行此更改,但这可能会非常慢。
我还有哪些选项?是否有更好的方法来制作具有自定义外观的小部件? 我不想为每个新添加的小部件手动更改字体。
我正在尝试在Android中使用XML文件定义GUI布局。据我所知,无法在XML文件中指定小部件应使用自定义字体(例如放置在assets / font /中的字体),您只能使用系统安装的字体。
我知道,在Java代码中,我可以使用唯一ID手动更改每个小部件的字体。或者,我可以在Java中迭代所有小部件以进行此更改,但这可能会非常慢。
我还有哪些选项?是否有更好的方法来制作具有自定义外观的小部件? 我不想为每个新添加的小部件手动更改字体。
TextView tv = (TextView) findViewById(R.id.textview1);
tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));
AppController.java
public class AppController extends Application {
@Override
public void onCreate() {
super.onCreate();
//Initial Font
FontsOverride.setDefaultFont(getApplicationContext(), "MONOSPACE", "fonts/iran_sans.ttf");
}
}
FontsOverride.java
public class FontsOverride {
public static void setDefaultFont(Context context, String staticTypefaceFieldName, String fontAssetName) {
final Typeface regular = Typeface.createFromAsset(context.getAssets(), fontAssetName);
replaceFont(staticTypefaceFieldName, regular);
}
private static void replaceFont(String staticTypefaceFieldName, final Typeface newTypeface) {
try {
final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
staticField.setAccessible(true);
staticField.set(null, newTypeface);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
方法2:使用setTypeface
对于特殊视图,只需调用setTypeface()更改字体。
CTextView.java
public class CTextView extends TextView {
public CTextView(Context context) {
super(context);
init(context,null);
}
public CTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context,attrs);
}
public void init(Context context, @Nullable AttributeSet attrs) {
if (isInEditMode())
return;
// use setTypeface for change font this view
setTypeface(FontUtils.getTypeface("fonts/iran_sans.ttf"));
}
}
FontUtils.java
public class FontUtils {
private static Hashtable<String, Typeface> fontCache = new Hashtable<>();
public static Typeface getTypeface(String fontName) {
Typeface tf = fontCache.get(fontName);
if (tf == null) {
try {
tf = Typeface.createFromAsset(AppController.getInstance().getApplicationContext().getAssets(), fontName);
} catch (Exception e) {
e.printStackTrace();
return null;
}
fontCache.put(fontName, tf);
}
return tf;
}
}
public class CustomTextView extends AppCompatTextView {
private int mFont = FontUtils.FONTS_NORMAL;
boolean fontApplied;
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, context);
}
public CustomTextView(Context context) {
super(context);
init(null, context);
}
protected void init(AttributeSet attrs, Context cxt) {
if (!fontApplied) {
if (attrs != null) {
mFont = attrs.getAttributeIntValue(
"http://schemas.android.com/apk/res-auto", "Lato-Regular.ttf",
-1);
}
Typeface typeface = getTypeface();
int typefaceStyle = Typeface.NORMAL;
if (typeface != null) {
typefaceStyle = typeface.getStyle();
}
if (mFont > FontUtils.FONTS) {
typefaceStyle = mFont;
}
FontUtils.applyFont(this, typefaceStyle);
fontApplied = true;
}
}
}
现在,每次自定义文本视图调用时,我们将从属性中获取int值:int fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1)
。
或者
我们还可以从我们在xml中设置的视图中获取getTypeface()(android:textStyle="bold|normal|italic"
)。所以你想做什么就做什么。
现在,我们制作了FontUtils
,以便将任何.ttf字体设置到我们的视图中。
public class FontUtils {
public static final int FONTS = 1;
public static final int FONTS_NORMAL = 2;
public static final int FONTS_BOLD = 3;
public static final int FONTS_BOLD1 = 4;
private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();
static Typeface getFonts(Context context, String name) {
Typeface typeface = TYPEFACE.get(name);
if (typeface == null) {
typeface = Typeface.createFromAsset(context.getAssets(), name);
TYPEFACE.put(name, typeface);
}
return typeface;
}
public static void applyFont(TextView tv, int typefaceStyle) {
Context cxt = tv.getContext();
Typeface typeface;
if(typefaceStyle == Typeface.BOLD_ITALIC) {
typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
}else if (typefaceStyle == Typeface.BOLD || typefaceStyle == SD_FONTS_BOLD|| typefaceStyle == FONTS_BOLD1) {
typeface = FontUtils.getFonts(cxt, "FaktPro-SemiBold.ttf");
} else if (typefaceStyle == Typeface.ITALIC) {
typeface = FontUtils.getFonts(cxt, "FaktPro-Thin.ttf");
} else {
typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
}
if (typeface != null) {
tv.setTypeface(typeface);
}
}
}
有一点需要注意,从Android 8.0(API级别26)开始,您可以在XML中使用自定义字体。
您可以按照以下方式将自定义字体应用于整个应用程序。
将字体放入文件夹res/font
中。
在res/values/styles.xml
中,在应用程序主题中使用它。
<style name="AppTheme" parent="{任何你喜欢的}">
<item name="android:fontFamily">@font/myfont</item>
</style>
这里有一个教程,向您展示如何设置自定义字体,就像@peter所描述的那样:http://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html
它还考虑了可能存在的内存泄漏问题,例如http://code.google.com/p/android/issues/detail?id=9904。此外,在教程中还有一个在按钮上设置自定义字体的示例。
你不能扩展TextView来创建小部件或在小部件布局中使用它: http://developer.android.com/guide/topics/appwidgets/index.html