自定义字体和 XML 布局 (Android)

发布于 2024-08-24 12:40:46 字数 272 浏览 5 评论 0原文

我正在尝试在 Android 中使用 XML 文件定义 GUI 布局。据我所知,没有办法指定您的小部件应该在 XML 文件中使用自定义字体(例如您放置在 asset/font/ 中的字体),并且您只能使用系统安装的字体。

我知道,在 Java 代码中,我可以使用唯一的 ID 手动更改每个小部件的字体。或者,我可以迭代 Java 中的所有小部件来进行此更改,但这可能会非常慢。

我还有什么其他选择?有没有更好的方法来制作具有自定义外观的小部件?我并不特别希望必须手动更改我添加的每个新小部件的字体。

I'm trying to define a GUI layout using XML files in Android. As far as I can find out, there is no way to specify that your widgets should use a custom font (e.g. one you've placed in assets/font/) in XML files and you can only use the system installed fonts.

I know that, in the Java code, I could change the font of each widget manually using unique IDs. Alternatively, I could iterate over all the widgets in Java to make this change, but this would probably be very slow.

What other options do I have? Is there any better ways to making widgets that have a custom look? I don't particularly want to have to manually change the font for every new widget I add.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

只有一腔孤勇 2024-08-31 12:40:46

您可以扩展 TextView 来设置自定义字体,正如我此处。

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/values 中)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TextViewPlus">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

ma​​in.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”放入 < em>assets 文件夹。

更新 8/1/13

此方法存在严重的内存问题。请参阅下面的 chedabob 的评论

You can extend TextView to set custom fonts as I learned 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: (in res/values)

<?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>

You would put "saxmono.ttf" in the assets folder.

UPDATE 8/1/13

There are serious memory concerns with this method. See chedabob's comment below.

碍人泪离人颜 2024-08-31 12:40:46

我迟到了 3 年:( 不过,这对于可能偶然发现这篇文章的人来说可能很有用。

我编写了一个缓存字体的库,还允许您直接从 XML 指定自定义字体。您可以找到库此处

是您使用 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" />

I'm 3 years late for the party :( However this could be useful for someone who might stumble upon this post.

I've written a library that caches Typefaces and also allow you to specify custom typefaces right from XML. You can find the library here.

Here is how your XML layout would look like, when you use it.

<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" />
戏蝶舞 2024-08-31 12:40:46

这可能有点晚了,但您需要创建一个返回自定义字体的单例类以避免内存泄漏。

TypeFace 类:

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());

This might be a little late, but you need to create a singleton class that returns the custom typeface to avoid memory leaks.

TypeFace class:

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;
}
}

Custom 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());
    }

}

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

Programmatically:

TextView programmaticallyTextView = (TextView) 
       findViewById(R.id.programmatically_text_view);

programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
                .getTypeFace());
递刀给你 2024-08-31 12:40:46

老问题,但我确实希望在开始自己寻找一个好的解决方案之前先在这里阅读这个答案。 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"/>

要激活它,您唯一要做的就是将其附加到您正在使用的 Activity 的上下文:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(new CalligraphyContextWrapper(newBase));
}

您还可以指定自己的自定义属性来替换 android:fontFamily

它也适用于主题,包括 AppTheme。

Old question, but I sure wish I read this answer here before I started my own search for a good solution. Calligraphy extends the android:fontFamily attribute to add support for custom fonts in your asset folder, like so:

<TextView 
  android:text="@string/hello_world"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:fontFamily="fonts/Roboto-Bold.ttf"/>

The only thing you have to do to activate it is attaching it to the Context of the Activity you're using:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(new CalligraphyContextWrapper(newBase));
}

You can also specify your own custom attribute to replace android:fontFamily

It also works in themes, including the AppTheme.

邮友 2024-08-31 12:40:46

使用DataBinding

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

