web-dev-qa-db-de.com

So ändern Sie das Thema für AlertDialog

Ich habe mich gefragt, ob mir jemand helfen kann. Ich versuche einen benutzerdefinierten AlertDialog zu erstellen. Zu diesem Zweck habe ich die folgende Codezeile in styles.xml hinzugefügt

<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 befindet sich in einem Zeichenordner. Dies ist auch im Ordner Android SDK res verfügbar.

Das Folgende ist die Hauptaktivität.

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

Um das Thema auf einen AlertDialog anzuwenden, musste ich das Thema auf den aktuellen Kontext einstellen.

Es scheint jedoch nicht möglich zu sein, dass die App angepassten AlertDialog anzeigt. Kann mir jemand dabei helfen?

221
Min Soo Kim

In Dialog.Java (Android src) wird ein ContextThemeWrapper verwendet. Sie könnten also die Idee kopieren und etwas tun wie:

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

Und dann gestalten Sie es wie Sie wollen:

<?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>
347
Arve Waltin

Ich hatte dieses AlertDialog themenbezogene Problem mit SDK 1.6, wie hier beschrieben: http://markmail.org/message/mj5ut56irkrkc4nr

Ich habe das Problem folgendermaßen gelöst:

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

Hoffe das hilft.

90
chee

Ich habe in meinem Blog einen Artikel zum Konfigurieren des Layouts eines AlertDialogs mit XML-Formatdateien verfasst. Das Hauptproblem besteht darin, dass Sie unterschiedliche Stildefinitionen für unterschiedliche Layoutparameter benötigen. Hier finden Sie eine Übersicht, die auf dem AlertDialog-Stil von Holo Light Platform Version 19 basiert und eine Formatdatei enthält, die eine Reihe von Standardlayoutaspekten wie Textgrößen und Hintergrundfarben abdecken soll.

<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>
66
Nantoka

Ich hatte damit zu kämpfen - Sie können den Hintergrund des Dialogfelds mit Android:alertDialogStyle="@style/AlertDialog" In Ihrem Design gestalten, aber Ihre Texteinstellungen werden ignoriert. Wie oben bei @rflexor bereits erwähnt, ist dies mit dem SDK vor Honeycomb nicht möglich (Sie können auch Reflection verwenden).

Kurz gesagt, meine Lösung bestand darin, den Hintergrund des Dialogfelds wie oben beschrieben zu gestalten und dann einen benutzerdefinierten Titel und eine Inhaltsansicht festzulegen (unter Verwendung von Layouts, die mit denen im SDK identisch sind).

Mein Umschlag:

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 (aus dem SDK entnommen)

<?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>

Verwenden Sie dann einfach CustomAlertDialogBuilder anstelle von AlertDialog.Builder, Um Ihre Dialoge zu erstellen, und rufen Sie setTitle und setMessage wie gewohnt auf.

31
Joseph Earl
 <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();
29
saigopi

Sie können ein Thema direkt zuweisen, wenn Sie den Builder starten:

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

Dann passen Sie Ihr Thema in Ihrem 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>
20
pha

Für benutzerdefinierten Dialog:

rufen Sie einfach super(context,R.style.<dialog style>) anstelle von super(context) im Dialogkonstruktor auf

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


Für AlertDialog:

Erstelle einfach alertDialog mit diesem Konstruktor:

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

Ich denke, das geht nicht. Zumindest nicht beim Builder. Ich arbeite mit 1.6 und die Implementierung in Builder.create () ist:

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

dies ruft den Konstruktor "Nicht themenorientiert" von AlertDialog auf, der folgendermaßen aussieht:

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

In AlertDialog gibt es einen zweiten Konstruktor zum Ändern von Themen:

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

dass der Builder einfach nicht aufruft.

Wenn der Dialog sowieso ziemlich allgemein ist, würde ich versuchen, eine Unterklasse von AlertDialog zu schreiben, den zweiten Konstruktor aufzurufen und diese Klasse anstelle des Builder-Mechanismus zu verwenden.

8
rflexor

Eine bessere Möglichkeit, um dies zu tun, ist das Beispiel eines benutzerdefinierten Dialogfelds .....

enter image description here

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

}

Hier ist das XML-Layout

<?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>
4
user2671902

Jeder, der versucht, dies innerhalb eines Fragments zu tun (unter Verwendung der Unterstützungsbibliothek, d. H. Vor API 11), sollte dies tun:

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 gab mir den Anstoß, AlertDialog zu erweitern und den Konstruktor verfügbar zu machen. Danke

3
Blundell

Die Lösung von Arve Waltin sieht gut aus, obwohl ich sie noch nicht getestet habe. Es gibt eine andere Lösung, falls Sie Probleme haben, dies zum Laufen zu bringen ... Erweitern Sie AlertDialog.Builder Und überschreiben Sie alle Methoden (z. B. setText, setTitle, setView, etc), um nicht den eigentlichen Text/Titel/die eigentliche Ansicht des Dialogs festzulegen, sondern um eine neue Ansicht in der Ansicht des Dialogs zu erstellen. Dann können Sie alles nach Ihren Wünschen gestalten.

Um zu verdeutlichen, was die übergeordnete Klasse betrifft, ist die Ansicht festgelegt und sonst nichts.

In Ihrer benutzerdefinierten erweiterten Klasse wird alles in dieser Ansicht ausgeführt.

2
Steven L

Dies kann einfach mit dem setView () des Builders geschehen. Sie können eine beliebige Ansicht Ihrer Wahl erstellen und in den Builder einspeisen. Das funktioniert gut. Ich verwende eine benutzerdefinierte Textansicht, die vom Dialog-Generator gerendert wird. Ich habe die Nachricht nicht gesetzt und dieser Bereich wird zum Rendern meiner benutzerdefinierten Textansicht verwendet.

0
AKh