简体   繁体   中英

How to set custom font for alert dialog in android?

In my android application an alert dialog appears after clicking on a button. I want to set custom font for the alert. I searched the web and found some tutorials and questions about this subject, but none of them works for me.

How can I change the font?

Thanks

To do this you use alert builder to build your alert. You then get the TextView from this alert and then you set the typeface for the alert.

AlertDialog dialog = new AlertDialog.Builder(this).setMessage("Hello world").show();
TextView textView = (TextView) dialog.findViewById(android.R.id.message);
Typeface face=Typeface.createFromAsset(getAssets(),"fonts/FONT"); 
textView.setTypeface(face); 

The above answers didnt work for me.

I used the following approach

// Initializing the alertDialog
AlertDialog alertDialog = new AlertDialog.Builder(QuizActivity.this).create();
alertDialog.setTitle("Warning");
alertDialog.setMessage("Are you sure you want to exit?");
alertDialog.show(); // This should be called before looking up for elements


// Getting the view elements
TextView textView = (TextView) alertDialog.getWindow().findViewById(android.R.id.message);
TextView alertTitle = (TextView) alertDialog.getWindow().findViewById(R.id.alertTitle);
Button button1 = (Button) alertDialog.getWindow().findViewById(android.R.id.button1);
Button button2 = (Button) alertDialog.getWindow().findViewById(android.R.id.button2);

// Setting font
textView.setTypeface(FontHelper.getFont(Fonts.MULI_REGULAR));
alertTitle.setTypeface(FontHelper.getFont(Fonts.MULI_REGULAR));
button1.setTypeface(FontHelper.getFont(Fonts.MULI_BOLD));
button2.setTypeface(FontHelper.getFont(Fonts.MULI_BOLD));

Tested on 7.1.1

NOTE: Make sure you get the element after showing the dialog . Without this you will get NullPointerException

I know this is an old question, but I leave this here for those still searching for a solution.

If you only want to change text format, you can just override alertDialogTheme attribute to change the theme for the AlertDialog .

Example, using the Application theme :

<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <!-- This will override the Alert Dialog theme -->
    <item name="alertDialogTheme">@style/MyAlertDialogTheme</item>
</style>

<style name="MyAlertDialogTheme" parent="@android:style/Theme.Material.Light.Dialog.Alert">
    <item name="android:textAppearanceSmall">@style/MyTextAppearanceSmall</item>
    <item name="android:textAppearanceMedium">@style/MyTextAppearanceMedium</item>
    <item name="android:textAppearanceLarge">@style/MyTextAppearanceLarge</item>
</style>

<style name="MyTextAppearance" parent="TextAppearance.AppCompat">
    <item name="android:fontFamily">@font/comic_sans</item>
</style>
(...)

If I'm not mistaken android:textAppearanceSmall is used for the message and the android:textAppearanceMedium for the title. But you can pick whatever you want and remove the rest.

Another option

Without overriding the alertDialogTheme , is by setting the style via the builder constructor. Example: AlertDialog.Builder(getActivity(), R.style.MyAlertDialogTheme)

If you are using Material Components , you can customize your diaog to nearly all of needs by declearing a style for it. For example, custom style I created for my dialog:

    <style name="ThemeOverlay.App.MaterialAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
        <item name="materialAlertDialogTitleTextStyle"><!--here goes your title text style --></item>
        <item name="materialAlertDialogBodyTextStyle"><!--here goes your message text style --></item>
        <item name="colorPrimary"><!--here goes your dialog primary color. e.g. button text color, etc.--></item>
        <item name="shapeAppearanceOverlay">@style/ShapeAppearance.App.SmallComponent</item> <!-- your custom shape appearance for your dialog. In my case, I am changing corner radius of dialog to rounded 20dp corners-->
        <item name="colorSurface">@color/white</item>
        <item name="buttonBarPositiveButtonStyle">@style/Widget.App.Button</item> <!-- your custom positive button style-->
        <item name="buttonBarNegativeButtonStyle">@style/Widget.App.Button</item> <!-- your custom negtive button style-->
    </style>

    <style name="ShapeAppearance.App.SmallComponent" parent="ShapeAppearance.MaterialComponents.SmallComponent">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">20dp</item>
    </style>

    <style name="Widget.App.Button" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
        <item name="shapeAppearance">@style/ShapeAppearance.App.SmallComponent</item>
        <item name="android:textAppearance">@style/Roboto.Bold.Small</item>
        <item name="android:textColor">@color/colorAccent</item>
        <item name="android:textAllCaps">true</item>
    </style>

Finally, when creating your dialog, do not forget set this style:

 MaterialAlertDialogBuilder(this, R.style.ThemeOverlay_App_MaterialAlertDialog)
            .setMessage("your message")
            .show()

You can define your own layout of the dialog you want to display.

Here's a link for this

Creating a custom dialog in Android

In your Layout you can define TextViews with the typeFace you want. You need to download otf files for the font you want. Have them in your asset directories. And set that as the TypeFace of your TextView. And how to set TypeFace

