如何使用支持库 26 在 AlertDialog 中设置自定义字体

How do I set a custom font in an AlertDialog using Support Library 26

我正在使用 Android Support Library 的修订版 26.0.1 在我的应用程序中设置自定义字体。在我的应用主题中,我添加了:

<item name="android:fontFamily">@font/my_font</item>

它就像一个魅力,将我整个应用程序中的文本转换为我的自定义字体。除了我的对话——特别是他们的标题、消息,还有他们的 NumberPickers。在那些地方,字体没有更新。 (单选按钮和复选框有效;yes/no 按钮也有效)

是否有什么我忘记添加到我的主题或样式中的东西?或者这只是支持库还不支持?

更详细一点:我正在使用 AppCompatDialogFragment 来实现我所有的对话框。在他们的 onCreateDialog() 方法中,我使用 AlertDialog.Builder 然后 return 创建了一个对话框。

感谢您的帮助!

您可以使用自定义 Alert Dialog 并使用 Typeface 设置字体。看看下面的代码片段。

 AlertDialog dg = new AlertDialog.Builder(this).setMessage("Your Message").show();
 TextView tv = (TextView) dg.findViewById(android.R.id.message); // Your TextView of custom Alert Dialog
 Typeface fc=Typeface.createFromAsset(getAssets(),"fonts/FONT"); // This is your font file name.
 tv.setTypeface(fc); 

您可以像这样在对话框中扩充自定义布局:

final android.support.v7.app.AlertDialog.Builder alertDialogBuilder = new android.support.v7.app.AlertDialog.Builder(context,
R.style.LimitAlertDialogStyle);
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View alertLayout = layoutInflater.inflate(R.layout.date_layout, null);
TextView tv= (TextView) alertLayout.findViewById(R.id.tv);

Typeface fc=Typeface.createFromAsset(getAssets(),"fonts/FONT"); 
tv.setTypeface(fc); 

您应该在创建对话框生成器时使用 ContextThemeWrapper。像这样

ContextThemeWrapper wrappedContext = new ContextThemeWrapper(context, R.style.mystyle); 
AlertDialog.Builder builder = new AlertDialog.Builder(wrappedContext);

如果您仅支持 SDK 11 及更高版本,您可能需要使用

ContextThemeWrapper wrappedContext = new ContextThemeWrapper(context, R.style.mystyle); 
AlertDialog.Builder builder = new AlertDialog.Builder(wrappedContext, R.style.mystyle);

谢谢所有回答的人,但不幸的是 none 这些解决方案对我有用。我希望他们能为别人工作。

我断定这是支持库中的错误,希望 Google 能够修复。同时,我开发了这个 hacky 解决方法:

public static void applyCustomFontToDialog(Context context, Dialog dialog) {
    Typeface font = ResourcesCompat.getFont(context, R.font.my_font);
    if (font != null) {
        TextView titleView = dialog.findViewById(android.support.v7.appcompat.R.id.alertTitle);
        TextView messageView = dialog.findViewById(android.R.id.message);
        if (titleView != null) titleView.setTypeface(font, Typeface.BOLD);
        if (messageView != null) messageView.setTypeface(font);
    }
}

这是通过扫描对话框的视图树来根据支持库提供的标题和消息视图来工作的。如果支持库要更改这些 ID,这将不再有效(这就是为什么它是 hacky 的原因)。希望 Google 解决了这个问题,我再也不需要这样做了。

我找到了一种方法,每次创建 AlertDialog 时只需要 one-line 更改为 Java 代码。

步骤 1

创建一个包含具有正确字体集的 TextView 的自定义、可重复使用的布局。称之为 alert_dialog.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/SomeStyleWithDesiredFont"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/spacing_2x" />

步骤 2

在某个地方创建一个可重复使用的辅助函数,它会膨胀此布局并将文本设置为您想要的字符串

public static TextView createMessageView(String message, Context context) {
    TextView messageView = (TextView) LayoutInflater.from(context).inflate(R.layout.alert_dialog, null, false);
    messageView.setText(message);
    return messageView;
}

步骤 3

在代码的每个 AlertDialog.Builder 链中,替换此行:

.setMessage(messageString)

这一行:

.setView(createMessageView(messageString, context))

(请注意,同样的方法也适用于标题 TextView。您可以通过在构建器中调用 setCustomTitle() 来为标题应用自定义视图)

也许这里不是这种情况,我遇到了类似的问题,发现使用 AsyncLayoutInflater 不会对 fontFamily 造成影响。如果 AlertDialog 嵌套在 AsyncLayoutInflater 中,情况也是如此。为了显示自定义字体,我不得不转换为传统布局充气器。例如,

这没有显示 fontFamilyTextView XML 调用。

AsyncLayoutInflater inflater =new AsyncLayoutInflater(activity);
    inflater.inflate(R.layout.dialog, null, new AsyncLayoutInflater.OnInflateFinishedListener() {
        @Override
        public void onInflateFinished(@NonNull View view, int resid, ViewGroup parent) {
            final TextView tv = view.findViewById(R.id.textview);
            tv.setText("Text with custom fontFamily called in XML, but won't work");
        }
});

这确实显示 fontFamilyTextView XML 调用。

final ViewGroup nullParent = null;
final View view = activity.getLayoutInflater().inflate(R.layout.dialog, nullParent);
final TextView tv= view.findViewById(R.id.textview);
tv.setText("Text with custom fontFamily called in XML, and will work");