自定义字体和XML布局(Android)
我想在Android中使用XML文件来定义GUI布局。据我所知,无法指定您的小部件应该使用XML文件中的自定义字体(例如,您放置在assets/font /中的字体),并且只能使用系统安装的字体。自定义字体和XML布局(Android)
我知道,在Java代码中,我可以使用唯一ID手动更改每个小部件的字体。或者,我可以遍历Java中的所有小部件来进行此更改,但这可能会很慢。
我还有其他选择吗?有没有更好的方法来制作具有自定义外观的小部件?我不是特别想要手动更改我添加的每个新小部件的字体。
使用自定义字体的唯一方法是通过源代码。
请记住,Android运行在资源非常有限且字体可能需要大量内存的设备上。内置的Droid字体是专门制作的,如果您注意,缺少许多字符和装饰。
“只要记住的Android设备上运行的资源非常有限” - >这是越来越少而不是这种情况。四核手机?真?? – Sandy 2012-08-10 03:33:10
我会更多地考虑tareqHs答案的背景,这在你的评论中早于2年半。 – SK9 2012-12-18 12:45:13
当你在2010年编写答案时,你的回应的第一部分可能是真实的。后者是超能力的,并且在这一点上:Droid很糟糕,在2012年被Google弃用而转向Roboto。 Android中缺少印刷术的选择是一个缺陷,而不是一个特征;按照今天的标准,iOS自2008年以来已经在原始设备下为开发者提供了多种字体。 – cosmix 2013-10-03 14:50:19
延伸TextView
并给它一个自定义属性,或者只是使用android:tag属性传递一个你想要使用什么字体的字符串。您需要选择一个约定并坚持下去,例如我将所有字体都放在res/assets/fonts /文件夹中,以便您的TextView类知道在哪里找到它们。然后在你的构造函数中,你只需在超级调用之后手动设置字体。
查看peter的答案,获取完整代码示例。 – Intrications 2011-08-26 10:57:49
不能扩展的TextView创建一个小部件或在部件布局中使用一个: http://developer.android.com/guide/topics/appwidgets/index.html
我想你可以。 – 2011-12-16 10:05:12
阿哈 - 着名的“小部件”这个词的双重用途再次袭击! – 2012-08-23 09:01:31
可以扩展TextView中设置自定义字体作为我学到here。
TextViewPlus.java:
package com.example;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
public class TextViewPlus extends TextView {
private static final String TAG = "TextView";
public TextViewPlus(Context context) {
super(context);
}
public TextViewPlus(Context context, AttributeSet attrs) {
super(context, attrs);
setCustomFont(context, attrs);
}
public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
String customFont = a.getString(R.styleable.TextViewPlus_customFont);
setCustomFont(ctx, customFont);
a.recycle();
}
public boolean setCustomFont(Context ctx, String asset) {
Typeface tf = null;
try {
tf = Typeface.createFromAsset(ctx.getAssets(), asset);
} catch (Exception e) {
Log.e(TAG, "Could not get typeface: "+e.getMessage());
return false;
}
setTypeface(tf);
return true;
}
}
attrs.xml:(在res /值)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TextViewPlus">
<attr name="customFont" format="string"/>
</declare-styleable>
</resources>
main.xml中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res/com.example"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.TextViewPlus
android:id="@+id/textViewPlus1"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:text="@string/showingOffTheNewTypeface"
foo:customFont="saxmono.ttf">
</com.example.TextViewPlus>
</LinearLayout>
您会将“saxmono.ttf”放入资产文件夹中。
UPDATE 13年8月1日
有严重的内存关切此方法。请参阅下面的chedabob's comment。
非常好。感谢代码。 – Intrications 2011-08-26 10:56:37
这看起来不错,但是,当我尝试在main.xml中使用“TextViewPlus”时出现错误。我得到如下: - 错误:错误解析XML:绑定前缀 - 前缀“富”的属性为“foo:CustomFont的”与元素类型“supportLibs.TextViewPlus”相关的不 \t界。 – Majjoodi 2011-11-17 15:11:33
有一点需要注意的是,这将产生几十个和几十个TypeFace对象并吃掉内存。 4.0之前版本的Android中存在一个缺陷,无法正确释放TypeFaces。最简单的做法是用HashMap创建一个TypeFace缓存。这使我的应用程序的内存使用量从120+ mb降至18mb。 http://code.google.com/p/android/issues/detail?id=9904 – chedabob 2012-01-24 14:20:29
这里有一个教程,显示你喜欢@peter自定义字体如何设置描述:http://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html
它也有考虑潜在的内存泄漏阿拉http://code.google.com/p/android/issues/detail?id=9904。在教程中还有一个用于在按钮上设置自定义字体的示例。
如果您只想添加一种字体,并且想要编写较少的代码,则可以为您的特定字体创建专用的TextView。见下面的代码。
package com.yourpackage;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class FontTextView extends TextView {
public static Typeface FONT_NAME;
public FontTextView(Context context) {
super(context);
if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
this.setTypeface(FONT_NAME);
}
public FontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
this.setTypeface(FONT_NAME);
}
public FontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
this.setTypeface(FONT_NAME);
}
}
main.xml中,您现在可以为自己的TextView这样的:
<com.yourpackage.FontTextView
android:id="@+id/tvTimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
这可能是晚了一点,但你需要创建一个返回自定义字体,以避免内存泄漏一个单独的类。
字体类:
public class OpenSans {
private static OpenSans instance;
private static Typeface typeface;
public static OpenSans getInstance(Context context) {
synchronized (OpenSans.class) {
if (instance == null) {
instance = new OpenSans();
typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf");
}
return instance;
}
}
public Typeface getTypeFace() {
return typeface;
}
}
自定义的TextView:
public class NativelyCustomTextView extends TextView {
public NativelyCustomTextView(Context context) {
super(context);
setTypeface(OpenSans.getInstance(context).getTypeFace());
}
public NativelyCustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setTypeface(OpenSans.getInstance(context).getTypeFace());
}
public NativelyCustomTextView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
setTypeface(OpenSans.getInstance(context).getTypeFace());
}
}
通过XML:
<com.yourpackage.views.NativelyCustomTextView
android:id="@+id/natively_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="20dp"
android:text="@string/natively"
android:textSize="30sp" />
编程:
TextView programmaticallyTextView = (TextView)
findViewById(R.id.programmatically_text_view);
programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
.getTypeFace());
似乎在运行时工作,但它应该在设计器中工作? – 2013-05-05 13:50:32
当然。你可以使用xml。 @Magnus – 2013-05-05 22:32:49
我想你误解了,它似乎并没有在_Design_时间(设计器预览)中工作。 (xml!=设计师)。它在编译到运行时的Xml布局文件中指定工作正常。无论如何,我使用这个扩展https://github.com/danh32/Fontify,它对我的需求更好(它支持多种字体样式,常规,粗体等,以及不同的字体名称以及其他控件超越TextView) – 2013-05-06 11:25:39
我对派对迟了3年:(但这可能会对可能会偶然发现此帖的人有用。
我已经写了一个缓存字体的库,并允许您从XML中指定自定义字体。你可以找到图书馆here。
这是您的XML布局在使用时的样子。
<com.mobsandgeeks.ui.TypefaceTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
geekui:customTypeface="fonts/custom_font.ttf" />
我可能没有扩展TextView和实现一个长代码的问题有一个简单的答案。
代码:
TextView tv = (TextView) findViewById(R.id.textview1);
tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));
将资产文件夹像往常一样自定义字体文件,试试这个。这个对我有用。 我只是不明白为什么彼得为这个简单的事情给了这么大的代码,或者他在旧版本中给出了他的答案。
老问题,但我确实希望我在这里阅读这个答案之前,我开始自己的搜索一个很好的解决方案。 Calligraphy扩展android:fontFamily
属性添加支持自定义字体,在您的资源文件夹,例如:
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="fonts/Roboto-Bold.ttf"/>
你必须做激活它是将其连接到您正在使用的活动方面唯一:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(new CalligraphyContextWrapper(newBase));
}
您还可以指定自己的自定义属性替换android:fontFamily
它也适用于主题,包括AppTheme。
使用数据绑定:
@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"/>
字体文件必须在assets/fonts/
我会在那里放置代码? – 707 2016-03-28 09:57:36
还可以在XML来定义,而无需创建自定义类
style.xml
<style name="ionicons" parent="android:TextAppearance">
<!-- Custom Attr-->
<item name="fontPath">fonts/ionicons.ttf</item>
</style>
activity_main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/ionicons"
android:text=""/>
</LinearLayout>
快速注意,因为我刚才一直忘了放在哪里的字体,它的字体必须是内assets
这个文件夹所在在同级别res
和src
,在我的情况下,它assets/fonts/ionicons.ttf
更新加根布局,因为这种方法需要xmlns:app="http://schemas.android.com/apk/res-auto"
工作
更新2忘了,我已经安装之前调用Calligraphy
做到这一点从Android的Ø预览版的最佳方法库是这样
1.)右键单击res文件夹并转至新建> Android资源目录。将出现新的
资源目录窗口。
2.)在资源类型列表中,选择字体,然后单击确定。
3.)将字体文件添加到字体文件夹。下面的文件夹结构生成R.font.dancing_script,R.font.la_la和R.font.ba_ba。
4.)双击字体文件在编辑器中预览文件的字体。
接下来,我们必须创建一个字体家族
1)右键单击字体文件夹,然后转到新建>字体资源文件。出现新资源文件窗口。
2.)输入文件名,然后点击确定。新的字体资源XML在编辑器中打开。
3.)在字体标签元素中包含每个字体文件,样式和重量属性。下面的XML说明了在字体资源XML添加字体相关的属性:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<font
android:fontStyle="normal"
android:fontWeight="400"
android:font="@font/hey_regular" />
<font
android:fontStyle="italic"
android:fontWeight="400"
android:font="@font/hey_bababa" />
</font-family>
添加字体到一个TextView:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
**android:fontFamily="@font/ba_ba"**/>
由于从文档
所有步骤都正确。
有两种自定义字体的方法:
!!!我的自定义字体资产/字体/ iran_sans.ttf
方式1: Refrection Typeface.class ||| 最好的办法
调用FontsOverride.setDefaultFont()在类扩展应用程序,此代码将导致所有软件字体被改变,甚至敬酒字体
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;
}
}
您可以轻松地自定义的TextView类: -
所以,你首先需要做什么,使Custom textview
班,其中扩展AppCompatTextView
。现在
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 fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1)
得到int值。
或者
我们还可以从视图,我们在我们的XML(android:textStyle="bold|normal|italic"
)设定得getTypeface()。所以做你想做的事。
现在,我们制作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);
}
}
}
DrDefrost - 请接受一些答案,您将在本网站上获得更多回复。 – SK9 2011-09-03 01:52:18
另外还有一个类似的问题:http://*.com/questions/9030204/how-to-use-custom-font-in-android-xml – Vins 2013-05-16 13:12:10
更新05/2017:“支持库26.0测试版提供支助运行Android API版本14和更高版本的设备上的XML字体。“请参阅:https://developer.android.com/preview/features/fonts-in-xml.html#using-support-lib – 2017-05-23 14:12:06