3

I created a custom dialog preference in my Android application, but I can not figure out how to get the dialog which is displayed to span the complete width of the display.

image of dialog with too much space on left and right side

I found many proposed solutions to get a normal Dialog in full screen mode

But setting the attributes via getWindow does not work:

@Override
public Dialog getDialog() {

    Dialog dialog = super.getDialog();    
    dialog.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    // or 
    // dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    return dialog;
}

And applying a full screen theme to my dialogs root element didn't do the job neither:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    [...]
    android:theme="@style/FullscreenTheme">

Moreover I'm not able to access the onCreate Method (at least I don't know how) of the Dialog, to set the style there.

Did anyone had the same problem and figured out a solution for this very specific issue?

My layout:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:orientation="vertical"
    android:padding="0dp"
    android:paddingTop="@dimen/preferences_dialog_def_padding"
    android:paddingBottom="@dimen/preferences_dialog_def_padding">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:layout_marginTop="-2dp"
            android:background="@color/expandable_preference_divider"/>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/preferences_expandable_margin_top_bottom"
            android:layout_marginTop="@dimen/preferences_expandable_margin_top_bottom">

            <RelativeLayout
                android:id="@+id/icon_wrapper_choose"
                android:layout_width="@dimen/preferences_expandable_icon_wrapper_size"
                android:layout_height="@dimen/preferences_expandable_icon_wrapper_size"
                android:layout_marginBottom="0dp"
                android:layout_marginEnd="@dimen/preference_expandable_icon_margin"
                android:layout_marginStart="@dimen/preference_expandable_icon_margin"
                android:layout_marginTop="0dp"
                android:gravity="center">

                <ImageView
                    android:layout_width="@dimen/preferences_expandable_icon_size"
                    android:layout_height="@dimen/preferences_expandable_icon_size"
                    android:layout_centerHorizontal="true"
                    android:layout_centerVertical="true"
                    android:cropToPadding="true"
                    android:scaleType="centerCrop"
                    android:src="@drawable/ic_settings_white_36dp"/>

            </RelativeLayout>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toEndOf="@+id/icon_wrapper_choose"
                android:paddingBottom="@dimen/preferences_expandable_text_padding_top_bottom"
                android:paddingTop="@dimen/preferences_expandable_text_padding_top_bottom"
                android:text="@string/pref_wheel_circumference_choose"
                android:textColor="@color/colorAccent"
                android:textSize="@dimen/text_size_medium"
                android:textStyle="bold"/>
        </RelativeLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_marginEnd="@dimen/preference_expandable_icon_margin"
            android:layout_marginStart="@dimen/preference_expandable_icon_margin"
            android:layout_height="wrap_content"
            android:text="@string/etrto_hint"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:minHeight="?android:attr/listPreferredItemHeight"
            android:orientation="horizontal"
            android:paddingBottom="20dp"
            android:paddingEnd="?android:attr/scrollbarSize"
            android:layout_marginStart="@dimen/preference_expandable_icon_margin"
            android:weightSum="3"
            >

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/etrto"/>

            <Spinner
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingBottom="20dp"
            android:paddingEnd="?android:attr/scrollbarSize"
            android:layout_marginStart="@dimen/preference_expandable_icon_margin"
            android:weightSum="3"
            >

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/manufacturer"/>

            <Spinner
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"/>

        </LinearLayout>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_marginTop="-2dp"
        android:background="@color/expandable_preference_divider"/>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/preference_category_wrapper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:orientation="vertical"
        android:padding="5dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/preferences_expandable_margin_top_bottom"
            android:layout_marginTop="@dimen/preferences_expandable_margin_top_bottom">

            <RelativeLayout
                android:id="@+id/icon_wrapper_manual"
                android:layout_width="@dimen/preferences_expandable_icon_wrapper_size"
                android:layout_height="@dimen/preferences_expandable_icon_wrapper_size"
                android:layout_marginBottom="0dp"
                android:layout_marginEnd="@dimen/preference_expandable_icon_margin"
                android:layout_marginStart="@dimen/preference_expandable_icon_margin"
                android:layout_marginTop="0dp"
                android:gravity="center">

                <ImageView
                    android:id="@+android:id/icon"
                    android:layout_width="@dimen/preferences_expandable_icon_size"
                    android:layout_height="@dimen/preferences_expandable_icon_size"
                    android:layout_centerHorizontal="true"
                    android:layout_centerVertical="true"
                    android:cropToPadding="true"
                    android:scaleType="centerCrop"
                    android:src="@drawable/ic_edit_white_36dp"/>

            </RelativeLayout>

            <TextView
                android:id="@+android:id/title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_toEndOf="@+id/icon_wrapper_manual"
                android:paddingBottom="@dimen/preferences_expandable_text_padding_top_bottom"
                android:paddingTop="@dimen/preferences_expandable_text_padding_top_bottom"
                android:text="@string/pref_wheel_circumference_manually"
                android:textColor="@color/colorAccent"
                android:textSize="@dimen/text_size_medium"
                android:textStyle="bold"/>
        </RelativeLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:minHeight="?android:attr/listPreferredItemHeight"
            android:orientation="horizontal"
            android:paddingBottom="20dp"
            android:paddingEnd="?android:attr/scrollbarSize"
            android:layout_marginStart="@dimen/preference_expandable_icon_margin"
            android:weightSum="2.5"
            >

            <EditText
                android:id="@+id/pref_dialog_wheelcircumference_et"
                android:layout_width="0dp"
                android:layout_weight="2"
                android:layout_height="wrap_content"
                android:textAlignment="textEnd"
                android:textColor="@color/colorFont"
                android:textSize="@dimen/text_size_small"
                android:inputType="number"/>

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="0.5"
                android:textAlignment="center"
                android:text="@string/wheel_circumference_unit"/>

        </LinearLayout>

    </LinearLayout>
</LinearLayout>

My custom preference class

public class WheelCircumferencePreference extends android.preference.DialogPreference {

private static String TAG = "CustomSwitchPreference";
private int mWheelCircumference;
public static int WHEEL_CIRCUMFERENCE_DEFAULT = 2125;

private int mDialogLayoutResId = R.layout.pref_dialog_wheelcircumference;

public WheelCircumferencePreference(Context context) {
    this(context, null);
}

public WheelCircumferencePreference(Context context, AttributeSet attrs) {
    this(context, attrs, R.attr.dialogPreferenceStyle);
}

public WheelCircumferencePreference(Context context, AttributeSet attrs,
                                    int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setLayoutResource(R.layout.custom_preference);      
    setDialogLayoutResource(mDialogLayoutResId);
    setPositiveButtonText(getContext().getString(R.string.dialog_save));
    setNegativeButtonText(getContext().getString(R.string.dialog_cancel));
}

@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
    // Default value from attribute. Fallback value is set to WHEEL_CIRCUMFERENCE_DEFAULT.
    return a.getInteger(index, WHEEL_CIRCUMFERENCE_DEFAULT);
}

@Override
protected void onSetInitialValue(boolean restorePersistedValue,
                                 Object defaultValue) {
    would load value from shared preferences
    if (restorePersistedValue) {
        mWheelCircumference = getPersistedInt(WHEEL_CIRCUMFERENCE_DEFAULT);
    } else {
        mWheelCircumference = (Integer) defaultValue;
        persistInt(mWheelCircumference);
    }
}

private EditText mWheelCircumferenceEt;


@Override
protected void onBindDialogView(View view) {

    mWheelCircumferenceEt = view.findViewById(R.id.pref_dialog_wheelcircumference_et);

    if (mWheelCircumferenceEt == null) {
        throw new IllegalStateException("preference dialog view must contain" +
                " a EditText with id 'pref_dialog_wheelcircumference_et'");
    }
    mWheelCircumferenceEt.setText(Integer.toString(mWheelCircumference));


    super.onBindDialogView(view);
}



@Override
public Dialog getDialog() {

    //Dialog dialog = super.getDialog();

   // WindowManager.LayoutParams p = getDialog().getWindow().getAttributes();
    //p.height = LinearLayout.LayoutParams.WRAP_CONTENT;
    //dialog.getWindow().setAttributes(p);

    return dialog;
}

@Override
protected void onDialogClosed(boolean positiveResult) {
    if (positiveResult) {
        String circumferenceText = mWheelCircumferenceEt.getText().toString();

        try {
            mWheelCircumference = Integer.parseInt(circumferenceText);
        } catch (Exception e) {
            NLog.e(TAG, "onDialogClosed - ", e);
            mWheelCircumference = WheelCircumferencePreference.WHEEL_CIRCUMFERENCE_DEFAULT;
        }
        persistInt(mWheelCircumference);
    }
}

Edit:

Actually I only want the dialog to span over the full width of the screen, not the height. If I would use a additional PreferenceFragment (as the DialogPreference is already embedded in a PreferenceFragment ) the "Dialog" (aka Fragment) would take the complete width and height (i guess).

I already implemented a solution without a DialogPrefrence, that works but is not exactly elegant

  • using just a normal EditTextPreference
  • adding an onPreferenceClickListener to this preference in my SettingsFragment Code
    • the ClickListener displays a simple Dialog

Example:

        Preference preference = findPreference(EXAMPLE_PREFRENCE);    

        if (preference != null) {

            preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
//                    showDialog();
                }
            });

