Як змінити тему для AlertDialog


242

Мені було цікаво, чи може хтось мені допомогти. Я намагаюся створити користувацький AlertDialog. Для цього я додав наступний рядок коду в styles.xml

<resources>
 <style name="CustomAlertDialog" parent="android:Theme.Dialog.Alert">
  <item name="android:windowBackground">@drawable/color_panel_background</item>
 </style>
</resources>
  • color_panel_background.9.png розташований у папці, що виводиться. Це також доступне в папці Resk для Android SDK.

Далі йде основна діяльність.

package com.customdialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;

public class CustomDialog extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        this.setTheme(R.style.CustomAlertDialog);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("HELLO!");
        builder .setCancelable(false)
          .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               //MyActivity.this.finish();
           }
       })
       .setNegativeButton("No", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               //dialog.cancel();
           }
       });

        AlertDialog alertdialog = builder.create();
        alertdialog.show();
    }
}

Щоб застосувати тему до AlertDialog, мені довелося встановити тему в поточний контекст.

Однак я просто не можу отримати додаток для показу налаштованого AlertDialog. Хтось може мені допомогти у цьому?



Я вважаю це репо на Github
esilver

Відповіді:


363

У Dialog.java (Android src) використовується ContextThemeWrapper. Таким чином, ви можете скопіювати ідею та зробити щось на кшталт:

AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AlertDialogCustom));

А потім стилізуйте його так, як вам хочеться:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AlertDialogCustom" parent="@android:style/Theme.Dialog">
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
        <item name="android:textSize">10sp</item>
    </style>
</resources>

62
Не використовуйте @android: style / AlertDialog. Це не в загальнодоступному API. Як наслідок, в Android 2.3.3 він виходить з ладу під час створення конструктора.
Каталін Моросан

18
@kaciula @android:style/Theme.Dialogпублічно? Можна замість цього використовувати?
HRJ

24
Так. Це публічно. Перегляньте developer.android.com/reference/android/R.style.html, щоб переглянути список усіх загальнодоступних стилів. Майте на увазі, що іменування в API відрізняється від використовуваного в коді. Існує "_" замість ". (Theme_Dialog)
Каталін Моросан

2
Де я можу розмістити вищевказаний файл XML?
Чайтанья Чандукар

3
Для нової теми, яка є частиною тем сумісності, я б запропонував використовувати цей Theme.AppCompat.Light.Dialog.Alertстиль як батьківського вашого власного стилю. Але якщо ви це зробите, переконайтеся, що ви імпортуєте, import android.support.v7.app.AlertDialog; а неimport android.app.AlertDialog
w3bshark

93

У мене виникла ця AlertDialogпроблема з використанням sdk 1.6, як описано тут: http://markmail.org/message/mj5ut56irkrkc4nr

Я вирішив проблему, зробивши наступне:

  new AlertDialog.Builder(
  new ContextThemeWrapper(context, android.R.style.Theme_Dialog))

Сподіваюсь, це допомагає.


2
Є кілька відповідних тем; в моєму випадку краще підійшов android.R.style.Theme_Holo_Dialog. Чудова порада.
Джонні О

78

Я написав у своєму блозі статтю про те, як налаштувати макет AlertDialog з файлами стилів XML. Основна проблема полягає в тому, що вам потрібні різні визначення стилів для різних параметрів компонування. Ось панель котлів, заснована на стилі AlertDialog Holo Light Platform версії 19 для файлу стилів, який повинен охоплювати купу стандартних аспектів компонування, таких як розміри тексту та кольори тла.

<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
    ...
    <item name="android:alertDialogTheme">@style/MyAlertDialogTheme</item>
    <item name="android:alertDialogStyle">@style/MyAlertDialogStyle</item>
    ...
</style>

<style name="MyBorderlessButton">
    <!-- Set background drawable and text size of the buttons here -->
    <item name="android:background">...</item>
    <item name="android:textSize">...</item>
</style>