Using DataBinding :

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName){
 textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

In XML:

<TextView
app:font="@{`Source-Sans-Pro-Regular.ttf`}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

font file must be in assets/fonts/

牵强ㄟ 2024-08-31 12:40:46

如果您只想添加一种字体,并且希望编写更少的代码,则可以为您的特定字体创建专用的 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="" />

If you only have one typeface you would like to add, and want less code to write, you can create a dedicated TextView for your specific font. See code below.

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);
    }
}

In main.xml, you can now add your textView like this:

<com.yourpackage.FontTextView
    android:id="@+id/tvTimer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="" />
甜中书 2024-08-31 12:40:46

从 Android O 预览版开始,最好的方法是这样
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"**/>

如文档所示

使用字体

所有步骤都是正确的。

The best way to do it From Android O preview release is this way
1.)Right-click the res folder and go to New > Android resource directory. The New
Resource Directory window appears.
2.)In the Resource type list, select font, and then click OK.
3.)Add your font files in the font folder.The folder structure below generates R.font.dancing_script, R.font.la_la, and R.font.ba_ba.
4.)Double-click a font file to preview the file's fonts in the editor.

Next we must create a font family

1.)Right-click the font folder and go to New > Font resource file. The New Resource File window appears.
2.)Enter the file name, and then click OK. The new font resource XML opens in the editor.
3.)Enclose each font file, style, and weight attribute in the font tag element. The following XML illustrates adding font-related attributes in the font resource 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>

Adding fonts to a TextView:

   <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    **android:fontFamily="@font/ba_ba"**/>

As from the documentation

Working With Fonts

all the steps are correct.

蹲在坟头点根烟 2024-08-31 12:40:46

扩展 TextView 并给它一个自定义属性,或者仅使用 android:tag 属性传入您要使用的字体的字符串。您需要选择一个约定并遵守它,例如我将把所有字体放在 res/assets/fonts/ 文件夹中,以便您的 TextView 类知道在哪里找到它们。然后在构造函数中,您只需在超级调用后手动设置字体即可。

Extend TextView and give it a custom attribute or just use the android:tag attribute to pass in a String of what font you want to use. You will need to pick a convention and stick to it such as I will put all of my fonts in the res/assets/fonts/ folder so your TextView class knows where to find them. Then in your constructor you just set the font manually after the super call.

世态炎凉 2024-08-31 12:40:46

使用自定义字体的唯一方法是通过源代码。

请记住,Android 运行在资源非常有限的设备上,并且字体可能需要大量 RAM。内置的 Droid 字体是专门制作的,如果您注意到的话,会缺少许多字符和装饰。

The only way to use custom fonts is through the source code.

Just remember that Android runs on devices with very limited resources and fonts might require a good amount of RAM. The built-in Droid fonts are specially made and, if you note, have many characters and decorations missing.

や莫失莫忘 2024-08-31 12:40:46

我可能会对这个问题有一个简单的答案,而无需扩展 TextView 并实现长代码。

代码:

 TextView tv = (TextView) findViewById(R.id.textview1);
    tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));

像往常一样将自定义字体文件放入资产文件夹中并尝试此操作。这对我有用。
我只是不明白为什么彼得为这个简单的事情给出了这么大的代码,或者他在旧版本中给出了答案。

I might have a simple answer for the question without extending the TextView and implementing a long code.

Code :

 TextView tv = (TextView) findViewById(R.id.textview1);
    tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));

Place the custom font file in assets folder as usual and try this. It works for me.
I just dont understand why peter has given such a huge code for this simple thing or he has given his answer in old version.

甲如呢乙后呢 2024-08-31 12:40:46

也可以在 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 中该文件夹与 ressrc 位于同一级别,在我的例子中是 assets/fonts/ionicons.ttf

< strong>更新了添加了根布局,因为此方法需要xmlns:app="http://schemas.android.com/apk/res-auto"才能工作

更新2< /strong> 忘记了我之前安装的一个名为 Calligraphy 的库

Also can be defined in the xml without creating custom classes

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>

