0

I have added a custom layout with parent layout as Constraint layout. In android 9 it is not able to take the width and getting truncated as shown in the image attached.

I am using DialogFragment to create a dialog.

Dialog image, this long white vertical bar is how the dialog is looking in android 9. Please ignore other white colours around.

Attaching the codes for the same -

<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/button_margin_top">

<!-- Title -->
<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/dialog_title"
    style="@style/AppTheme.PageTitle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="0dp"
    android:gravity="left"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:textColor="@color/dark_grey"
    android:textSize="@dimen/text_xxxl"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Remove this device from the list?"/>

<!-- Description -->
<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/description"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/spacing_xm"
    android:textAppearance="@style/AppTheme.Disclist.Body"
    android:textColor="@color/dark_grey"
    android:textSize="@dimen/text_xl"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/dialog_title"
    tools:text="Pause connection or block access at certain times. Pause connection or block access at certain times. Pause connection or block access at certain times."
    tools:visibility="visible"/>


<!-- Positive Button-->
<androidx.appcompat.widget.AppCompatButton
    android:id="@+id/positive_button"
    style="@style/AppTheme.LargeButton.Primary"
    android:layout_width="match_parent"
    android:gravity="center"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/description"
    tools:text="Yes, remove Device"/>

<androidx.appcompat.widget.AppCompatButton
    android:id="@+id/negative_button"
    style="@style/AppTheme.LargeButton.Secondary"
    android:layout_width="match_parent"
    android:gravity="center"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/positive_button"
    tools:text="Cancel"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Java Codes for the dialog -

public class NewConfirmationDialog extends DialogFragment implements View.OnClickListener {


private static final String DIALOG_TITLE = "title";
private static final String DIALOG_DESCRIPTION = "description";
private static final String POSITIVE_BUTTON_LABEL = "positive_button_label";
private static final String NEGATIVE_BUTTON_LABEL = "negative_button_label";
private static final String CANCELABLE = "cancelable";

private String titleString;
private String description;
private String postiveButtonLabel;
private String negativeButtonLabel;
private boolean cancelable = true;
private boolean isCancelled = false;

public static final int ACTION_CLOSE = 0;
public static final int ACTION_POSITIVE = 1;


public static NewConfirmationDialog getInstance(String title, String description,
                                                String positiveButtonLabel, String negativeButtonLabel,
                                                boolean cancelable) {
    return newInstance(title, description, positiveButtonLabel, negativeButtonLabel, cancelable);
}

public static NewConfirmationDialog getInstance(String title, String positiveButtonLabel,
                                                String negativeButtonLabel, boolean cancelable) {
    return newInstance(title, null, positiveButtonLabel, negativeButtonLabel, cancelable);
}


public static NewConfirmationDialog getInstance(String title, String description, String positiveButtonLabel) {
    return newInstance(title, description, positiveButtonLabel, null, false);
}


private static NewConfirmationDialog newInstance(String title, String description,
                                                 String positiveButtonLabel,
                                                 String negativeButtonLabel, boolean cancelable) {
    NewConfirmationDialog popupWidget = new NewConfirmationDialog();
    Bundle args = new Bundle();
    args.putString(DIALOG_TITLE, title);

    args.putBoolean(CANCELABLE, cancelable);
    args.putString(DIALOG_DESCRIPTION, description);

    args.putString(POSITIVE_BUTTON_LABEL, positiveButtonLabel);
    args.putString(NEGATIVE_BUTTON_LABEL, negativeButtonLabel);

    popupWidget.setArguments(args);
    return popupWidget;
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    Bundle args = getArguments();
    if (args == null) {
        throw new IllegalStateException("argument is empty");
    }
    titleString = args.getString(DIALOG_TITLE, null);
    description = args.getString(DIALOG_DESCRIPTION, null);
    postiveButtonLabel = args.getString(POSITIVE_BUTTON_LABEL, null);
    negativeButtonLabel = args.getString(NEGATIVE_BUTTON_LABEL, null);
    cancelable = args.getBoolean(CANCELABLE);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.layout_new_confirmation_dialog, container, false);

    //title
    if (titleString != null) {
        ((TextView) view.findViewById(R.id.dialog_title)).setText(titleString);
    } else {
        view.findViewById(R.id.dialog_title).setVisibility(View.GONE);
    }

    //Description
    if (description != null) {
        ((TextView) view.findViewById(R.id.description)).setText(description);
    } else {
        view.findViewById(R.id.description).setVisibility(View.GONE);
    }