<style name="MyButtonBar">
    <!-- Define a background for the button bar and a divider between the buttons here -->
    <item name="android:divider">....</item>
    <item name="android:dividerPadding">...</item>
    <item name="android:showDividers">...</item>
    <item name="android:background">...</item>
</style>

<style name="MyAlertDialogTitle">
    <item name="android:maxLines">1</item>
    <item name="android:scrollHorizontally">true</item>
</style>

<style name="MyAlertTextAppearance">
    <!-- Set text size and color of title and message here -->
    <item name="android:textSize"> ... </item>
    <item name="android:textColor">...</item>
</style>

<style name="MyAlertDialogTheme">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowTitleStyle">@style/MyAlertDialogTitle</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
    <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:textAppearanceMedium">@style/MyAlertTextAppearance</item>
    <!-- If you don't want your own button bar style use
            @android:style/Holo.Light.ButtonBar.AlertDialog
            and
            ?android:attr/borderlessButtonStyle
         instead of @style/MyButtonBar and @style/MyBorderlessButton -->
    <item name="android:buttonBarStyle">@style/MyButtonBar</item>
    <item name="android:buttonBarButtonStyle">@style/MyBorderlessButton</item>
</style>

<style name="MyAlertDialogStyle">
    <!-- Define background colors of title, message, buttons, etc. here -->
    <item name="android:fullDark">...</item>
    <item name="android:topDark">...</item>
    <item name="android:centerDark">...</item>
    <item name="android:bottomDark">...</item>
    <item name="android:fullBright">...</item>
    <item name="android:topBright">...</item>
    <item name="android:centerBright">...</item>
    <item name="android:bottomBright">...</item>
    <item name="android:bottomMedium">...</item>
    <item name="android:centerMedium">...</item>
</style>

2
я можу запитати вас, чому нам і потрібен стиль та тема для налаштування AlertDialog? Дуже дякую! @nantoka
brainvision

2
@brainvision У моєму блозі є деталі, але, у двох словах, макет AlertDialog походить з двох різних класів (Dialog та AlertController), які використовують різні параметри файлів компонування.
Нантока

46
 <style name="AlertDialogCustom" parent="Theme.AppCompat.Light.Dialog.Alert">
    <!-- Used for the buttons -->
    <item name="colorAccent">@color/colorAccent</item>
    <!-- Used for the title and text -->
    <item name="android:textColorPrimary">#FFFFFF</item>
    <!-- Used for the background -->
    <item name="android:background">@color/teal</item>
</style>





new AlertDialog.Builder(new ContextThemeWrapper(context,R.style.AlertDialogCustom))
            .setMessage(Html.fromHtml(Msg))
            .setPositiveButton(posBtn, okListener)
            .setNegativeButton(negBtn, null)
            .create()
            .show();

3
Найпростіше, але швидке рішення!
FonzTech

4
Добре, а як щодо використання якогось атрибута, щоб оголосити його глобально в "AppTheme"?
мертвий риб

2
Це допомогло мені змінити кольори кнопок діалогу.
ікаровіртуальне

1
Спасибі мій чувак, ти врятував мій тиждень !!
Clifton Steenkamp

31

Я боровся з цим - ви можете стилізувати фон діалогового вікна, використовуючи android:alertDialogStyle="@style/AlertDialog"свою тему, але він ігнорує будь-які налаштування тексту. Як @rflexor говорив вище, це не можна робити з SDK до Honeycomb (добре, що ви можете використовувати Reflection).

Моє рішення, в двох словах, полягала в тому, щоб стилізувати фон діалогового вікна, використовуючи вищезазначене, а потім встановити спеціальний перегляд заголовка та вмісту (з використанням макетів, таких самих, як у SDK).

Моя обгортка:

import com.mypackage.R;

