Jak mogę zmienić kolor tytułu AlertDialog i kolor linii pod nim

109

Za pomocą tego polecenia zmieniłem kolor tytułu AlertDialog

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

Ale chcę zmienić kolor linii, która pojawia się pod tytułem; jak mogę to zrobić ?

Uwaga: nie chcę używać niestandardowego układu

zrzut ekranu z pożądanym efektem

Mohammed Subhi Sheikh Quroush
źródło
1
Czy jest jakiś konkretny powód, dla którego chcesz uniknąć niestandardowych układów? Jakie masz dodatkowe wymagania, które musisz spełnić?
Daniel Smith,
4
W rzeczywistości możesz zmienić kolor tytułu AlertDialog przez bardzo prosty hack. stackoverflow.com/a/21401181/855884
MatrixDev

Odpowiedzi:

134

Niestety nie jest to szczególnie proste zadanie do wykonania. W mojej odpowiedzi szczegółowo opisuję, jak dostosować kolor a, ListSeparatorpo prostu sprawdzając styl nadrzędny używany przez Androida, tworząc nowy obraz i tworząc nowy styl na podstawie oryginału. Niestety, w przeciwieństwie do ListSeparatorstylu,AlertDialog motywy mają charakter wewnętrzny i dlatego nie można do nich odwoływać się jako stylów macierzystych. Nie ma łatwego sposobu na zmianę tej małej niebieskiej linii! Dlatego musisz uciec się do tworzenia niestandardowych okien dialogowych.

Jeśli to nie twoja filiżanka herbaty ... nie poddawaj się! Byłem bardzo zaniepokojony, że nie ma na to łatwego sposobu, więc założyłem mały projekt na githubie do tworzenia szybko dostosowanych dialogów w stylu holo (zakładając, że telefon obsługuje styl Holo). Projekt można znaleźć tutaj: https://github.com/danoz73/QustomDialog

Powinien z łatwością umożliwić przejście od nudnego błękitu do ekscytującej pomarańczy!

wprowadź opis obrazu tutaj

Projekt jest w zasadzie przykładem użycia konstruktora niestandardowego okna dialogowego, aw przykładzie utworzyłem niestandardowy widok, który wydawał się odpowiadać przykładowi adresu IP, który podałeś w swoim pierwotnym pytaniu.

W przypadku QustomDialog, aby stworzyć podstawowe okno dialogowe (tytuł, komunikat) z żądanym innym kolorem tytułu lub separatora, należy użyć następującego kodu:

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

Aby dodać niestandardowy układ (powiedzmy, aby dodać mały adres IP EditText), dodajesz

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

do konstruktora z zaprojektowanym układem (przykład adresu IP można znaleźć na github). Mam nadzieję, że to pomoże. Wielkie podziękowania dla Josepha Earla i jego odpowiedzi tutaj .

Daniel Smith
źródło
2
dlaczego system Android nadal nie obsługuje zmiany kolorów okna dialogowego ostrzeżenia, czy powinienem użyć innego okna dialogowego lub gdzie jest problem?
Mohammed Subhi Sheikh Quroush
3
Android prawdopodobnie próbuje wymusić spójne wzorce interfejsu użytkownika, więc prawdopodobnie jest to tak trudne. To najlepsze rozwiązanie, jakie mogłem stworzyć, aby ci pomóc. Mam nadzieję, że uznasz to za przydatne lub przynajmniej interesujące i pouczające :)
Daniel Smith
2
cześć Daniel. dziękuję za udostępnienie swojej pracy. To jest bardzo pomocne. Przy wdrażaniu tego mam jeden problem. Właściwie chcę dodać wybór pojedynczego elementu, używając setItemsw tym niestandardowym oknie dialogowym. Dodanie listy powoduje przesunięcie tytułu poniżej listy. Jak rozwiązać ten problem.
Dory
3
no, może jeszcze nie całkiem… Mam problem z tytułem pod listą… przepraszam.
dentex
1
@DanielSmith hi! Dobra robota, ale czy znalazłeś rozwiązanie dla
``
74

Kolor przegrody:

Trochę to hack, ale dla mnie działa świetnie i działa bez żadnej zewnętrznej biblioteki (przynajmniej na Androidzie 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));

Więcej identyfikatorów okien dialogowych można znaleźć w pliku alert_dialog.xml . Na przykład. android:id/alertTitledo zmiany koloru tytułu ...

UPDATE: Kolor tytułu

Sposób na zmianę koloru tytułu:

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));
mmrmartin
źródło
Nawet na KitKat natrafiam android.util.AndroidRuntimeException: requestFeature() must be called before adding contenttutaj.
Konrad Reiche
Używam tego fragmentu kodu w wielu miejscach mojej aplikacji i wszędzie działa dobrze. Wiem tylko o problemach z DialogFragmentbrakiem identyfikatora koloru tytułu, android:id/alertTitleale nie znalazłem właściwego.
mmrmartin
2
@platzhirsch, w mojej niestandardowej klasie DialogFragment, uniknąłem problemu requestFeature (), uruchamiając kod dostosowywania w onStart (). Możesz uzyskać dostęp do tego okna dialogowego za pomocą getDialog ().
arlomedia
1
Jako ostrzeżenie dla przyszłych użytkowników, którzy mogą się z tym spotkać; z jakiegoś powodu, kiedy używam tylko ogólnego okna dialogowego, muszę użyć „title” jako nazwy identyfikatora zamiast „alertTitle”. Nie jestem pewien, czy jest o tym mowa gdziekolwiek indziej, ale pomyślałem, że dodam mój kawałek w nadziei, że pomogę: P
zgc7009
3
Dostaję NullPointerExceptionwsetTextColor()
Abhi
21

