My app's main activity is set in the manifest to always be in portrait view. This works fine when I load the app onto the tablet.
However, when I use my menu button and click "Setup", which opens an AlertDialog that inflates an xml layout, the tablet will display the left 2/3 or so of the entire dialog. The rest of it goes offscreen to the right. This case only occurs if I install my app on the tablet while holding it in landscape mode or if I turn the tablet to landscape mode while the app is not running (even if I go back to Portrait and click on the app). The dialog even calls this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); to make sure it stays in portrait (even though the problem persists with this call or not).
In other words, the way the AlertDialog is being displayed in portrait view is that it is blowing up a landscape view (and thus some of it goes offscreen), even though the actual orientation of the AlertDialog is portrait, like it should be.
(I apologize if the wording above was confusing - ask me to clarify anything if needed.)
So why would the tablet do this? I've tested it on a few android mobile phones and this doesn't happen, so I don't understand why the tablet will do this.
SIDE NOTES:
This isn't even occurring for just this AlertDialog either.. my EULA that displays at the start of the app (another AlertDialog) also appears this way if I start the app in landscape mode.
I've even allowed the usability of landscape by getting rid of all calls to specify portrait/landscape mode, and the tablet is still expending the dialog off-screen when held in portrait view on just the tablet, but not the phones.
EDIT:
This code works well on the phone, but the tablet problem still persists. If I uncomment dialog.show(); below, the tablet and phone display the dimensions I want, but on blackness instead of the dimmed main screen. Any ideas?
Calling function does this:
showDialog(EXAMPLE_CASE);
Function that gets called by the calling function:
protected Dialog onCreateDialog(final int id) {
Dialog dialog;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Display display = getWindowManager().getDefaultDisplay();
int mwidth = display.getWidth();
int mheight = display.getHeight();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
switch(id) {
// Example of what all my cases look like (there were way too many to copy)
case EXAMPLE_CASE:
builder.setTitle("Example")
.setMessage("Example message")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface,int i) {
dialoginterface.dismiss();
showDialog(DIALOG_CHOICE);
}
})
.setCancelable(false);
dialog = builder.create();
break;
}
if (dialog != null) {
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = mwidth;
lp.height = mheight;
lp.x = mwidth;
//lp.y = mheight;
lp.dimAmount=0.0f;
//dialog.show();
dialog.getWindow().setAttributes(lp);
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
dialog.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
removeDialog(id);
}
});
}
return dialog;
}
You could try getting the screen dimensions like this:
Display display = getWindowManager().getDefaultDisplay();
int mwidth = display.getWidth();
int mheight = display.getHeight();
And then alter the Dialog like this:
AlertDialog.Builder adb = new AlertDialog.Builder(this);
Dialog d = adb.setView(new View(this)).create();
// (That new View is just there to have something inside the dialog that can grow big enough to cover the whole screen.)
d.show();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(d.getWindow().getAttributes());
lp.width = mwidth;
lp.height = myheight;
//change position of window on screen
lp.x = mwidth/2; //set these values to what work for you; probably like I have here at
lp.y = mheight/2; //half the screen width and height so it is in center
//set the dim level of the background
lp.dimAmount=0.1f; //change this value for more or less dimming
d.getWindow().setAttributes(lp);
//add a blur/dim flags
d.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND | WindowManager.LayoutParams.FLAG_DIM_BEHIND);
Also, you say you are inflating a custom layout. Have you tried tinkering with the layout_height and layout_width of the views in that layout to see if that makes a difference?
Related
I have an ImageView inside a ConstraintLayout in my Activity. I want to show a custom Dialog (with a custom layout) right on top of this ImageView whenever I click on it.
I have achieved this on my device by tweaking the LayoutParams "x" and "y", but, of course, it fails when I test it on a device with another density (as it also would on a different screen size, I guess). The position is wrong.
How can I make sure my dialog always shows up right above and centered on this ImageView? I'm having a hard time figuring out positions and sizes of views in Android.
priority.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showCustomDialog();
}
});
private void showCustomDialog() {
dialog = new MyDialog(MainActivity.this);
Window window = dialog.getWindow();
WindowManager.LayoutParams param = window.getAttributes();
//any ideas?
dialog.show();
}
I have a problem with a fragment dialog, if the phone is on portrait mode, everything is ok, the dialog is almost full screen, but when I rotate my phone, in landscape there are some big gaps on the sides..is possible to fix this problem?
I call this
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
To get rid of the DIalogFragment title.
I'm using a Linear Layout.
The solution:
#Override
public void onStart()
{
super.onStart();
Dialog dialog = getDialog();
if (dialog != null)
{
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width, height);
}
}
Add this to your dialog fragment.
I've got a DialogFragment, normally centered on the screen, that I'm trying to move out of the way of the on screen keyboard, if any should appear, because it's not a good UX experience for the keyboard to cover over parts of the window when there's perfectly unused screen real estate farther up.
Suppose I've solved the problem of detecting the keyboard appearing or disappearing, e.g. How to check visibility of software keyboard in Android? .
Currently I go to move the window out of the way by doing something like this:
...
final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
params.gravity = Gravity.TOP;
params.verticalMargin = .1f; //or whatever
dialog.getWindow().setAttributes(params);
...
This works fine, but the window suddenly jerks into place, which isn't a pleasant UX experience. The window in question has a successful enter and exit animation - and these even work appropriately after the window layout change. How can I further animate the window between WindowManager.LayoutParams changes?
(I'd prefer if possible to keep working in terms of layout {of the} / {within the} http://developer.android.com/reference/android/view/Window.html rather than, say, forcing the DialogFragment into my activity's layout and animating it from within there).
I didn't have time to wait for the bounty to expire, so I coded the below stop gap until I can get a better solution. In case it helps anybody else, or gives them an idea for a bounty-worthy answer, this is what I did. However, I suspect its inefficient as all hell, since I assume it forces a window relayout every animation frame rather than just panning a bitmap across the screen. This isn't all of it of course, but is the critical bit:
// Not shown: setting currentVerticalMargin, targetVerticalMargin, or calling this method
private synchronized void restartVerticalMarginAnimator() {
if (verticalMarginAnimator != null) {
return;
}
final Dialog dialog = this.getDialog();
if (dialog == null) {
return;
}
final WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
verticalMarginAnimator = new TimeAnimator();
verticalMarginAnimator.setTimeListener(new TimeListener() {
#Override
public void onTimeUpdate(TimeAnimator a, long totalTime, long deltaTime) {
float stretch = targetVerticalMargin - currentVerticalMargin;
float distance = WINDOW_ANIMATION_SPEED * deltaTime / 1000L;
boolean finished = false;
// Adjust distance so it's capped at "going all the way to target" and no further,
// and has the right sign if we're animating upward.
if (distance > Math.abs(stretch)) {
distance = stretch;
finished = true;
} else if (stretch < 0) {
distance *= -1f;
}
// Move.
currentVerticalMargin += distance;
if (finished) {
verticalMarginAnimator.end();
verticalMarginAnimator = null;
}
params.verticalMargin = currentVerticalMargin;
dialog.getWindow().setAttributes(params);
}
});
verticalMarginAnimator.start();
}
I want to achieve the following design: A dialog with custom layout, created programatically. It will contain an EditText and a Button. I want the soft keyboard to pop up when the dialog appears, and I want the dialog to fill the screen horizontally and to be placed right above the keyboard.
Here is what I've done right now:
final AlertDialog obsDialog = new AlertDialog.Builder(ProdutoDetalheActivity.this).create();
final View obsLayout = View.inflate(getApplicationContext(), R.layout.observation_layout, null);
Button obsButton = (Button) obsLayout.findViewById(R.id.observation_button);
obsEdit = (EditText) obsLayout.findViewById(R.id.observation_edit);
obsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
text.setText(String.valueOf(obsEdit.getText()));
obsDialog.dismiss();
}
});
obsDialog.setView(obsLayout);
obsDialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
obsDialog.show();
obsEdit.requestFocus();
But this doesn't makes the dialog full width, nor calls the soft keyboard. And I still wonder how can I align the dialog with the keyboard.
I've tried these answers with no success.
Thanks in advance for any help!
[EDIT] I've brought the keyboard up by using the following code:
obsDialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
obsDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
[EDIT] Below is a printscreen of the design I want to achieve:
As far as I know, you have to adjust the dialog size/position in the code if you do not want the default size/position.
In you case specifically, you can fist declare adjustResize for the activity's windowSoftInputMode in the AndroidManifest.xml.
After that, you can set your dialog gravity at bottom and set the width in the onStart of the dialog fragment:
...
getDialog().getWindow().setLayout(mWidth, mHeight);
WindowManager.LayoutParams lp = getDialog().getWindow().getAttributes();
lp.gravity = Gravity.BOTTOM;
lp.x = 0; lp.y = 0;
getDialog().getWindow().setAttributes(lp);
...
the mWidth and mHeight are initialized in onCreate, but I think you can do it in the onStart as well. To get the width, I used below code:
Point size = new Point();
WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
display.getSize(size);
mWidth = size.x;
Hope this can meet your requirement. I used this to create a similar dialog, but I do not have a edit in the dialog. And I need it to be at the bottom of the screen.
I'm trying to show a simple prompt dialog fragment programatically. I've extended SherlockFragmentActivity, and coded a custom SherlockDialogFragment implementation in it.
(I'm using ActionbarSherlock library, but I think the problem doesn't have to do with it, and would also be observed using regular ActionBar and Fragments).
This is the overriden oncreateDialog method inside the custom FragmentActivity class:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//Skipped section. Setting positive, negative buttons, title, message on builder.
efPsw = new EditText(getActivity());
// Hacky margin stuff (yeah, I know it's dirty)
DisplayMetrics displaymetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int smallestSide = Math.min(displaymetrics.heightPixels, displaymetrics.widthPixels);
int margin = (int)(0.5 * ((double) smallestSide));
efPsw.setTransformationMethod(PasswordTransformationMethod.getInstance());
FrameLayout fl = new FrameLayout(getActivity());
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(margin, 0, margin, 0);
fl.addView(efPsw, layoutParams);
builder.setView(fl);
return builder.create();
}
When I show the fragment, the inner framelayout is not shown (looks like an invisible rectangle that grows in height with each typed character). I'm not sure what am I doing wrong here, but certainly something must be wrong, since if I put the edittext in setView everything works fine (but without margin).
Thanks in advance.
it looks like you are making the margin half the smallest side, which in portrait mode would make your margin the entire screen. i would start by reducing the margin.
you can apply the margins directly to the EditText using the setLayoutParams() method. That would eliminate the FrameLayout.