import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class CustomAlertDialogBuilder extends AlertDialog.Builder {

    private final Context mContext;
    private TextView mTitle;
    private ImageView mIcon;
    private TextView mMessage;

    public CustomAlertDialogBuilder(Context context) {
        super(context);
        mContext = context; 

        View customTitle = View.inflate(mContext, R.layout.alert_dialog_title, null);
        mTitle = (TextView) customTitle.findViewById(R.id.alertTitle);
        mIcon = (ImageView) customTitle.findViewById(R.id.icon);
        setCustomTitle(customTitle);

        View customMessage = View.inflate(mContext, R.layout.alert_dialog_message, null);
        mMessage = (TextView) customMessage.findViewById(R.id.message);
        setView(customMessage);
    }

    @Override
    public CustomAlertDialogBuilder setTitle(int textResId) {
        mTitle.setText(textResId);
        return this;
    }
    @Override
    public CustomAlertDialogBuilder setTitle(CharSequence text) {
        mTitle.setText(text);
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setMessage(int textResId) {
        mMessage.setText(textResId);
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setMessage(CharSequence text) {
        mMessage.setText(text);
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setIcon(int drawableResId) {
        mIcon.setImageResource(drawableResId);
        return this;
    }

    @Override
    public CustomAlertDialogBuilder setIcon(Drawable icon) {
        mIcon.setImageDrawable(icon);
        return this;
    }

}

alert_dialog_title.xml (взяті з SDK)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <LinearLayout
            android:id="@+id/title_template"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginTop="6dip"
            android:layout_marginBottom="9dip"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="10dip">

            <ImageView android:id="@+id/icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="top"
                android:paddingTop="6dip"
                android:paddingRight="10dip"
                android:src="@drawable/ic_dialog_alert" />
            <TextView android:id="@+id/alertTitle"
                style="@style/?android:attr/textAppearanceLarge"
                android:singleLine="true"
                android:ellipsize="end"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
        <ImageView android:id="@+id/titleDivider"
            android:layout_width="fill_parent"
            android:layout_height="1dip"
            android:scaleType="fitXY"
            android:gravity="fill_horizontal"
            android:src="@drawable/divider_horizontal_bright" />
</LinearLayout>

alert_dialog_message.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/scrollView"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingTop="2dip"
            android:paddingBottom="12dip"
            android:paddingLeft="14dip"
            android:paddingRight="10dip">
    <TextView android:id="@+id/message"
                style="?android:attr/textAppearanceMedium"
                android:textColor="@color/dark_grey"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:padding="5dip" />
</ScrollView>

Потім просто використовуйте CustomAlertDialogBuilderзамість того, AlertDialog.Builderщоб створити діалоги, а просто зателефонуйте setTitleта, setMessageяк завжди.


3
як ви отримали доступ до android.R.internal.id.alerttitle?
Гілберт

2
Я цього не зробив, я звернувся до R.id.alertTitle
Джозеф граф

28

Ви можете безпосередньо призначити тему, коли ви ініціюєте Builder:

AlertDialog.Builder builder = new AlertDialog.Builder(
                    getActivity(), R.style.MyAlertDialogTheme);

Потім налаштуйте свою тему у своєму values/styles.xml

<!-- Alert Dialog -->
<style name="MyAlertDialogTheme" parent="Theme.AppCompat.Dialog.Alert">
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:colorBackground">@color/alertDialogBackground</item>
    <item name="android:windowBackground">@color/alertDialogBackground</item>
</style>

1
Ідеально. Єдине, що я використавTheme.AppCompat.Light.Dialog.Alert
екшакінг

11

Для користувацького діалогового вікна:

просто зателефонуйте super(context,R.style.<dialog style>)замість super(context)конструктора діалогу

public class MyDialog extends Dialog
{
    public MyDialog(Context context)
    {
       super(context, R.style.Theme_AppCompat_Light_Dialog_Alert)
    }
}


Для AlertDialog:

Просто створіть alerDialog за допомогою цього конструктора:

 new AlertDialog.Builder(
 new ContextThemeWrapper(context, android.R.style.Theme_Dialog))

1
Діалог не потрібно розширювати на новий порожній клас, оскільки вже існує версія конструктора, яка займає стиль теми.
FindOut_Quran

@FindOut_Quran Суть полягає в тому, щоб показати, як перекрити стиль у користувацькому класі Dialog. Це лише приклад, і ваш справжній клас Dialog матиме ще якийсь код.
Найлл

8

Я думаю, це зробити неможливо. Принаймні, не з Будівельником. Я працюю з 1.6, а впровадження в Builder.create ():

public AlertDialog create() {
    final AlertDialog dialog = new AlertDialog(P.mContext);
    P.apply(dialog.mAlert);
    [...]
}

який називає конструктор "AlertDialog", який не знає теми, який виглядає приблизно так:

protected AlertDialog(Context context) {
    this(context, com.android.internal.R.style.Theme_Dialog_Alert);
}

В AlertDialog є другий конструктор для зміни тем:

protected AlertDialog(Context context, int theme) {
    super(context, theme);
    [...]
}

що Builder просто не дзвонить.

Якщо діалог все-таки досить загальний, я б спробував написати підклас AlertDialog, викликаючи другий конструктор і використовувати цей клас замість механізму Builder.


4

Кращий спосіб зробити це за допомогою спеціального діалогового вікна та налаштувати відповідно до ваших потреб, це приклад спеціального діалогу .....

введіть тут опис зображення

public class CustomDialogUI {
Dialog dialog;
Vibrator vib;
RelativeLayout rl;

@SuppressWarnings("static-access")
public void dialog(final Context context, String title, String message,
        final Runnable task) {
    dialog = new Dialog(context);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(R.layout.custom);
    dialog.setCancelable(false);
    TextView m = (TextView) dialog.findViewById(R.id.message);
    TextView t = (TextView) dialog.findViewById(R.id.title);
    final Button n = (Button) dialog.findViewById(R.id.button2);
    final Button p = (Button) dialog.findViewById(R.id.next_button);
    rl = (RelativeLayout) dialog.findViewById(R.id.rlmain);
    t.setText(bold(title));
    m.setText(message);
    dialog.show();
    n.setText(bold("Close"));
    p.setText(bold("Ok"));
    // color(context,rl);
    vib = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
    n.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View arg0) {
            vib.vibrate(15);
            dialog.dismiss();
        }
    });
    p.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View arg0) {
            vib.vibrate(20);
            dialog.dismiss();
            task.run();
        }
    });
}
 //customize text style bold italic....
