We are trying to set the title of a dialog to have a custom font so we tried doing a theme with the following:
<style name="DialogTheme" parent="Theme.AppCompat.Dialog.Alert">
<item name="android:windowTitleStyle">#style/Dialog.Title</item>
</style>
<style name="Dialog.Title" parent="RtlOverlay.DialogWindowTitle.AppCompat">
<item name="android:textAppearance">#style/Dialog.TextAppearance.Title</item>
</style>
<style name="Dialog.TextAppearance.Title" parent="TextAppearance.AppCompat.Title">
<item name="fontFamily">#font/custom_font</item>
</style>
And we are creating the dialog builder like this:
AlertDialog.Builder(ContextThemeWrapper(context, R.style.DialogTheme), R.style.DialogTheme)
The style and text appearance are completely ignored. For other styles, it seems to be working.
We managed to make it work by copying the layout used by AppCompat and adding it as a custom title:
<?xml version="1.0" encoding="utf-8"?>
<!-- modified from AppCompat's abc_alert_dialog_title_material.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical|start|left"
android:paddingLeft="?attr/dialogPreferredPadding"
android:paddingRight="?attr/dialogPreferredPadding"
android:paddingTop="#dimen/abc_dialog_padding_top_material">
<TextView
android:id="#+id/alertTitle"
style="#style/Dialog.Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
tools:text="Some title" />
</FrameLayout>
Based on this: abc_alert_dialog_title_material.xml
Instead of using DialogTitle here we are using TextView. What DialogTitle is overloading onMeasure with the following:
final Layout layout = getLayout();
if (layout != null) {
final int lineCount = layout.getLineCount();
if (lineCount > 0) {
final int ellipsisCount = layout.getEllipsisCount(lineCount - 1);
if (ellipsisCount > 0) {
setSingleLine(false);
setMaxLines(2);
final TypedArray a = getContext().obtainStyledAttributes(null,
R.styleable.TextAppearance,
android.R.attr.textAppearanceMedium,
android.R.style.TextAppearance_Medium);
final int textSize = a.getDimensionPixelSize(
R.styleable.TextAppearance_android_textSize, 0);
if (textSize != 0) {
// textSize is already expressed in pixels
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
a.recycle();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
We think it's related with it setting the text size, but we are not sure. We have a working hack (with the copied layout). However, we would prefer to know how we can make it work with xml styles and themes instead of having to change the default behaviour.
From my answer to another question I just posted recently, this is how I was able to programmatically set the font of all attributes of an AlertDialog. Hope it works for you.
Typeface semibold = ResourcesCompat.getFont(this, R.font.product_bold);
Typeface regular = ResourcesCompat.getFont(this, R.font.product_regular);
AlertDialog myDialog = new AlertDialog.Builder(this).setTitle("Your title")
.setMessage("Your message.")
.setPositiveButton("Your button", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//your code
}
}).show();
int titleText = getResources().getIdentifier("alertTitle", "id", "android");
((TextView) myDialog.getWindow().findViewById(titleText)).setTypeface(semibold);
TextView dialogMessage = myDialog.getWindow().findViewById(android.R.id.message);
Button dialogButton = myDialog.getWindow().findViewById(android.R.id.button1);
dialogMessage.setTypeface(regular);
dialogButton.setTypeface(semibold);
Confirmed working on Android 9.0, can't claim for it to work on older APIs.
Another method of programmatically setting the title with a TextView, this is how I used to do it:
TextView alertTitle = findViewById(R.id.alertTextTemp);
if (alertTitle.getParent() != null) {
((ViewGroup) alertTitle.getParent()).removeView(alertTitle);
}
alertTitle.setText("Warning");
alertTitle.setVisibility(View.VISIBLE);
alertTitle.setTypeface(semibold);
Then when you create your dialog, you set a custom title with:
new AlertDialog.Builder(MainActivity.this).setCustomTitle(alertTitle)...
alertTitle being a TextView in your activity_main.xml file:
<TextView
android:id="#+id/alertTextTemp"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:paddingLeft="23dp"
android:paddingTop="22dp"
android:textColor="#000000" />
Those attributes on the TextView I had to fine tune to get it as close to the default title margins and size as possible, you might want to verify it works for you.
Related
I implemented a DialogPreference exactly the way it is explained in http://www.lukehorvat.com/blog/android-seekbardialogpreference
Additionally I was able to change the text- and divider color of the DialogPreference, but I couldn't change the highlighting color of the buttons when they are pressed. Does anybody know how to do this?
Update:
I use the following layout for the DialogPreference:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/text_dialog_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"/>
<TextView
android:id="#+id/text_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dip"
android:gravity="center_horizontal"/>
<SeekBar
android:id="#+id/seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dip"
android:layout_marginTop="6dip"/>
</LinearLayout>
The only style attributes regarding this DialogPreference or the layout I change so far are changed programatically:
int alertTitleId = this.getContext().getResources().getIdentifier("alertTitle", "id", "android");
TextView alertTitle = (TextView) getDialog().getWindow().getDecorView().findViewById(alertTitleId);
alertTitle.setTextColor(color); // change title text color
int titleDividerId = this.getContext().getResources().getIdentifier("titleDivider", "id", "android");
View titleDivider = getDialog().getWindow().getDecorView().findViewById(titleDividerId);
titleDivider.setBackgroundColor(color); // change divider color
All you need to do is subclass DialogPreference, then call Resource.getIdentifier to locate each View you want to theme, much like you're doing, but you don't need to call Window.getDecorView. Here's an example:
Custom DialogPreference
public class CustomDialogPreference extends DialogPreference {
public CustomDialogPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* {#inheritDoc}
*/
#Override
protected void showDialog(Bundle state) {
super.showDialog(state);
final Resources res = getContext().getResources();
final Window window = getDialog().getWindow();
final int green = res.getColor(android.R.color.holo_green_dark);
// Title
final int titleId = res.getIdentifier("alertTitle", "id", "android");
final View title = window.findViewById(titleId);
if (title != null) {
((TextView) title).setTextColor(green);
}
// Title divider
final int titleDividerId = res.getIdentifier("titleDivider", "id", "android");
final View titleDivider = window.findViewById(titleDividerId);
if (titleDivider != null) {
titleDivider.setBackgroundColor(green);
}
// Button views
window.findViewById(res.getIdentifier("button1", "id", "android"))
.setBackgroundDrawable(res.getDrawable(R.drawable.your_selector));
window.findViewById(res.getIdentifier("button2", "id", "android"))
.setBackgroundDrawable(res.getDrawable(R.drawable.your_selector));
window.findViewById(res.getIdentifier("button3", "id", "android"))
.setBackgroundDrawable(res.getDrawable(R.drawable.your_selector));
}
}
XML preferences
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<path_to.CustomDialogPreference
android:dialogMessage="Message"
android:negativeButtonText="Cancel"
android:positiveButtonText="Okay"
android:title="Title" />
</PreferenceScreen>
Custom selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true">
<item android:drawable="#drawable/your_pressed_drawable" android:state_pressed="true"/>
<item android:drawable="#drawable/your_default_drawable"/>
</selector>
Alternate selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true">
<item android:drawable="#color/your_pressed_color" android:state_pressed="true"/>
<item android:drawable="#color/your_default_color/>
</selector>
Screenshot
If you fail to find a solution for styling the built-in buttons to your liking, you could actually add a button row to the bottom of your custom layout, which looks and acts exactly like the built-in one. Then set your button listeners to your custom button bar's buttons, which will result in no built-in button bar.
In this way you can make them look however you want!
I you can try this Answer. Here you don't need write code just need customise AlertDialog theme.
After customisation theme it may be applicable for your complete application.
I am wondering how it is possible to get rid of (or change color) titleDivider in Dialog. It is a blue line below dialog title shown on honeycomb+ devices.
I guess this is relevant piece of layout from SDK, but since there is no style attribute I dont know how to style it. If i try with findViewById there is no android.R.id.titleDivider
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<TextView android:id="#android:id/title" style="?android:attr/windowTitleStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="#android:dimen/alert_dialog_title_height"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:gravity="center_vertical|left" />
<View android:id="#+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
android:background="#android:color/holo_blue_light" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:foreground="?android:attr/windowContentOverlay">
<FrameLayout android:id="#android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
I have tried to override dialogTitleDecorLayout which is only reference to dialog_title_holo.xml in my theme.xml, but without success. Error is:
error: Error: No resource found that matches the given name: attr
'dialogTitleDecorLayout'.
To get a reference to titleDivider of AlertDialog to change its color:
int divierId = dialog.getContext().getResources()
.getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(divierId);
divider.setBackgroundColor(getResources().getColor(R.color.creamcolor));
You need to implement
myDialog = builder.create();
myDialog.setOnShowListener(new OnShowListenerMultiple());
//----------------------------
//Function to change the color of title and divider of AlertDialog
public static class OnShowListenerMultiple implements DialogInterface.OnShowListener {
#Override
public void onShow( DialogInterface dialog ) {
if( !(dialog instanceof Dialog) )
return;
Dialog d = ((Dialog) dialog);
final Resources resources = d.getContext().getResources();
final int color = AppUtility.getColor( resources, R.color.defaultColor );
try {
int titleId = resources.getIdentifier( "android:id/alertTitle", null, null );
TextView titleView = d.findViewById( titleId );
titleView.setTextColor( color );
}
catch( Exception e ) {
Log.e( "XXXXXX", "alertTitle could not change color" );
}
try {
int divierId = resources.getIdentifier( "android:id/titleDivider", null, null );
View divider = d.findViewById( divierId );
divider.setBackgroundColor( color );
}
catch( Exception e ) {
Log.e( "XXXXXX", "titleDivider could not change color" );
}
}
}
I solved the issue by using DialogFragment.STYLE_NO_TITLE theme and then faking title bar in dialog layout.
Here is how I resolved that (thanks to http://joerg-richter.fuyosoft.com/?p=181 ):
MyDialogBuilder.class
public class MyDialogBuilder extends android.app.AlertDialog.Builder {
public MyDialogBuilder(Context context) {
super(context);
}
#NonNull
#Override
public android.app.AlertDialog create() {
final android.app.AlertDialog alertDialog = super.create();
alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
int titleDividerId = getContext().getResources()
.getIdentifier("titleDivider", "id", "android");
View titleDivider = alertDialog.findViewById(titleDividerId);
if (titleDivider != null) {
titleDivider.setBackgroundColor(getContext().getResources()
.getColor(R.color.alert_dialog_divider));
}
}
});
return alertDialog;
}
}
use
<View android:id="#+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
android:background=#CC3232 />
Before write dialog.show(), write:
int divierId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(divierId);
if(divider!=null){
divider.setBackgroundColor(getResources().getColor(R.color.transparent));}
In colors.xml:
<color name="transparent">#00000000</color>
If you don't want to use Default style, don't use AlertDialog. You could go with Activity(with your custom layout) with Dialog Theme.
<activity android:theme="#android:style/Theme.Dialog">
This one is tested on some 4.x devices:
TextView title = (TextView)getWindow().getDecorView().findViewById(android.R.id.title);
((ViewGroup)title.getParent()).getChildAt(1).setVisibility(View.GONE);
Your idea was correct. However, dialogTitleDecorLayout you were looking for is a private resource, so you can't access it in a normal way. But you still can access it using * syntax:
<item name="*android:dialogTitleDecorLayout">#layout/dialog_title</item>
Adding this to my own style and simply copying dialog_title.xml to my app and changing it slightly solved the problem in my case.
Do you watchthis and there is a pcecial library for that, you can watch it there. And the last link will solve you problem
you can make a custom dialog like this:
Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.custom_dialog);
Button okay = (Button) dialog.findViewById(R.id.button1);
okay.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// do your work
}
});
Set a custom title in layout don't use android
dialog.setTitle();
and your custom_dialog.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android1="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="40sp"
android:text="Hello"/>
<Button
android:id="#+id/button1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginLeft="150dp"
android:text="OK" />
</RelativeLayout>
"Removing the blue line" if I guess correctly means dropping the border between the title of the dialog and it's body. That border come from the Holo theme, so it's not possible to drop it without using your custom layout.
Create a file named custom-dialog.xml with the following content (it's just an example..modify it as you want):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/general_dialog_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/dialogTopImage"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.12"
android:padding="10dp" />
<LinearLayout
android:id="#+id/dialogLine"
android:layout_width="fill_parent"
android:layout_height="3dp"
android:background="#drawable/green_btn"
android:orientation="vertical" />
<TextView
android:id="#+id/dialogText"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.32"
android:padding="5dp"
android:text=""
/>
<LinearLayout
android:id="#+id/general_dialog_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:layout_weight="0.11"
android:gravity="center"
android:orientation="horizontal" >
<Button
android:id="#+id/dialogButton"
android:layout_width="100dp"
android:textSize="8pt"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:background="#drawable/green_btn"
android:gravity="center"
android:text="Ok" />
</LinearLayout>
As you see I'm using resources and stuff that won't be in your project, but you can remove them safely. The result in my case is more or less the following one, with an image at top that I'll programatically set in the code.
To create the dialog then use something like:
private Dialog createAndShowCustomDialog(String message, Boolean positive, Drawable d, View.OnClickListener cl, String text1) {
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.general_dialog_layout);
// BIND
ImageView image = (ImageView) dialog.findViewById(R.id.dialogTopImage);
TextView text = (TextView) dialog.findViewById(R.id.dialogText);
Button button = (Button) dialog.findViewById(R.id.dialogButton);
LinearLayout line = (LinearLayout) dialog.findViewById(R.id.dialogLine);
// SET WIDTH AND HEIGHT
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = (int) (displaymetrics.widthPixels * 0.85);
int height = (int) (displaymetrics.heightPixels * 0.60);
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = width;
dialog.getWindow().setLayout(width, height);
// SET TEXTS
text.setText(message);
button.setText(text1);
// SET IMAGE
if (d == null) {
image.setImageDrawable(getResources().getDrawable(R.drawable.font_error_red));
} else {
image.setImageDrawable(d);
}
// SET ACTION
if (cl == null) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
} else {
button.setOnClickListener(cl);
}
// SHOW
dialog.show();
return dialog;
}
These is no way hiding it by control brotha.. I've had the same problem. only thing you can do is create your own CustomDialog
Here is a sample App
Download and have look at the design pattern, then it will be easy
Here is one Tutorial About making Custom Dialog
Important part is after creating the DialogObject don't set the Title by setTitle()
create TextView inside your CustomLayout and call it from findViewByID() and set your title
In colors.xml:
<color name="transparent">#00000000</color>
In dialog:
int divierId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider",null, null);
View divider = d.findViewById(divierId);
divider.setBackgroundColor(getResources().getColor(R.color.transparent));
In order to hide the default blue line completely (assuming you're in DialogFragment):
Dialog dialog = getDialog();
if (dialog != null) {
final int dividerId = dialog.getContext().getResources()
.getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(dividerId);
if (divider != null) {
divider.setBackground(null);
}
}
I see to set the text color of the action mode "done" / "close" button. This is what I've tried:
<item name="android:actionModeCloseButtonStyle">#style/ActionModeCloseButton</item>
....
<style name="ActionModeCloseButton" parent="android:style/Widget.Holo.ActionButton.CloseMode">
<item name="android:textColor">#android:color/white</item>
</style>
but is has no effect.
Note that on JB, it's enough that I make the ActionModeCloseButton style's parent the regular holo theme. It works fine there (without the textColor setting even).
Any ideas?
First of all, the textview "Done" is only visible on large devices.
Checkout action_mode_close_item.xml in the Android source.
So the android:actionModeCloseButtonStyle only applies to the containing view and not the imageview and the textview.
Luckily, the android engineers used publicly accessible attributes to styles the childviews.
Use android:actionMenuTextColor to change to textColor of the TextView.
Use android:actionModeCloseDrawable to change the drawable of the ImageView
Example:
<style name="MyTheme">
<item name="android:actionMenuTextColor">#ff000000</item>
<item name="android:actionModeCloseDrawable">#drawable/my_close_drawable</item>
</style>
Below is a copy of the action_mode_close_item.xml in the layout-large-folder where you can see how the layout is build.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/action_mode_close_button"
android:focusable="true"
android:clickable="true"
android:paddingStart="8dip"
style="?android:attr/actionModeCloseButtonStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="16dip">
<ImageView android:layout_width="48dip"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:scaleType="center"
android:src="?android:attr/actionModeCloseDrawable" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="4dip"
android:layout_marginEnd="16dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/actionMenuTextColor"
android:textSize="12sp"
android:textAllCaps="true"
android:text="#string/action_mode_done" />
</LinearLayout>
Since the layout for the action mode close button doesn't provide a color attribute for the text view, there is no way to set this color in a custom theme. Instead the only ay I found was to overwrite the text color in the onPrepareActionMode() method of my derived ActionMode class:
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... none) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
return null;
}
#Override
protected void onPostExecute(Void none) {
if (activity != null) {
LinearLayout layout = (LinearLayout) activity
.findViewById(R.id.abs__action_mode_close_button);
if (layout == null) {
int id = Resources.getSystem().getIdentifier(
"action_mode_close_button", "id", "android");
layout = (LinearLayout) activity.findViewById(id);
}
if (layout != null && layout.getChildCount() > 1) {
TextView label = (TextView) layout.getChildAt(1);
if (label != null) label.setTextColor(Color.RED);
}
}
}
}.execute();
return false;
}
Worked with two devices pre and post Android 4.0.
I am wondering how it is possible to get rid of (or change color) titleDivider in Dialog. It is a blue line below dialog title shown on honeycomb+ devices.
I guess this is relevant piece of layout from SDK, but since there is no style attribute I dont know how to style it. If i try with findViewById there is no android.R.id.titleDivider
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<TextView android:id="#android:id/title" style="?android:attr/windowTitleStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="#android:dimen/alert_dialog_title_height"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:gravity="center_vertical|left" />
<View android:id="#+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
android:background="#android:color/holo_blue_light" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:foreground="?android:attr/windowContentOverlay">
<FrameLayout android:id="#android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
I have tried to override dialogTitleDecorLayout which is only reference to dialog_title_holo.xml in my theme.xml, but without success. Error is:
error: Error: No resource found that matches the given name: attr
'dialogTitleDecorLayout'.
To get a reference to titleDivider of AlertDialog to change its color:
int divierId = dialog.getContext().getResources()
.getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(divierId);
divider.setBackgroundColor(getResources().getColor(R.color.creamcolor));
You need to implement
myDialog = builder.create();
myDialog.setOnShowListener(new OnShowListenerMultiple());
//----------------------------
//Function to change the color of title and divider of AlertDialog
public static class OnShowListenerMultiple implements DialogInterface.OnShowListener {
#Override
public void onShow( DialogInterface dialog ) {
if( !(dialog instanceof Dialog) )
return;
Dialog d = ((Dialog) dialog);
final Resources resources = d.getContext().getResources();
final int color = AppUtility.getColor( resources, R.color.defaultColor );
try {
int titleId = resources.getIdentifier( "android:id/alertTitle", null, null );
TextView titleView = d.findViewById( titleId );
titleView.setTextColor( color );
}
catch( Exception e ) {
Log.e( "XXXXXX", "alertTitle could not change color" );
}
try {
int divierId = resources.getIdentifier( "android:id/titleDivider", null, null );
View divider = d.findViewById( divierId );
divider.setBackgroundColor( color );
}
catch( Exception e ) {
Log.e( "XXXXXX", "titleDivider could not change color" );
}
}
}
I solved the issue by using DialogFragment.STYLE_NO_TITLE theme and then faking title bar in dialog layout.
Here is how I resolved that (thanks to http://joerg-richter.fuyosoft.com/?p=181 ):
MyDialogBuilder.class
public class MyDialogBuilder extends android.app.AlertDialog.Builder {
public MyDialogBuilder(Context context) {
super(context);
}
#NonNull
#Override
public android.app.AlertDialog create() {
final android.app.AlertDialog alertDialog = super.create();
alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
int titleDividerId = getContext().getResources()
.getIdentifier("titleDivider", "id", "android");
View titleDivider = alertDialog.findViewById(titleDividerId);
if (titleDivider != null) {
titleDivider.setBackgroundColor(getContext().getResources()
.getColor(R.color.alert_dialog_divider));
}
}
});
return alertDialog;
}
}
use
<View android:id="#+id/titleDivider"
android:layout_width="match_parent"
android:layout_height="2dip"
android:background=#CC3232 />
Before write dialog.show(), write:
int divierId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(divierId);
if(divider!=null){
divider.setBackgroundColor(getResources().getColor(R.color.transparent));}
In colors.xml:
<color name="transparent">#00000000</color>
If you don't want to use Default style, don't use AlertDialog. You could go with Activity(with your custom layout) with Dialog Theme.
<activity android:theme="#android:style/Theme.Dialog">
This one is tested on some 4.x devices:
TextView title = (TextView)getWindow().getDecorView().findViewById(android.R.id.title);
((ViewGroup)title.getParent()).getChildAt(1).setVisibility(View.GONE);
Your idea was correct. However, dialogTitleDecorLayout you were looking for is a private resource, so you can't access it in a normal way. But you still can access it using * syntax:
<item name="*android:dialogTitleDecorLayout">#layout/dialog_title</item>
Adding this to my own style and simply copying dialog_title.xml to my app and changing it slightly solved the problem in my case.
Do you watchthis and there is a pcecial library for that, you can watch it there. And the last link will solve you problem
you can make a custom dialog like this:
Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.custom_dialog);
Button okay = (Button) dialog.findViewById(R.id.button1);
okay.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// do your work
}
});
Set a custom title in layout don't use android
dialog.setTitle();
and your custom_dialog.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android1="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="40sp"
android:text="Hello"/>
<Button
android:id="#+id/button1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginLeft="150dp"
android:text="OK" />
</RelativeLayout>
"Removing the blue line" if I guess correctly means dropping the border between the title of the dialog and it's body. That border come from the Holo theme, so it's not possible to drop it without using your custom layout.
Create a file named custom-dialog.xml with the following content (it's just an example..modify it as you want):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/general_dialog_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/dialogTopImage"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.12"
android:padding="10dp" />
<LinearLayout
android:id="#+id/dialogLine"
android:layout_width="fill_parent"
android:layout_height="3dp"
android:background="#drawable/green_btn"
android:orientation="vertical" />
<TextView
android:id="#+id/dialogText"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.32"
android:padding="5dp"
android:text=""
/>
<LinearLayout
android:id="#+id/general_dialog_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:layout_weight="0.11"
android:gravity="center"
android:orientation="horizontal" >
<Button
android:id="#+id/dialogButton"
android:layout_width="100dp"
android:textSize="8pt"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:background="#drawable/green_btn"
android:gravity="center"
android:text="Ok" />
</LinearLayout>
As you see I'm using resources and stuff that won't be in your project, but you can remove them safely. The result in my case is more or less the following one, with an image at top that I'll programatically set in the code.
To create the dialog then use something like:
private Dialog createAndShowCustomDialog(String message, Boolean positive, Drawable d, View.OnClickListener cl, String text1) {
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.general_dialog_layout);
// BIND
ImageView image = (ImageView) dialog.findViewById(R.id.dialogTopImage);
TextView text = (TextView) dialog.findViewById(R.id.dialogText);
Button button = (Button) dialog.findViewById(R.id.dialogButton);
LinearLayout line = (LinearLayout) dialog.findViewById(R.id.dialogLine);
// SET WIDTH AND HEIGHT
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = (int) (displaymetrics.widthPixels * 0.85);
int height = (int) (displaymetrics.heightPixels * 0.60);
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = width;
dialog.getWindow().setLayout(width, height);
// SET TEXTS
text.setText(message);
button.setText(text1);
// SET IMAGE
if (d == null) {
image.setImageDrawable(getResources().getDrawable(R.drawable.font_error_red));
} else {
image.setImageDrawable(d);
}
// SET ACTION
if (cl == null) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
} else {
button.setOnClickListener(cl);
}
// SHOW
dialog.show();
return dialog;
}
These is no way hiding it by control brotha.. I've had the same problem. only thing you can do is create your own CustomDialog
Here is a sample App
Download and have look at the design pattern, then it will be easy
Here is one Tutorial About making Custom Dialog
Important part is after creating the DialogObject don't set the Title by setTitle()
create TextView inside your CustomLayout and call it from findViewByID() and set your title
In colors.xml:
<color name="transparent">#00000000</color>
In dialog:
int divierId = dialog.getContext().getResources().getIdentifier("android:id/titleDivider",null, null);
View divider = d.findViewById(divierId);
divider.setBackgroundColor(getResources().getColor(R.color.transparent));
In order to hide the default blue line completely (assuming you're in DialogFragment):
Dialog dialog = getDialog();
if (dialog != null) {
final int dividerId = dialog.getContext().getResources()
.getIdentifier("android:id/titleDivider", null, null);
View divider = dialog.findViewById(dividerId);
if (divider != null) {
divider.setBackground(null);
}
}
I'm working on an Android app and I have an AlertDialog subclass. I would like to put 2 ImageButtons on the right side of the title area of the dialog (similar to an the ActionBar in an Activity). I'm using setCustomTitle() to do this, which replaces the title area with a custom view of my own creation. This works fine, but the styling of my custom title area is not the same as the standard title styling (height, color, separator, etc).
My question is: with the understanding that styling varies by OS version and manufacturer, how can I style my custom title in the dialog so that it will match the standard title styling for other AlertDialogs?
Here is an image of anAlertDialog with standard styling (this is from ICS, but I want to be able to match any variant -- not this particular style)
And here is an image of an AlertDialog with custom title and buttons (note how the title height and color don't match the standard dialog)
EDIT: I can't just add the ImageButtons to the standard title view, because I don't have access to it. If you know of a (reliable, non-hack) method for me to add buttons to the standard title area, I would accept that as well.
Given that there is new interest in this question, let me elaborate about how I "solved" this.
First, I use ActionBarSherlock in my app. This is not necessary, I suppose, though it helps a lot because the styles and themes defined in the ABS project allow me to mimic the Holo theme on pre-ICS devices, which provides a consistent experience in the app.
Second, my "dialog" is no longer a dialog -- it's an activity themed as a dialog. This makes manipulation of the view hierarchy simpler, because I have complete control. So adding buttons to the title area is now trivial.
Here are the screenshots (2.2 device and 4.1 emulator). Note that the only significant styling difference is the EditText, which I have chosen not to address.
Here is my onCreate in my dialog activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_tag);
setTitle(R.string.tag_dialog_title);
View sherlockTitle = findViewById(android.R.id.title);
if (sherlockTitle != null) {
sherlockTitle.setVisibility(View.GONE);
}
View sherlockDivider = findViewById(R.id.abs__titleDivider);
if (sherlockDivider != null) {
sherlockDivider.setVisibility(View.GONE);
}
// setup custom title area
final View titleArea = findViewById(R.id.dialog_custom_title_area);
if (titleArea != null) {
titleArea.setVisibility(View.VISIBLE);
TextView titleView = (TextView) titleArea.findViewById(R.id.custom_title);
if (titleView != null) {
titleView.setText(R.string.tag_dialog_title);
}
ImageButton cancelBtn = (ImageButton) titleArea.findViewById(R.id.cancel_btn);
cancelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
cancelBtn.setVisibility(View.VISIBLE);
ImageButton okBtn = (ImageButton) titleArea.findViewById(R.id.ok_btn);
okBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do stuff here
finish();
}
});
okBtn.setVisibility(View.VISIBLE);
}
}
And here is the relevant layout for the activity:
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<LinearLayout
android:id="#+id/dialog_custom_title_area"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingRight="10dp">
<TextView
android:id="#+id/custom_title" style="?android:attr/windowTitleStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="#dimen/abs__alert_dialog_title_height"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:textColor="#ffffff"
android:gravity="center_vertical|left" />
<ImageButton
android:id="#+id/ok_btn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="#dimen/abs__action_button_min_width"
android:minHeight="#dimen/abs__alert_dialog_title_height"
android:scaleType="center"
android:src="#drawable/ic_action_accept"
android:background="#drawable/abs__item_background_holo_dark"
android:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="#string/acc_done"/>
<ImageButton
android:id="#+id/cancel_btn"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:minWidth="#dimen/abs__action_button_min_width"
android:minHeight="#dimen/abs__alert_dialog_title_height"
android:scaleType="center"
android:src="#drawable/ic_action_cancel"
android:background="#drawable/abs__item_background_holo_dark"
android:visibility="visible"
android:layout_gravity="center_vertical"
android:contentDescription="#string/acc_cancel"
/>
</LinearLayout>
<View
android:id="#+id/dialog_title_divider"
android:layout_width="fill_parent"
android:layout_height="2dip"
android:background="#color/abs__holo_blue_light" />
</LinearLayout>
<RelativeLayout
android:id="#+id/list_suggestions_layout"
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<!-- this is where the main dialog area is laid out -->
</RelativeLayout>
</LinearLayout>
And finally, in my AndroidManifext.xml, here is how I define my TagActivity:
<activity
android:icon="#drawable/ic_home"
android:name=".activity.TagActivity"
android:theme="#style/Theme.Sherlock.Dialog"/>
OK, maybe it is not the super perfect solution and maybe it is a bad solution, but I tried this on android 2.3.7 and android 4.1.2:
2.3.7 (real device)
4.1.2 (emulator)
We start by creating a dialog Title style to make sure we have some space for our icons:
res/values/dialogstyles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Dialog" parent="#android:style/Theme.Dialog">
<item name="android:windowTitleStyle">#style/MyOwnDialogTitle</item>
</style>
<style name="MyOwnDialogTitle">
<!-- we need to make sure our images fit -->
<item name="android:layout_marginRight">100dp</item>
</style>
</resources>
res/values-v11/dialogstyles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Dialog" parent="#android:style/Theme.Holo.Dialog">
<item name="android:windowTitleStyle">#style/MyOwnDialogTitle</item>
</style>
</resources>
Then we create our DialogFragment with two tricks:
set the style in the onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, R.style.Dialog);
}
override onCreateView and add our layout (of buttons) to the Dialog (see comments)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//we need the view to remove the tree observer (that's why it is final)
final View view = inflater.inflate(R.layout.dialog_custom, container);
getDialog().setTitle("Shush Dialog");
//register a layout listener to add our buttons
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public void onGlobalLayout() {
//inflate our buttons
View menu = LayoutInflater.from(getActivity()).inflate(R.layout.layout_mymenu, null);
//get the root view of the Dialog (I am pretty sure this is the weakest link)
FrameLayout fl = ((FrameLayout) getDialog().getWindow().getDecorView());
//get the height of the root view (to estimate the height of the title)
int height = fl.getHeight() - fl.getPaddingTop() - fl.getPaddingBottom();
//to estimate the height of the title, we subtract our view's height
//we are sure we have the heights btw because layout is done
height = height - view.getHeight();
//prepare the layout params for our view (this includes setting its width)
//setting the height is not necessary if we ensure it is small
//we could even add some padding but anyway!
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height);
params.gravity = Gravity.RIGHT | Gravity.TOP;
//add the view and we are done
fl.addView(menu, params);
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
return view;
}
Alright if it just images, then you just have ensure that everything that you create in xml is scaled by density pixels or DP for short. Most simple coding that sets paint are usually set by pixels as well and may need a manual coding version to density pixels.