But as I have a lot of preferences which will display dialogs the code for the dialog creation and display bloads the SettingsFragment and makes it nearly unreadable. Therefore I thought it would be a nice solution to put the responsibility of displaying the dialog and handling the preference values to the Preference and the XML layout.

Unfortunately I got stuck with the "full width issue" mentioned above.

Note: fixed the code of getDialog as I tested different versions (also in combination with the xml theme set)

little_planet
  • 655
  • 1
  • 6
  • 13
  • It's a ```DialogPreference```, presumably it has some kind of Dialog Theme quality that would stop you (xml doesn't tend to override them so well I find, I think it could be applied programmatically) - why not use a ```PreferenceFragment``` instead? Also, in your ```getDialog``` you're setting the _height_ to ```wrap_content``` (you want width at ```match_parent``` right?), if you're right at the start of your android journey, just read around google's docs, they're pretty good, you'll learn quickly and it will be a lot less frustrating – Saik Caskey Mar 21 '18 at 15:45
  • I edited my question to explain the issue in more detail and to show a solution that worked in the past (but which I would like to replace) – little_planet Mar 22 '18 at 08:02

3 Answers3

1

Finally I did find a solution for this problem:

Fetch the AlertDialog of the Preference in showDialog method

@Override 
protected void showDialog(Bundle state) {
        super.showDialog(state);
        CustomDialogPreference.makeDialogFullScreen((AlertDialog) getDialog()); 
}

make it span the complete width:

public static void makeDialogFullScreen(AlertDialog d) {
    NLog.d(TAG, "makeDialogFullScreen enter ");
    if (d != null) {
        ViewGroup.LayoutParams params = d.getWindow().getAttributes();
        if (params != null) {
            params.width = WindowManager.LayoutParams.MATCH_PARENT;
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            d.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
        }
    }
}
little_planet
  • 655
  • 1
  • 6
  • 13
0

Try this in the onResume of your dialog.

   // Store access variables for window and blank point
    Window window = getDialog().getWindow();
    Point size = new Point();
    // Store dimensions of the screen in `size`
    Display display = window.getWindowManager().getDefaultDisplay();
    display.getSize(size);
    // Set the width of the dialog proportional to 75% of the screen width and height
    window.setLayout((int) (size.x * 0.75), (int) (size.y * 0.75));
    window.setGravity(Gravity.CENTER);
    // Call super onResume after sizing

Adjust accordingly for 100%. It works great for a dialogFragment. Haven't tried it for your case though.

costa
  • 19
  • 3
  • As far as I know I do not have access to the underlying Dialog of the DialogPreference. Do you have any information about that matter which you can share with me? – little_planet Mar 22 '18 at 07:48
0

Wait, you're not looking for the bog-standard 'Pref settings user options appear in a dialog' thing are you? That's almost definitely already done in AndroidStudio's add activity...> Settings Activity in boiler plate, check it out, or look for sample settings apps


Anyway, I do actually have a fullscreen dialog in my app, although it purposely doesn't fill the full screen, and I actually use an activity with some fragments now instead.

Personally I think this is what your problem is, I remember having this exact issue when I first needed a dialog like this. You should just use activities and have up navigation (if you want a full screen "popup" type thing you could use the Navigation pattern that makes the home/up button an 'X' instead of a '<');

Or anything else, you don't need to have a dialog explicitly, and if you do then extend activity or dialog and get what you want.

Here's my activity stuff in case it's any use

my theme:

  <style name="AppTheme.FullScreenDialog"
                  parent="@style/Theme.AppCompat.Light.Dialog">
    <item name="windowActionBar">true</item>
    <item name="windowNoTitle">true</item>
</style>

my onCreate gist:

 @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    ...

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    ...
    super.onCreate(savedInstanceState);
    setContentView(getConcreteContentView());
    ButterKnife.bind(this);
    setUpUIComponents();
    ...
}

my general layout gist:

<CoordinatorLayout>
<AppBarLayout>
    <android.support.v7.widget.Toolbar/>
</android.support.design.widget.AppBarLayout>

<RelativeLayout
    android:id="@+id/container_main"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:paddingTop="6dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <RelativeLayout
        android:id="@+id/container_recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_security_word"
        android:paddingEnd="18dp"
        android:paddingStart="18dp" />

    <RelativeLayout
        android:id="@+id/container_security"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/container_recycler"
        android:minHeight="150dp"
        android:paddingEnd="18dp"
        android:paddingStart="18dp"

        android:visibility="visible" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/security_container"
        android:layout_centerHorizontal="true"
        android:contentDescription="@string/app_name"
        android:minHeight="50dp"
        android:scaleType="centerInside" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

Bon Chance!

Saik Caskey
  • 500
  • 4
  • 18