public SpannableString bold(String s) {
    SpannableString spanString = new SpannableString(s);
    spanString.setSpan(new StyleSpan(Typeface.BOLD), 0,
            spanString.length(), 0);
    spanString.setSpan(new UnderlineSpan(), 0, spanString.length(), 0);
    // spanString.setSpan(new StyleSpan(Typeface.ITALIC), 0,
    // spanString.length(), 0);
    return spanString;
}

}

Ось xml макет

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
>

<RelativeLayout
    android:id="@+id/rlmain"
    android:layout_width="fill_parent"
    android:layout_height="150dip"
    android:layout_alignParentLeft="true"
    android:layout_centerVertical="true"
    android:background="#569CE3" >

    <RelativeLayout
        android:id="@+id/relativeLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="25dip"
        android:layout_marginTop="10dip" >

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:text="Are you Sure?"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="#ffffff"
            android:textSize="13dip" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/relativeLayout2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/relativeLayout1"
        android:layout_alignRight="@+id/relativeLayout1"
        android:layout_below="@+id/relativeLayout1"
        android:layout_marginTop="5dip" >
    </RelativeLayout>

    <ProgressBar
        android:id="@+id/process"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="3dip"
        android:layout_marginTop="3dip" />

    <RelativeLayout
        android:id="@+id/relativeLayout3"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/relativeLayout2"
        android:layout_below="@+id/relativeLayout2"
        android:layout_toLeftOf="@+id/process" >

        <TextView
            android:id="@+id/message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:text="Medium Text"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="#ffffff"
            android:textSize="13dip"/>

    </RelativeLayout>

    <Button
        android:id="@+id/next_button"
        android:layout_width="90dip"
        android:layout_height="35dip"
        android:layout_alignParentBottom="true"
        android:textColor="@drawable/button_text_color"
         android:background="@drawable/blue_button"
         android:layout_marginBottom="5dp"
           android:textSize="10dp"

        android:layout_alignRight="@+id/relativeLayout3"
        android:text="Okay" />

    <Button
        android:id="@+id/button2"
        android:text="Cancel"
        android:textColor="@drawable/button_text_color"
        android:layout_width="90dip"
        android:layout_height="35dip"
        android:layout_marginBottom="5dp"
         android:background="@drawable/blue_button"
         android:layout_marginRight="7dp"
        android:textSize="10dp"
        android:layout_alignParentBottom="true"
        android:layout_toLeftOf="@+id/next_button"
         />