A quick note, because I just always forgot where to put the fonts, its that the font must be inside assets and this folder resides in the same level that res and src, in my case its assets/fonts/ionicons.ttf

Updated Added root layout because this method needs xmlns:app="http://schemas.android.com/apk/res-auto" to work

Update 2 Forgot about a library that I've installed before called Calligraphy

心房敞 2024-08-31 12:40:46

Peter 的答案是最好的,但可以通过使用 Android 中的 styles.xml 为应用程序中的所有文本视图自定义字体来改进它。

我的代码是 这里

Peter's answer is the best, but it can be improved by using the styles.xml from Android to customize your fonts for all textviews in your app.

My code is here

三生一梦 2024-08-31 12:40:46

自定义字体有两种方法:

!!!我的自定义字体位于 asset/fonts/iran_sans.ttf

方式 1 :
反射 Typeface.class ||| 最好的方法

在继承Application的类中调用FontsOverride.setDefaultFont(),此代码将导致所有软件字体发生变化,甚至Toasts字体

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;
    }

}

There are two ways to customize fonts :

!!! my custom font in assets/fonts/iran_sans.ttf

Way 1 :
Refrection Typeface.class ||| best way

call FontsOverride.setDefaultFont() in class extends Application, This code will cause all software fonts to be changed, even Toasts fonts

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();
        }
    }
}

Way 2: use setTypeface

for special view just call setTypeface() to change font.

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;
    }

}
香橙ぽ 2024-08-31 12:40:46

这是一个教程,向您展示如何设置像 @peter 描述的自定义字体: http://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html

它还考虑了潜在的内存泄漏 http://code.google.com/p/android/issues/detail?id=9904 。本教程中还提供了在按钮上设置自定义字体的示例。

Here's a tutorial that shows you how to setup a custom font like @peter described: http://responsiveandroid.com/2012/03/15/custom-fonts-in-android-widgets.html

it also has consideration for potential memory leaks ala http://code.google.com/p/android/issues/detail?id=9904 . Also in the tutorial is an example for setting a custom font on a button.

风启觞 2024-08-31 12:40:46

您可以轻松创建自定义 textview 类:-

因此,您首先需要做的是,创建使用 AppCompatTextView 扩展的 Custom textview 类。

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);
        }
    }
}

You can make easily custom textview class :-

So what you need to do first, make Custom textview class which extended with 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;
        }
    }
}

Now , every time Custom text view call and we will get int value from attribute int fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1).

Or

We can also get getTypeface() from view which we set in our xml (android:textStyle="bold|normal|italic"). So do what ever you want to do.

Now, we make FontUtils for set any .ttf font into our view.

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);
        }
    }
}
百善笑为先 2024-08-31 12:40:46

了解从 Android 8.0(API 级别 26)开始,您可以 在 XML 中使用自定义字体

您可以通过以下方式将自定义字体应用于整个应用程序。

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

  2. res/values/styles.xml中在应用程序主题中使用它。
    <代码>

It may be useful to know that starting from Android 8.0 (API level 26) you can use a custom font in XML.

You can apply a custom font to the entire application in the following way.

  1. Put the font in the folder res/font.

  2. In res/values/styles.xml use it in the application theme.

    <style name="AppTheme" parent="{whatever you like}">
    <item name="android:fontFamily">@font/myfont</item>
    </style>

倚栏听风 2024-08-31 12:40:46

Fontinator 是一个 Android 库,可以轻松使用自定义字体。
https://github.com/svendvd/Fontinator

Fontinator is an Android-Library make it easy, to use custom Fonts.
https://github.com/svendvd/Fontinator

如若梦似彩虹 2024-08-31 12:40:46

您无法扩展 TextView 来创建小部件或在小部件布局中使用小部件:
http://developer.android.com/guide/topics/appwidgets/index.html

You can't extend TextView to create a widget or use one in a widgets layout:
http://developer.android.com/guide/topics/appwidgets/index.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文