Alertdialog with Custom View: Resize to Wrap the View's Content

AlertDialog with custom view: Resize to wrap the view's content

I have a working solution that to be honest, I think digs way too deep to obtain such a simple result. But here it is:

What exactly is happening:

By opening the Dialog layout with the Hierarchy Viewer, I was able to examine the entire layout of the AlertDialog and what exactly what was going on:
Sample Image

The blue highlight is all of the high level parts (Window, frames for the Dialog visual style, etc) and from the end of the blue down is where the components for the AlertDialog are (red = title, yellow = a scrollview stub, maybe for list AlertDialogs, green = Dialog content i.e. custom view, orange = buttons).

From here it was clear that the 7-view path (from the start of the blue to the end of the green) was what was failing to correctly WRAP_CONTENT. Looking at the LayoutParams.width of each View revealed that all are given LayoutParams.width = MATCH_PARENT and somewhere (I guess at the top) a size is set. So if you follow that tree, it is clear that your custom View at the bottom of the tree, will never be able to affect the size of the Dialog.

So what were the existing solutions doing?

  • Both of the coding approaches mentioned in my question were simply getting the top View and modifying its LayoutParams. Obviously, with all View objects in the tree matching the parent, if the top level is set a static size, the whole Dialog will change size. But if the top level is set to WRAP_CONTENT, all the rest of the View objects in the tree are still looking up the tree to "MATCH their PARENT", as opposed to looking down the tree to "WRAP their CONTENT".

How to solve the problem:

Bluntly, change the LayoutParams.width of all View objects in the affecting path to be WRAP_CONTENT.

I found that this could only be done AFTER onStart lifecycle step of the DialogFragment is called. So the onStart is implemented like:

@Override
public void onStart() {
// This MUST be called first! Otherwise the view tweaking will not be present in the displayed Dialog (most likely overriden)
super.onStart();

forceWrapContent(myCustomView);
}

Then the function to appropriately modify the View hierarchy LayoutParams:

protected void forceWrapContent(View v) {
// Start with the provided view
View current = v;

// Travel up the tree until fail, modifying the LayoutParams
do {
// Get the parent
ViewParent parent = current.getParent();

// Check if the parent exists
if (parent != null) {
// Get the view
try {
current = (View) parent;
} catch (ClassCastException e) {
// This will happen when at the top view, it cannot be cast to a View
break;
}

// Modify the layout
current.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
}
} while (current.getParent() != null);

// Request a layout to be re-done
current.requestLayout();
}

And here is the working result:
Sample Image

It confuses me why the entire Dialog would not want to be WRAP_CONTENT with an explicit minWidth set to handle all cases that fit inside the default size, but I'm sure there is a good reason for it the way it is (would be interested to hear it).

How to wrap alertdialog in android?

Try Creating a dialog like this. this works perfect and then right away your dialog logic is seperated from you activity logic

public class CustomDialog extends Dialog implements
android.view.View.OnClickListener {

public Activity c;
public CustomDialog d;
public Button yes, no;

public CustomDialog(Activity a) {
super(a);
// TODO Auto-generated constructor stub
this.c = a;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dialog_layout);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//dosomething
}
});
}
}

Alert dialog custom layout width was not fit to the screen

try this:

in your res/values/styles:

 <style name="dialog_style" parent="android:style/Theme.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>

Now in your activity use the following code to show the dialog:

     final Dialog dialog = new Dialog(Sample.this,R.style.dialog_style);
dialog.setContentView(R.layout.research);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PA‌​RENT, ViewGroup.LayoutParams.MATCH_PARENT);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);
dialog.show();

Here ViewGroup.LayoutParams.MATCH_PARENT will fill the screen width

How to control the width and height of the default Alert Dialog in Android?

Only a slight change in Sat Code, set the layout after show() method of AlertDialog.

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(layout);
builder.setTitle("Title");
alertDialog = builder.create();
alertDialog.show();
alertDialog.getWindow().setLayout(600, 400); //Controlling width and height.

Or you can do it in my way.

alertDialog.show();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();

lp.copyFrom(alertDialog.getWindow().getAttributes());
lp.width = 150;
lp.height = 500;
lp.x=-170;
lp.y=100;
alertDialog.getWindow().setAttributes(lp);


Related Topics



Leave a reply



Submit