</RelativeLayout>


7
Тематизація та використання спеціального перегляду - це дві різні речі та мають різні цілі.
jmc34

3

Кожен, хто намагається зробити це в межах фрагмента (використовуючи бібліотеку підтримки, тобто попередній API 11), повинен:

public class LoadingDialogFragment extends DialogFragment {
    public static final String ID = "loadingDialog";

    public static LoadingDialogFragment newInstance() {
        LoadingDialogFragment f = new LoadingDialogFragment();

        return f;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        StyleAlertDialog adb = new StyleAlertDialog(getActivity(), R.style.Your_Style);
        adb.setView(getActivity().getLayoutInflater().inflate(R.layout.fragment_dialog_layout, null));
        return adb;
    }

    private class StyleAlertDialog extends AlertDialog {
        protected StyleAlertDialog(Context context, int theme) {
            super(context, theme);
        }
    }
}

@Rflexor дав мені поштовх, щоб розширити AlertDialog і викласти конструктор спасибі


Конструктор AlertDialog.Builder(Context, int)працює лише на API 11 і вище. У попередніх версіях Android ваш код буде збій.
Джозеф Граф

@JosephEarl (використовуючи бібліотеку підтримки, тобто API 11)
Блонделл

Моє погано, ви використовуєте конструктор діалогів, а не конструктор діалогу.
Джозеф граф

2

Рішення Арве Уолтіна виглядає добре, хоча я його ще не перевіряв. Існує ще одне рішення в разі , якщо у вас є проблеми при отриманні , що до роботи .... Розширення AlertDialog.Builderі перевизначити всі методи (наприклад. setText, setTitle,setView І т.д.) не встановлено фактичний Діалог текст / назва / вид, але і створити новий вид всередині діалоговий погляд робить усе, що там. Тоді ви можете стилізовувати все як завгодно.

Для уточнення, що стосується батьківського класу, вигляд встановлюється, і більше нічого.

Що стосується вашого індивідуального розширеного класу, все робиться в межах цього подання.


0

Я не впевнений, як працюватиме рішення Arve у користувальницькому діалозі з будівельником, де подання завищене через LayoutInflator.

Рішенням має бути вставлення ContextThemeWrapper в нагнітач через cloneInContext():

View sensorView = LayoutInflater.from(context).cloneInContext(
     new ContextThemeWrapper(context, R.style.AppTheme_DialogLight)
).inflate(R.layout.dialog_fingerprint, null);

-1

Це можна зробити просто, використовуючи setView () Builder. Ви можете створити будь-який перегляд на свій вибір і подати в програму будівельника. Це добре працює. Я використовую користувальницький TextView, який надається конструктором діалогів. Я не встановлюю повідомлення, і цей простір використовується для надання мого перегляду тексту зберігання.


-12
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title");
builder.setMessage("Description");
builder.setPositiveButton("OK", null);
builder.setNegativeButton("Cancel", null);
builder.show();

Ви не проти відформатувати свій код за допомогою вбудованого фрагмента коду?
Адріано
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.