Как изменить цвет заголовка AlertDialog и цвет строки под ним

109

Я изменил цвет заголовка AlertDialog с помощью этой команды

alert.setTitle( Html.fromHtml("<font color='#FF7F27'>Set IP Address</font>"));

Но я хочу изменить цвет строки, которая появляется под заголовком; Как мне это сделать ?

Примечание: я не хочу использовать собственный макет

скриншот желаемого эффекта

Мохаммед Субхи Шейх Куруш
источник
1
есть ли конкретная причина, по которой вы хотите избегать нестандартных макетов? Какие дополнительные условия необходимо выполнить?
Дэниел Смит
4
На самом деле вы можете изменить цвет заголовка AlertDialog очень простым взломом. stackoverflow.com/a/21401181/855884
MatrixDev

Ответы:

134

К сожалению, это не очень простая задача. В своем ответе я подробно описываю, как настроить цвет a ListSeparator, просто проверив родительский стиль, используемый Android, создав новое изображение и создав новый стиль на основе оригинала. К сожалению, в отличие от ListSeparatorстиля, AlertDialogтемы являются внутренними, и поэтому на них нельзя ссылаться как на родительские стили. Нет простого способа изменить эту маленькую синюю линию! Таким образом, вам нужно прибегнуть к созданию настраиваемых диалогов.

Если это не ваша чашка чая ... не сдавайтесь! Я был очень обеспокоен тем, что не было простого способа сделать это, поэтому я создал небольшой проект на github для создания быстро настраиваемых диалогов в голографическом стиле (при условии, что телефон поддерживает голографический стиль). Вы можете найти проект здесь: https://github.com/danoz73/QustomDialog

Он должен легко позволить перейти от скучного синего к волнующему оранжевому!

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

Проект в основном представляет собой пример использования настраиваемого конструктора диалоговых окон, и в этом примере я создал настраиваемое представление, которое, похоже, соответствует примеру IP-адреса, который вы указываете в исходном вопросе.

С QustomDialog, чтобы создать базовый диалог (заголовок, сообщение) с желаемым другим цветом для заголовка или разделителя, вы используете следующий код:

private String HALLOWEEN_ORANGE = "#FF7F27";

QustomDialogBuilder qustomDialogBuilder = new QustomDialogBuilder(v.getContext()).
    setTitle("Set IP Address").
    setTitleColor(HALLOWEEN_ORANGE).
    setDividerColor(HALLOWEEN_ORANGE).
    setMessage("You are now entering the 10th dimension.");

qustomDialogBuilder.show();

А чтобы добавить собственный макет (скажем, чтобы добавить маленький IP-адрес EditText), вы добавляете

setCustomView(R.layout.example_ip_address_layout, v.getContext())

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

Дэниел Смит
источник
2
почему Android до сих пор не поддерживает изменение цвета диалогового окна предупреждения, следует ли использовать другой диалог или в чем проблема?
Мохаммед Субхи Шейх Куруш
3
Android, вероятно, пытается обеспечить согласованные шаблоны пользовательского интерфейса, поэтому, вероятно, это так сложно. Это лучшее решение, которое я мог бы придумать, чтобы помочь вам. Надеюсь, вы найдете это полезным или, по крайней мере, интересным и информативным :)
Дэниел Смит
2
привет Даниэль. спасибо, что поделились своей работой. Это очень полезно. Я столкнулся с одной проблемой при реализации этого. На самом деле я хочу добавить выбор одного элемента setItemsв этом настраиваемом диалоговом окне. Когда я добавляю список, он фактически сдвигает заголовок под списком. Как решить эту проблему.
Дори
3
ну, может быть, еще не совсем ... Я столкнулся с проблемой заголовка под списком ... извините.
dentex
1
@DanielSmith привет! Хорошая работа, но нашли ли вы решение для «заголовка под списком», как упоминалось выше,
Шириш Хервэйд,
74

Цвет разделителя:

Это немного хак, но он отлично работает для меня и работает без какой-либо внешней библиотеки (по крайней мере, на Android 4.4).

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.dialog)
       .setIcon(R.drawable.ic)
       .setMessage(R.string.dialog_msg);
//The tricky part
Dialog d = builder.show();
int dividerId = d.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
View divider = d.findViewById(dividerId);
divider.setBackgroundColor(getResources().getColor(R.color.my_color));

Вы можете найти больше идентификаторов диалогов в файле alert_dialog.xml . Например. android:id/alertTitleдля изменения цвета заголовка ...

