简体   繁体   中英

Why can Android AlertDialog's width and height = -1

I have three questions to AlertDialog. First of all, I will post my code Then ask my question.

<LinearLayout
android:id="@+id/l2"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@android:color/holo_orange_light"
xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:layout_width="200dp"
        android:layout_height="600dp"
        android:text="Test Test"
        android:textSize="40sp"
        android:background="@android:color/holo_green_light"
        android:textColor="@android:color/black"/>

This is the view to display in the AlertDialog, In the activity_main.xml, I have set a button to open the AlertDialog,The following is the code of listener.

  btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_window, null);
            AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setView(view).create();
            WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
            Log.d("TAG", "First lp width and height" + lp.width + "  " + lp.height);
            dialog.show();
            Window dialogWindow = dialog.getWindow();
            dialogWindow.setLayout(500,500);
            WindowManager.LayoutParams lp2 = dialogWindow.getAttributes();
            Log.d("TAG", "lp2 width and height" + lp2.width + "  " + lp2.height);

        }
    });

The logcat information screenshot in the following: Log Question:

  1. As you can see, The width and height of Dialog equals -1, I don't know the reason.
  2. dialogWindow.setLayout(500,500); is executed after dialog.show .When I put dialogWindow.setLayout(500,500); in front of dialog.show , I find it does't work. Why
  3. getWindow.setLayout(int width, int height) ; What is the unit of the width and height? ScreenShot

1 & 2
An alertdialog is not created until you call either .show() or .create() on it. So if you call the methods you're calling before creating it it will just return some default values.

If you do it like this

AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setView(view).create();
dialog.create();
WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
Log.d("TAG", "First lp width and height" + lp.width + "  " + lp.height);

it should show the right values.

3
The same values as you would enter in xml. Can be MATCH_PARENT , WRAP_CONTENT or an exact value. The exact value is in pixels.

Also see the docs for Window

As you can see, The width and height of Dialog equals -1, I don't know the reason.

-1 is the default value for both WindowManager.LayoutParams.width and WindowManager.LayoutParams.height .

-1 is also known as MATCH_PARENT which means the dialog will try to occupy as much space while respecting theme attributes such as maximum and minimum width and height.

dialogWindow.setLayout(500,500) is executed after dialog.show() . When I put it in front of dialog.show() it does't work. Why?

Before dialog.show() or dialog.create() the AlertDialog hasn't installed its content yet. It internally calls the following method of PhoneWindow :

@Override
public void setContentView(View view) {
    setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
}

This should also explain where the default values come from. Your call to setLayout should now produce desired results.

Credit: @TimCastelijns

getWindow.setLayout(int width, int height) What is the unit of the width and height?

The unit is pixels. You can also use WRAP_CONTENT and MATCH_PARENT constants.

If you're going to use this method avoid hardcoding pixels since on different screens you'd get different visual results. These methods will help you:

/** Precise decimal value, use for translation. */
public static float dpToPx(Context context, int dp) {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}

/** Rounded down value, use for offsets, paddings, margins. */
public static int dpToPxOffset(Context context, int dp) {
    return (int) (dpToPx(context, dp));
}

/** Rounded up value, use for sizes. */
public static int dpToPxSize(Context context, int dp) {
    return (int) (0.5f + dpToPx(context, dp));
}

Notes:

The following lines are ignored.

android:layout_width="200dp"
android:layout_height="200dp"

layout_ prefixed attributes are set on a LayoutParams object provided by parent view. Since there's no parent, there are no LayoutParams you can work with. Try setting android:minHeight and android:minWidth instead.

Parent view for root element is determined by parameter for inflation:

LayoutInflater.from(context).inflate(R.layout.popup_window, /*parent*/ null);
 btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_window, null);
        AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setView(view).create();
        WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
        Log.d("TAG", "First lp width and height" + lp.width + "  " + lp.height); <---------
        dialog.show();     <----------- you show the window here, so its size can be calculated. Before this, it doesn't exist. This is why you get -1 -1
        Window dialogWindow = dialog.getWindow();
        dialogWindow.setLayout(500,500);
        WindowManager.LayoutParams lp2 = dialogWindow.getAttributes();
        Log.d("TAG", "lp2 width and height" + lp2.width + "  " + lp2.height);

    }
});

Try with dialog.show before your first Log ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM