Как настроить пользовательский шрифт в AlertDialog с помощью библиотеки поддержки 26

Я использую версию 26.0.1 Android Support Library для установки пользовательских шрифтов в моем приложении. В моей теме приложения я добавил:

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

Он работал как шарм, преобразовывая текст в моем приложении в мой собственный шрифт. ЗА ИСКЛЮЧЕНИЕМ для моих диалогов - в частности, их заголовки, сообщения, а также их NumberPickers. В этих местах шрифты не обновлялись. (Радио кнопки и флажки работали, а также кнопки да/нет)

Есть ли что-то, что я забываю добавить к моим темам или стилям? Или это еще не поддерживается библиотекой поддержки?

Немного подробней: я использую AppCompatDialogFragment для реализации всех моих диалогов. В своих методах onCreateDialog() я создаю диалог с помощью AlertDialog.Builder, а затем возвращаю его.

Спасибо за помощь!

Ответ 1

Спасибо всем, кто ответил, но, к сожалению, ни один из этих решений не работал у меня. Надеюсь, они будут работать для кого-то другого.

Я пришел к выводу, что это ошибка в библиотеке поддержки, и, надеюсь, Google исправит. Тем временем я разработал этот хакерский способ:

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

Это работает путем сканирования дерева диалогового окна для заголовков и представлений сообщений по идентификаторам, которые им предоставляет библиотека поддержки. Если библиотека поддержки должна была изменить эти идентификаторы, это больше не будет работать (и именно поэтому она взламывает). Надеюсь, Google исправляет эту проблему, и мне больше не нужно будет этого делать.

Ответ 2

Я нашел способ, который требует только однострочного изменения кода Java каждый раз, когда вы создаете AlertDialog.

Шаг 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() в своем застройщике)

Ответ 3

При создании диалогового построителя следует использовать 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);

Ответ 4

Возможно, дело не в этом, у меня была похожая проблема, и я обнаружил, что fontFamily не будет подвержен AsyncLayoutInflater. Это также имеет место, если AlertDialog вложен в AsyncLayoutInflater. Мне пришлось конвертировать в обычный инфлятор, чтобы показать собственный шрифт. Например,

Это не показывало fontFamily вызываемый из TextView 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");
        }
});

Это показывало, что fontFamily из TextView 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");

Ответ 5

Вы можете использовать пользовательский 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); 

Ответ 6

вы можете раздуть пользовательский макет в своем диалоге следующим образом:

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