This can be helpful

How to change the font on the TextView?

Customising the alert dialog title textview

             TextView tv_message = new TextView(this);

            Typeface typeface = Typeface.createFromAsset(
                    getAssets(),
                    "fonts/OpenSans-Semibold.ttf"
            );


            // Set the text view layout parameters
            tv_message.setLayoutParams(
                    new 
      ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 
      ViewGroup.LayoutParams.WRAP_CONTENT)
            );

            // Set message text color
            tv_message.setTextColor(Color.RED);

            // Set message gravity/text align
            tv_message.setGravity(Gravity.START);

            // Set message text size
            tv_message.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);

            // Set message custom font
            tv_message.setTypeface(typeface);

            // Set message background color
            tv_message.setBackgroundColor(Color.YELLOW);

            // Set message text padding
            tv_message.setPadding(15, 25, 15, 15);

            tv_message.setText("Are you sure?");
            tv_message.setTextColor(Color.BLACK);

You could use a SpannableString, set the typeface on it and return it back to the AlertDialog.Builder

This is a helper function that adds a typeface to a CharSequence and returns a SpannableString -

private static SpannableString typeface(Typeface typeface, CharSequence chars) {
    if (chars == null) {
        return null;
    }
    SpannableString s = new SpannableString(chars);
    s.setSpan(new TypefaceSpan(typeface), 0, s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    return s;
}

Class that sets the TypeFace on the text -

public class TypefaceSpan extends MetricAffectingSpan {

    private final Typeface typeface;

    public TypefaceSpan(Typeface typeface) {
        this.typeface = typeface;
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setTypeface(typeface);
        tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }

    @Override
    public void updateMeasureState(TextPaint p) {
        p.setTypeface(typeface);
        p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }
}

While creating the dialog you can substitute the strings with the SpannableString like so -

public static Dialog createDialog(Context c, String title, String message, String pButton, String nButton, AlertCallback callback) {

    AlertDialog.Builder builder = new AlertDialog.Builder(c);

    builder.setMessage(typeface(Fonts.Regular, message));
    builder.setTitle(typeface(Fonts.Bold, title));
    builder.setPositiveButton(typeface(Fonts.Bold, pButton),callback::onPositiveButtonClick);
    builder.setNegativeButton(typeface(Fonts.Bold, nButton),callback::onNegativeButtonClick);

    AlertDialog dialog = builder.create();
    return builder.create();
} 

I'd recommend to load the fonts into a cache, rather than calling createFromAsset multiple times. Hope this helps!

I had an alert dialog containing a list of items, so I had to combine a couple of answers and also simplify it a little bit, here's the code for the alert dialog itself:

val dialog = AlertDialog.Builder(this, R.style.MyAlertDialogTheme).setTitle(R.string.sort_by)
   .setSingleChoiceItems(modelList, selectedSortPosition) { _, position -> selectedSortPosition = position }
   .setPositiveButton(R.string.ok) { _, _ ->  }
   .setNegativeButton(R.string.cancel) { _, _ -> }.create()
dialog.show()
setFontsForDialog(dialog)

here I have used the style from Danilo's answer, but I have added set theme colors for that:

   <style name="MyAlertDialogTheme" parent="Theme.MaterialComponents.DayNight.Dialog.Alert">
      <item name="colorPrimary">@color/colorPrimary</item>
      <item name="colorAccent">@color/colorAccent</item>
      <item name="android:textAppearanceSmall">@style/MyTextAppearanceSmall</item>
      <item name="android:textAppearanceMedium">@style/MyTextAppearanceMedium</item>
      <item name="android:textAppearanceLarge">@style/MyTextAppearanceLarge</item>
   </style>

and since it only changes the font for the list items, I have added this method and since I was going to use it a lot of times in the app, I have created an extension method for the activity itself:

private fun Activity.setFontsForDialog(dialog: AlertDialog) {
    val font = ResourcesCompat.getFont(this, R.font.theme_bold_pn)
    dialog.findViewById<TextView>(android.R.id.message)?.typeface = font
    dialog.findViewById<TextView>(android.R.id.button1)?.typeface = font
    dialog.findViewById<TextView>(android.R.id.button2)?.typeface = font
}

I created an extension method for AlertDialog for this purpose -
(This works as of androidx.appcompat:appcompat:1.1.0)

fun AlertDialog.setTypefaceInDialog(context: Context) {

    val regularFont = ResourcesCompat.getFont(context, R.font.regular_font)
    val boldFont = ResourcesCompat.getFont(context, R.font.medium_font)

    findViewById<TextView>(androidx.appcompat.R.id.alertTitle)?.typeface = boldFont
    findViewById<TextView>(android.R.id.message)?.typeface = regularFont
    getButton(AlertDialog.BUTTON_POSITIVE).typeface = boldFont
    getButton(AlertDialog.BUTTON_NEGATIVE).typeface = boldFont
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM