61

I need to make a AlertDialog with a custom view. The message of a AlertDialog has a default padding but when I set a view it has no padding, I want to get the same padding as the default as the message. I'm using a style that extends Holo theme (if this is relevant).

AlertDialog.Builder builder = new AlertDialog.Builder(PlaylistListView.this.getContext());
builder.setTitle("Title");
builder.setView(inflate(context, R.layout.music_player_create_dialog, null));
builder.setPositiveButton("OK", null);
builder.setNegativeButton("Cancel", null);
builder.show();

This is the layout for the content:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/abc_dialog_padding_material"
    android:paddingRight="@dimen/abc_dialog_padding_material"
    android:paddingTop="@dimen/abc_dialog_padding_top_material"
    android:paddingBottom="@dimen/abc_dialog_padding_top_material">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Title:"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom"
        android:background="@null"
        android:layout_marginTop="20dp"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@color/divider"/>
</LinearLayout>
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Ari M
  • 1,386
  • 3
  • 18
  • 33

3 Answers3

93

The ?dialogPreferredPadding attribute now has this value. It was introduced in API 22; see https://developer.android.com/sdk/api_diff/22/changes/android.R.attr.html.

You can get consistent padding in your custom dialogs by specifying this attribute on the dialog's layout. For example, android:paddingLeft="?dialogPreferredPadding" will bring the dialog's contents into alignment with its title.

trooper
  • 4,444
  • 5
  • 32
  • 32
  • 24
    This works perfectly, and I want to point out that the attribute is present in the support library if you use `?dialogPreferredPadding` instead of `?android:dialogPreferredPadding`. – Jarett Millard Oct 07 '16 at 14:21
  • 1
    What values is this setting? I suppose 24dp as it is currently the default value, but I am wondering if this set 20dp on Top as per material specs https://material.io/guidelines/components/dialogs.html#dialogs-specs – David Oct 19 '17 at 14:59
  • 2
    How to apply this programatically? in my case I use only AlertDialog.setAdapter(ListAdapter), no view whatsoever. – David Jun 13 '18 at 17:47
  • I guess we'll never know – Denny Nov 18 '18 at 00:17
26

I got stuck with the same problem, so had to find the answer. In case anyone comes looking for the answer, here is my solution.

The source code for AlertDialog's layout is described in alert_dialog.xml (e.g. here for android 4.4.1, which should correspond to Holo theme). Layout has hard-coded paddings (and they might be different in different versions of android). To know the default padding you have to sum up all paddings for Views containing id/message" TextView. In this case they are 3+14+5=22 dp left and 1+10+5=16 dp right.

The android:id/custom element is where a custom view gets inserted into and it has 3 dp left and 1 dp right paddings (from the root element, others do not have paddings) which you do not have to set manually.

So to have resulting padding of a custom View be the same as message's, set it to 19 dp left and 15 dp right (and don't forget to keep default 5 dp top and bottom padding).

Example code:

final EditText input = new EditText( getContext() );
float dpi = ctx.getResources().getDisplayMetrics().density;
AlertDialog dialog = (new AlertDialog.Builder(getContext()))
        .setTitle("Rename track")
        .setMessage("Track name:")
        .setPositiveButton("OK", null)
        .setNegativeButton("Cancel", null)
        .create();
dialog.setView(input, (int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi) );
dialog.show();

These code gives result like this (looks good). BTW, this is Material theme, which seems to have the same paddings (also hardcoded).

[]

Osman-pasha
  • 634
  • 8
  • 18
  • It's a coincidence that you answered only 23 hours ago as I was in the same muddle. Clearly the default layout is not well designed, but your answer works and makes it look much nicer, thank you. – Matthew Mitchell Feb 05 '16 at 19:49
  • 1
    @MatthewMitchell you welcome! Yes, the AlertDialog layout should probably have some ````@android:dimen/dialog_padding```` constants instead of hard-coded numbers, or force paddings to inserted views (first option is better, I think) – Osman-pasha Feb 08 '16 at 11:52
  • The compiler says @android:dimen/dialog_padding is not public. – Damn Vegetables Apr 18 '16 at 13:32
  • @Sin-jeong-hun it's not used in AlertDialog layout anyway, so it might contain different values than padding in AlertDialog – Osman-pasha Apr 20 '16 at 08:44
  • 3
    I used "?dialogPreferredPadding" in the paddingLeft paddingRight in my custom view Layout. – Alexey May 09 '16 at 08:41
  • In my case this code works: `View view = getLayoutInflater().inflate(R.layout.dialog_deferred, null); float dpi = getResources().getDisplayMetrics().density; view.setPadding((int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi)); builder.setView(view);` – pablogupi Mar 23 '17 at 11:52
10

Just to add a more complete answer of how to use it:

You can use in the layout XML file android:paddingStart="?dialogPreferredPadding" and android:paddingEnd="?dialogPreferredPadding" .

Alternatively, if you want to do it by code:

@JvmStatic
fun getDimensionFromAttribute(context: Context, attr: Int): Int {
    val typedValue = TypedValue()
    return if (context.theme.resolveAttribute(attr, typedValue, true)) 
           TypedValue.complexToDimensionPixelSize(typedValue.data, context.resources.displayMetrics) 
           else 0
}

usage:

val alertDialogPadding = getDimensionFromAttribute(context, R.attr.dialogPreferredPadding)
view.setPadding(alertDialogPadding, 0, alertDialogPadding, 0)

If you use a CheckBox (and maybe some other views), I don't think it's possible to set the paddings or margins so that it will get aligned nicely with other views in the dialog, unless you wrap it with a different view, or extend it

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • 1
    Java version: private static int getDimensionFromAttribute(Context context, int attrId) { final TypedValue value = new TypedValue(); if (context.getTheme().resolveAttribute(attrId, value, true)) { return TypedValue.complexToDimensionPixelSize(value.data, context.getResources().getDisplayMetrics()); } return 0; } – Oliver May 29 '20 at 09:58
  • @Oliver Not really needed. Kotlin supports Java, and Java supports Kotlin. And both languages are very similar anyway. – android developer May 29 '20 at 19:23
  • Maybe for experienced developers is not really needed, perhaps newbies will appreciate :). I prefer not to mix Kotlin and Java in the same project anyway. – Oliver Jun 15 '20 at 07:22
  • @Oliver Sometimes you don't have a choice. If you work on an old project, it is mainly Java. And it's very hard to convert it all to Kotlin without having any issues. I have to work on a project with ~1000 Java files, and I converted only about 200 of them to Kotlin so far. An Android developer should know both languages. Both are used in various places, including on Google's presentations and documentation. And Kotlin is the main&default one now, so it's even more important. – android developer Jun 15 '20 at 07:45
  • You are right...but it depends on the project. If my project is already in Java I prefer to have all code in the same language, so I will not use Kotlin in the project unless is totally necessary :) – Oliver Jun 15 '20 at 10:16
  • Well, converting to Kotlin has its own advantages. Usually Kotlin is shorter, and usually it helps against NPE much better than Java (because it forces you to always use nullable/non-nullable stuff) – android developer Jun 15 '20 at 20:00
  • I tried this but I get an error saying "cannot resolve symbol R.attr.dialogPreferredPadding". – Donald Duck May 10 '23 at 12:10