2010-03-11 10 views
180

Mi chiedevo se qualcuno potesse darmi una mano. Sto cercando di creare un AlertDialog personalizzato. Per fare questo, ho aggiunto la seguente riga di codice in styles.xmlCome cambiare tema per AlertDialog

<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 si trova nella cartella drawable. Questo è disponibile anche nella cartella di ricerca di Android SDK.

Quanto segue è l'attività principale.

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

Al fine di applicare il tema a un AlertDialog, ho dovuto impostare il tema al contesto attuale.

Tuttavia, proprio non riesco a ottenere l'applicazione per mostrare AlertDialog personalizzato. Qualcuno può aiutarmi con questo?

+0

E 'd'aiuto? http://androblip.huiges.nl/2010/05/09/theme-android-dialog/ – Karoly

+0

Ho trovato questo repository su github per essere molto utile: https://github.com/StylingAndroid/AlertDialog – esilver

risposta

6

Suppongo che non si possa fare. Almeno non con il costruttore. Sto lavorando con 1.6 e l'attuazione in Builder.create() è:

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

che chiama il costruttore "non-theme-aware" di AlertDialog, che assomiglia a questo:

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

C'è un secondo costruttore in AlertDialog per cambiare temi:

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

che il costruttore non chiama.

Se la finestra di dialogo è abbastanza generica, proverei a scrivere una sottoclasse di AlertDialog, chiamando il secondo costruttore e utilizzi quella classe invece del meccanismo del generatore.

+0

Stessa situazione nel 2.2.2 – Silver

310

In Dialog.java (src Android) viene utilizzato ContextThemeWrapper. Così si potrebbe copiare l'idea e fare qualcosa di simile:

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

E poi lo stile è come si vuole:

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

Non utilizzare @android: style/AlertDialog. Non è nell'API pubblica. Di conseguenza, in Android 2.3.3, si blocca durante la creazione del builder. –

+17

@kaciula È '@android: style/Theme.Dialog' pubblico? Può essere usato invece? – HRJ

+22

Sì. È pubblico Controlla http://developer.android.com/reference/android/R.style.html per un elenco di tutti gli stili pubblici. Tieni presente che la denominazione nell'API è diversa da quella utilizzata nel codice. C'è un "_" invece di "." (Theme_Dialog) –

84

ho avuto questo problema relativo AlertDialog tema utilizzando SDK 1.6 come descritto qui: http://markmail.org/message/mj5ut56irkrkc4nr

ho risolto il problema nel modo seguente:

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

Spero che questo aiuti.

+3

Ha funzionato per me. Grazie. –

+1

Eccellente. Proprio quello di cui avevo bisogno con il minimo sforzo. – Darren

+1

Ci sono diversi temi rilevanti; nel mio caso, Android.R.style.Theme_Holo_Dialog era più adatto. Ottimo consiglio. –

31

Ero alle prese con questo: puoi modificare lo sfondo della finestra di dialogo utilizzando android:alertDialogStyle="@style/AlertDialog" nel tema, ma ignora qualsiasi impostazione di testo che hai. Come @rflexor ha detto sopra, non può essere fatto con l'SDK prima di Honeycomb (beh, potresti usare Reflection).

La mia soluzione, in poche parole, era quella di definire lo sfondo della finestra di dialogo utilizzando il precedente, quindi impostare un titolo personalizzato e una vista del contenuto (utilizzando layout uguali a quelli dell'SDK).

mio involucro:

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 (tratto dal 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> 

poi basta usare CustomAlertDialogBuilder invece di AlertDialog.Builder per creare la tua finestre di dialogo e chiama semplicemente setTitle e setMessage come al solito.

+3

come hai avuto accesso a android.R.internal.id.alerttitle? – Gilbert

+2

Non l'ho fatto, ho visitato R.id.alertTitle –

0

Può essere fatto semplicemente utilizzando setView del Builder(). Puoi creare qualsiasi vista a tua scelta e inserirla nel costruttore. Funziona bene Io uso un TextView personalizzato che viene visualizzato dal generatore di finestre di dialogo. Non ho impostato il messaggio e questo spazio è utilizzato per rendere la mia vista testuale.

3

Chiunque cercando di fare questo all'interno di un frammento (utilizzando la libreria di supporto IE pre API 11) dovrebbe andare con questo:

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 mi ha dato la spinta per estendere AlertDialog ed esporre il costruttore, grazie

+0

Il costruttore 'AlertDialog.Builder (Context, int)' funziona solo su API 11 e successive. Il tuo codice si bloccherà nelle versioni precedenti di Android. –

+0

@JosephEarl ** (utilizzando la libreria di supporto i.e. pre API 11) ** – Blundell

+0

Il mio male, si utilizza il costruttore di finestre di dialogo e ** non ** il costruttore di finestre di dialogo. –

2

La soluzione di Arve Waltin sembra buona, anche se non l'ho ancora testata. Esiste un'altra soluzione nel caso in cui abbiate problemi nel far funzionare il dispositivo .... Estendere AlertDialog.Builder e sovrascrivere tutti i metodi (ad esempio setText, setTitle, setView, ecc.) Per non impostare il testo/titolo/vista effettivo della finestra di dialogo, ma per creare una nuova vista all'interno del Dialog's View fa tutto ciò che c'è dentro. Allora sei libero di disegnare tutto come ti pare.

Per chiarire, per quanto riguarda la classe genitore, la vista è impostata, e nient'altro.

Per quanto riguarda la classe estesa personalizzata, tutto viene eseguito all'interno di quella vista.

40

Ho scritto un article nel mio blog su come configurare il layout di un AlertDialog con file di stile XML. Il problema principale è che sono necessarie definizioni di stile diverse per diversi parametri di layout. Di seguito è riportato uno standard di base basato sullo stile AlertDialog di Holo Light Platform versione 19 per un file di stile che dovrebbe coprire una serie di aspetti di layout standard come le dimensioni del testo e i colori di sfondo.

<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> 
+1

Posso chiederti perché entrambi abbiamo bisogno di stile e tema per la personalizzazione di AlertDialog? Molte grazie! @nantoka – brainvision

+1

@brainvision Il mio post di blog ha i dettagli ma in poche parole il layout di un AlertDialog proviene da due classi diverse (Dialog e AlertController) che utilizzano diversi file di layout param. – Nantoka

+0

FYI, MyBorderlessButton.textSize non funziona. – arsent

4

modo migliore per fare questo dialogo personalizzato utilizzare e personalizzare in base alle vostre esigenze qui è personalizzato dialogo esempio .....

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

}

Ecco il layout 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

Il tema e l'utilizzo di una vista personalizzata sono 2 cose diverse e hanno scopi diversi. – jmc34

11
<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(); 
+0

Soluzione semplicistica, ma veloce! – FonzTech

+0

OK, che ne dici di utilizzare qualche attributo per dichiararlo globalmente in "AppTheme"? – deadfish

0

Per di dialogo personalizzate:

basta chiamare super(context,R.style.<dialog style>) invece di super(context) nella finestra costruttore

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


Per AlertDialog:

basta creare alertDialog con questo costruttore:

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

È possibile assegnare direttamente un tema quando si avvia il Generatore:

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

quindi personalizzare il tema nel vostro 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
AlertDialog.Builder builder = new AlertDialog.Builder(this);`enter code here` 
builder.setTitle("Title");`enter code here` 
builder.setMessage("Description");`enter code here` 
builder.setPositiveButton("OK", null);`enter code here` 
builder.setNegativeButton("Cancel", null);`enter code here` 
builder.show();`enter code here` 
+0

Ti dispiace formattare il codice con lo snippet di codice incorporato? – Adriano