ОБНОВЛЕНИЕ: цвет заголовка

Хак для изменения цвета заголовка:

int textViewId = d.getContext().getResources().getIdentifier("android:id/alertTitle", null, null);
TextView tv = (TextView) d.findViewById(textViewId);
tv.setTextColor(getResources().getColor(R.color.my_color));
ммрмартин
источник
Даже на KitKat android.util.AndroidRuntimeException: requestFeature() must be called before adding contentздесь натыкаюсь.
Конрад Райх
Я использую этот фрагмент кода во многих местах своего приложения, и везде он отлично работает. Я знаю только о проблемах, DialogFragmentкогда у цвета заголовка нет идентификатора, android:id/alertTitleно я не нашел правильный.
mmrmartin
2
@platzhirsch, в моем собственном классе DialogFragment я избежал проблемы requestFeature (), запустив код настройки в onStart (). Вы можете получить доступ к диалогу там, используя getDialog ().
arlomedia
1
Так же как предупреждение для будущих пользователей, которые могут столкнуться с этим; по какой-то причине, когда я использую только общий диалог, я должен использовать «title» в качестве имени идентификатора вместо «alertTitle». Не уверен, что это упоминается где-нибудь еще, но просто подумал, что добавлю свой бит в надежде помочь: P
zgc7009
3
я получаю NullPointerExceptionвsetTextColor()
Abhi
21

проверьте, это полезно для вас ...

public void setCustomTitle (View customTitleView)

вы получите подробную информацию по следующей ссылке.

http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setCustomTitle%28android.view.View%29

CustomDialog.java

Dialog alert = new Dialog(this);
    alert.requestWindowFeature(Window.FEATURE_NO_TITLE);
    alert.setContentView(R.layout.title);
    TextView msg = (TextView)alert.findViewById(R.id.textView1);
    msg.setText("Hello Friends.\nIP address : 111.111.1.111");
    alert.show();

title.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Set IP address"
    android:textColor="#ff0000"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<ImageView 
    android:layout_width="fill_parent"
    android:layout_height="2dp"
    android:layout_marginTop="5dp"
    android:background="#00ff00"
    />
<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#775500"
    android:textAppearance="?android:attr/textAppearanceLarge" />

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

Мистер Сэнди
источник
Я пробую это, но у меня все еще есть синяя линия под моим TextView
Мохаммед Субхи Шейх Куруш
у меня есть код. которые поставили в ответ после "Edit". вы попробуете это.
Мистер Сэнди
10

Это установит цвет для заголовка, значка и разделителя. Обязательно изменится с любой новой версией Android.

public static void colorAlertDialogTitle(AlertDialog dialog, int color) {
    int dividerId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
    if (dividerId != 0) {
        View divider = dialog.findViewById(dividerId);
        divider.setBackgroundColor(color);
    }

    int textViewId = dialog.getContext().getResources().getIdentifier("android:id/alertTitle", null, null);
    if (textViewId != 0) {
        TextView tv = (TextView) dialog.findViewById(textViewId);
        tv.setTextColor(color);
    }

    int iconId = dialog.getContext().getResources().getIdentifier("android:id/icon", null, null);
    if (iconId != 0) {
        ImageView icon = (ImageView) dialog.findViewById(iconId);
        icon.setColorFilter(color);
    }
}

Не забудьте вызвать dialog.show () перед вызовом этого метода.

Джаред Раммлер
источник
@Vlado вы используете appcompat? В таком случае это может не сработать.
Джаред Раммлер
9

Следуя исходному коду диалогового окна , я обнаружил, что заголовок создается в классе MidWindowпутем расширения dialog_title_holo.xmlмакета. так что идентификатор mTitleViewравен, titleа идентификатор делителя равен titleDivider.

мы можем получить доступ к Id titleпросто с помощью android.R.id.title.

и доступ к идентификатору titleDividerпользователяResources.getSystem().getIdentifier("titleDivider","id", "android");

Последний код, который я использовал для изменения направления заголовка и изменения цвета:

TextView mTitle = (TextView)findViewById(android.R.id.title);
mTitle.setGravity(Gravity.RIGHT|Gravity.CENTER_VERTICAL);
int x = Resources.getSystem().getIdentifier("titleDivider","id", "android");
View titleDivider = findViewById(x);
titleDivider.setBackgroundColor(getContext().getResources().getColor(R.color.some_color));
MRD ABD
источник
Это полный ответ! Использование android.R.id.title для изменения заголовка!
Андреас Лимбурас
Отличный ответ, мне очень помог! Пришлось изменить: TextView mTitle = (TextView) findViewById (android.R.id.title); кому: TextView mTitle = (TextView) dialog.findViewById (android.R.id.title); чтобы это работало.
Ян Цисс
Это сработало для меня, я использую Activity, который наследует @android: style / Theme.Dialog. Можно настроить разделительную линию и цвет заголовка. +1
voghDev
4

Если вам не нужна "библиотека" для этого, вы можете использовать этот ужасный прием:

((ViewGroup)((ViewGroup)getDialog().getWindow().getDecorView()).getChildAt(0)) //ie LinearLayout containing all the dialog (title, titleDivider, content)
.getChildAt(1) // ie the view titleDivider
.setBackgroundColor(getResources().getColor(R.color.yourBeautifulColor));

Это было протестировано и работает на 4.x; не тестировался, но если у меня хорошая память, он должен работать для 2.x и 3.x

Бенджамин Вадон
источник
Это отлично работает для 4.xi, я тоже не пробовал другие, поэтому я попробую и подтвердю это
kandroidj
getDialog () выдает ошибку «Метод getDialog () не определен для типа MainActivity» он просит меня создать метод
Zen
4

В классе onCreateView я поместил это:

Dialog d = getDialog();
    d.setTitle(Html.fromHtml("<font color='#EC407A'>About</font>"));
    int dividerId = d.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
    View divider = d.findViewById(dividerId);
    divider.setBackgroundColor(getResources().getColor(R.color.colorPrimary));

colorPrimary ссылается на наш файл colors.xml, в котором хранятся все цвета. Также d.setTitleпредоставляет хакерский способ установить цвет заголовка.

lg365
источник
1

Если вы создаете собственный макет для диалогового окна предупреждения

тогда вы можете легко добавить такой способ, чтобы изменить цвет

<LinearLayout
    android:id="@+id/DialogTitleBorder"
    android:layout_width="fill_parent"
    android:layout_height="1dip"
    android:layout_below="@id/mExitDialogDesc"
    android:background="#4BBAE3"            <!--change color easily -->
    >

</LinearLayout>
Janmejoy
источник
1

Если вы используете собственный макет заголовка, вы можете использовать его как alertDialog.setCustomTitle(customTitle);

пример

В потоке пользовательского интерфейса используйте диалог, например:

 LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
 View customTitle = inflater.inflate(R.layout.customtitlebar, null);
 AlertDialog.Builder d = new AlertDialog.Builder(this);
 d.setCustomTitle(customTitle);
 d.setMessage("Message");
 d.setNeutralButton("OK", null);
 d.show();

customtitlebar.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="wrap_content"
    android:orientation="vertical"
    android:background="#525f67">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@drawable/ic_launcher"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true" >
    </ImageView>

    <TextView
        android:id="@+id/customtitlebar"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:textColor="#ffffff"
        android:text="Title Name"
        android:padding="3px"
        android:textStyle="bold" 
        android:layout_toRightOf="@id/icon"
        android:layout_alignParentTop="true"
        android:gravity="center_vertical"/>

     <ImageView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#ff0000" 
        android:layout_below="@id/icon"><!-- This is line below the title -->
    </ImageView>

</RelativeLayout>
Амол Вадекар
источник
Я хочу изменить цвет линии внутри красного эллипса
Мохаммед Субхи Шейх Куруш
1

Вот еще одно решение (на основе предложенных ответов), которое обрабатывает стили диалогов в одном классе, не беспокоясь о состоянии диалогового окна при изменении стиля - диалоговое окно может быть уже показано или только что инициализировано.

Пример использования:

AlertDialog.Builder builder = new AlertDialog.Builder(context);
AlertDialog dialog = builder.create(); //or builder.show()
DialogViewDecorator.decorate(dialog, android.R.color.holo_red_light); //can also set the defaut color in the class

Реализация:

public class DialogViewDecorator {

private static final
@ColorRes int DEFAULT_TITLE_DIVIDER_COLOR = android.R.color.holo_orange_light;

public static void decorate(Dialog dialog) {
    decorate(dialog, DEFAULT_TITLE_DIVIDER_COLOR);
}

/**
 * Sets the title divider color when the view is shown by setting DialogInterface.OnShowListener on the dialog.
 * <p/>
 * If you want to do other things onShow be sure to extend OnDecoratedDialogShownListener(call super.show(...)!)
 * and call {@link #decorate(Dialog, int, OnDecoratedDialogShownListener)}.
 *
 * @param dialog
 * @param titleDividerColor
 */
public static void decorate(Dialog dialog, final int titleDividerColor) {
    decorate(dialog, titleDividerColor, new OnDecoratedDialogShownListener(titleDividerColor));
}

/**
 * Method for setting a extended implementation of OnDecoratedDialogShownListener. Don't forget to call super
 * or the titleDividerColor wont be applied!
 *
 * @param dialog
 * @param titleDividerColor
 * @param OnShowListener
 * @param <T>
 */
public static <T extends OnDecoratedDialogShownListener> void decorate(Dialog dialog, int titleDividerColor, T OnShowListener) {
    if (dialog == null || titleDividerColor <= 0) { return; }

    if (dialog.isShowing()) {
        setTitleDividerColor(dialog, titleDividerColor);
    } else {
        dialog.setOnShowListener(OnShowListener);
    }
}

private static void setTitleDividerColor(DialogInterface dialogInterface, int titleDividerColor) {
    try {
        Dialog dialog = (Dialog) dialogInterface;
        int dividerId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
        View divider = dialog.findViewById(dividerId);
        if (divider != null) {
            divider.setBackgroundColor(dialog.getContext().getResources().getColor(titleDividerColor));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}


public static class OnDecoratedDialogShownListener implements DialogInterface.OnShowListener {
    private int titleDividerColor;

    public OnDecoratedDialogShownListener() {
        this.titleDividerColor = DEFAULT_TITLE_DIVIDER_COLOR;
    }

    public OnDecoratedDialogShownListener(int titleDividerColor) {
        this.titleDividerColor = titleDividerColor;
    }

    @Override
    public void onShow(DialogInterface dialogInterface) {
        setTitleDividerColor(dialogInterface, titleDividerColor);
    }
}}
GMan
источник
0

Продолжая этот ответ: https://stackoverflow.com/a/15285514/1865860 , я раздвоил красивое репозиторий github от @ daniel-smith и внес некоторые улучшения:

  • улучшенный пример Activity
  • улучшенные макеты
  • фиксированный setItems метод
  • добавлены разделители на items_list
  • закрыть диалоги по щелчку
  • поддержка отключенных элементов в setItemsметодах
  • listItem сенсорная обратная связь
  • прокручиваемое диалоговое сообщение

ссылка: https://github.com/dentex/QustomDialog

Dentex
источник
0

Вместо использования разделителя в диалоговом окне используйте представление в настраиваемом макете и установите макет как настраиваемый макет в диалоговом окне.

custom_popup.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

    <com.divago.view.TextViewMedium
        android:id="@+id/txtTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="AlertDialog"
        android:textColor="@android:color/black"
        android:textSize="20sp" />

    <View
        android:id="@+id/border"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_below="@id/txtTitle"
        android:background="@color/txt_dark_grey" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/border"
        android:scrollbars="vertical">

        <com.divago.view.TextViewRegular
            android:id="@+id/txtPopup"
            android:layout_margin="15dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </ScrollView>
</RelativeLayout>

activity.java:

public void showPopUp(String title, String text) {

    LayoutInflater inflater = getLayoutInflater();
    View alertLayout = inflater.inflate(R.layout.custom_popup, null);

    TextView txtContent = alertLayout.findViewById(R.id.txtPopup);
    txtContent.setText(text);

    TextView txtTitle = alertLayout.findViewById(R.id.txtTitle);
    txtTitle.setText(title);

    AlertDialog.Builder alert = new AlertDialog.Builder(this);
    alert.setView(alertLayout);
    alert.setCancelable(true);

    alert.setPositiveButton("Done", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });

    AlertDialog dialog = alert.create();
    dialog.show();
}
Velayutham M
источник
0
    ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.BLACK);

    String title = context.getString(R.string.agreement_popup_message);
    SpannableStringBuilder ssBuilder = new SpannableStringBuilder(title);
    ssBuilder.setSpan(
            foregroundColorSpan,
            0,
            title.length(),
            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
    );

AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(context);
alertDialogBuilderUserInput.setTitle(ssBuilder)
Самет ÖZTOPRAK
источник
-1

Если вы используете расширение диалога, используйте:

requestWindowFeature(Window.FEATURE_NO_TITLE);
Махеш
источник