    Button buttonPositive = view.findViewById(R.id.positive_button);
    if (postiveButtonLabel == null) {
        buttonPositive.setVisibility(View.GONE);
    } else {
        buttonPositive.setVisibility(View.VISIBLE);
        buttonPositive.setText(postiveButtonLabel);
        buttonPositive.setOnClickListener(this);
    }

    Button buttonNegative = view.findViewById(R.id.negative_button);
    if (negativeButtonLabel == null) {
        buttonNegative.setVisibility(View.GONE);
    } else {
        buttonNegative.setVisibility(View.VISIBLE);
        buttonNegative.setText(negativeButtonLabel);
        buttonNegative.setOnClickListener(this);
    }

    return view;
}

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getContext(), R.style.CustomDialog);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

    return dialog;
}

@Override
public void onDismiss(DialogInterface dialog) {
    super.onDismiss(dialog);
}

Style -

   <style name="CustomDialog" parent="Base.Theme.AppCompat.Dialog">
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowTitleStyle">@null</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:background">@drawable/round_corner_dialog_background</item>
</style>

Any suggestion why this is showing up in Android 9 only ?

Rahul
  • 395
  • 5
  • 20

4 Answers4

1

So after looking around I have actually found the cause.

When you override onCreateDialog(), Android COMPLETELY IGNORES several attributes of the root node of the .xml Layout you inflate. This includes, but probably isn't limited to:

  • background_color
  • ayout_gravity
  • layout_width
  • layout_height

Same thing was happening with me.

I solved this by adding 2 line in by CustomDialog style -

  1. android:windowMinWidthMajor
  2. android:windowMinWidthMinor

so it takes the width from there and works fine.

Reference- https://stackoverflow.com/a/41495370/4288868

Rahul
  • 395
  • 5
  • 20
1

The magic of dialog fragment! One must understand what's going on under the hood to fully get it work.

Setting android:layout_width="match_parent" and android:layout_height="wrap_content" in the xml won't do anything, why? because when the view is created, the onCreateView method is passed a null container. LayoutParams are only generated when the view is added to a dialog later on.

You'll notice also that behind your view is background that has a specific color, it's the dialog's window decor view bringing that.

Long story short, you have to manually specify all this in the onStart method like following:

override fun onStart() {
    super.onStart()
    requireDialog().window?.apply {
        setBackgroundDrawable(null)
        setLayout(MATCH_PARENT, WRAP_CONTENT)

    }
    val margin = //any margin
    view?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        setMargins(margin, margin, margin, margin)
    }
}
Guigui
  • 127
  • 2
  • 8
0

Can you try this code. It's working in my case:

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

public class DialogMap extends Dialog  {
    private Activity mActivity;
    private Button mBtnConfirmLocation;

    public DialogMap(@NonNull Activity activity) {
        super(activity);
        this.mActivity = activity;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_dialog_fm_map);

        mBtnConfirmLocation = findViewById(R.id.btn_confirm_location);
        mBtnConfirmLocation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //todo
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        setHeightWidth();
    }

    private void setHeightWidth() {
        WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
        assert wm != null;
        Display display = wm.getDefaultDisplay();
        DisplayMetrics metrics = new DisplayMetrics();
        display.getMetrics(metrics);
        Window win = getWindow();
        if (win != null) {
            win.setBackgroundDrawableResource(android.R.color.white);
            win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
            int width = (int) (metrics.widthPixels * 0.9);<-- you can change this 0.9 to acquire the width you want. In current case it will acquire 90% of total width available
            int height = (int) (metrics.heightPixels * 0.8);<-- same with height
            win.setLayout(width, height);
        }
    }

}

And use like this

DialogMap dialogMap = new DialogMap(MainActivity.this);
dialogMap.setCancelable(false);
dialogMap.show();
Deepak S. Gavkar
  • 447
  • 8
  • 21
0

You can set the width and height dynamically according to the screen width and height. Which would be a more ideal solution.

    val dialog = Dialog(
        context,
        android.R.style.Theme_Translucent_NoTitleBar
    )

    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
    dialog.window!!.setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
    )

    val lp = WindowManager.LayoutParams()
    lp.copyFrom(dialog.window!!.attributes)
    lp.width = (ScreenUtils.screenWidth * 0.6).toInt()
    lp.height = (ScreenUtils.screenWidth * 0.6).toInt()
    lp.gravity = Gravity.CENTER

    dialog.window!!.attributes = lp

    dialog.setContentView(R.layout.layout_bookmark_note)

    //this is how you access views
    //val editText = dialog.findViewById<EditText>(R.id.editTextNote)

    dialog.setCancelable(true)
    dialog.setCanceledOnTouchOutside(true)
    dialog.setOnCancelListener {

    }
    dialog.show()
Oshan Madusanka
  • 327
  • 3
  • 9