sprawdź, czy jest to przydatne dla Ciebie ...

public void setCustomTitle (View customTitleView)

otrzymasz szczegółowe informacje z poniższego linku.

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" />

wprowadź opis obrazu tutaj

Panie Sandy
źródło
Próbuję tego, ale nadal mam niebieską linię pod moim TextView
Mohammed Subhi Sheikh Quroush
mam kod. które umieściły w odpowiedzi po „Edytuj”. spróbuj tego.
Pan Sandy,
10

Spowoduje to ustawienie koloru tytułu, ikony i separatora. Obowiązuje zmiana w każdej nowej wersji Androida.

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

Pamiętaj, aby wywołać dialog.show () przed wywołaniem tej metody.

Jared Rummler
źródło
@Vlado czy używasz appcompat? Jeśli tak, to może nie działać.
Jared Rummler
9

Postępując zgodnie z kodem źródłowym Dialog , odkryłem, że tytuł jest generowany w klasie MidWindowprzez zawyżenie dialog_title_holo.xmlukładu. więc Id mTitleViewjest titlei Id rozdzielacza jest titleDivider.

możemy uzyskać dostęp do Id titlepo prostu przez android.R.id.title.

i dostęp do identyfikatora użytkownika titleDividerwgResources.getSystem().getIdentifier("titleDivider","id", "android");

Ostatni kod, którego użyłem do zmiany kierunku tytułu i zmiany koloru to:

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
źródło
To jest pełna odpowiedź! Użycie android.R.id.title do zmiany tytułu!
Andreas Lymbouras,
Świetna odpowiedź, bardzo mi pomogła! Musiałem zmienić: TextView mTitle = (TextView) findViewById (android.R.id.title); to: TextView mTitle = (TextView) dialog.findViewById (android.R.id.title); żeby to zadziałało.
Jan Ziesse
Ten zadziałał dla mnie, używam działania, które dziedziczy @android: style / Theme.Dialog. Można dostosować linię podziału i kolor tytułu. +1
voghDev
4

Jeśli nie chcesz do tego „biblioteki”, możesz użyć tego złego hacka:

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

To zostało przetestowane i działa na 4.x; nie testowane pod, ale jeśli moja pamięć jest dobra, powinna działać dla 2.xi 3.x.

Benjamin Vadon
źródło
To działa świetnie dla 4.xi nie próbowałem też innych, więc spróbuję i potwierdzę to
kandroidj
getDialog () wyświetla mi błąd "Metoda getDialog () jest niezdefiniowana dla typu MainActivity" prosi mnie o utworzenie metody
Zen
4

W klasie onCreateView umieściłem to:

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 łączy z naszym plikiem colors.xml, który przechowuje wszystkie kolory. Również d.setTitlezapewnia hacky sposób ustawić kolor tytułowy.

lg365
źródło
1

Jeśli tworzysz niestandardowy układ okna dialogowego ostrzeżenia

następnie możesz łatwo dodać w ten sposób, aby zmienić kolor

<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
źródło
1

Jeśli używasz niestandardowego układu tytułu , możesz go używać jak alertDialog.setCustomTitle(customTitle);

Przykład

W wątku interfejsu użytkownika użyj okna dialogowego takiego jak:

 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>
Amol Wadekar
źródło
Chcę zmienić kolor linii wewnątrz czerwonej elipsy
Mohammed Subhi Sheikh Quroush
1

Oto inne rozwiązanie (oparte na sugerowanych odpowiedziach), które obsługuje stylizację okien dialogowych w jednej klasie bez konieczności martwienia się o stan okna dialogowego po zmianie stylu - okno dialogowe może być już wyświetlone lub po prostu zainicjowane.

Przykład użycia:

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

Realizacja:

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
źródło
0

Kontynuując tę ​​odpowiedź: https://stackoverflow.com/a/15285514/1865860 , rozwidliłem ładne repozytorium github z @ daniel-smith i wprowadziłem kilka ulepszeń:

  • ulepszony przykład Activity
  • ulepszone układy
  • naprawiona setItemsmetoda
  • dodane dzielniki do items_list
  • zamknąć okna dialogowe po kliknięciu
  • obsługa wyłączonych elementów w setItemsmetodach
  • listItem reakcja na dotyk
  • przewijalny komunikat w oknie dialogowym

link: https://github.com/dentex/QustomDialog

dentex
źródło
0

Zamiast używać separatora w oknie dialogowym, użyj widoku w układzie niestandardowym i ustaw układ jako układ niestandardowy w oknie dialogowym.

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
źródło
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)
Samet ÖZTOPRAK
źródło
-1

W przypadku rozszerzenia okna użyj:

requestWindowFeature(Window.FEATURE_NO_TITLE);
Mahesh
źródło