This is an approach to set all four margins without having to care about gravity.
I tested my approach for a DialogFragment
by applying it in the onCreateDialog
method:
public Dialog onCreateDialog( Bundle savedInstanceState )
{
// create dialog in an arbitrary way
Dialog dialog = super.onCreateDialog( savedInstanceState );
DialogUtils.setMargins( dialog, 0, 150, 50, 75 );
return dialog;
}
This is the method applying the margins to the dialog:
public static Dialog setMargins( Dialog dialog, int marginLeft, int marginTop, int marginRight, int marginBottom )
{
Window window = dialog.getWindow();
if ( window == null )
{
// dialog window is not available, cannot apply margins
return dialog;
}
Context context = dialog.getContext();
// set dialog to fullscreen
RelativeLayout root = new RelativeLayout( context );
root.setLayoutParams( new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) );
dialog.requestWindowFeature( Window.FEATURE_NO_TITLE );
dialog.setContentView( root );
// set background to get rid of additional margins
window.setBackgroundDrawable( new ColorDrawable( Color.WHITE ) );
// apply left and top margin directly
window.setGravity( Gravity.LEFT | Gravity.TOP );
LayoutParams attributes = window.getAttributes();
attributes.x = marginLeft;
attributes.y = marginTop;
window.setAttributes( attributes );
// set right and bottom margin implicitly by calculating width and height of dialog
Point displaySize = getDisplayDimensions( context );
int width = displaySize.x - marginLeft - marginRight;
int height = displaySize.y - marginTop - marginBottom;
window.setLayout( width, height );
return dialog;
}
Here are the helper methods I used:
@NonNull
public static Point getDisplayDimensions( Context context )
{
WindowManager wm = ( WindowManager ) context.getSystemService( Context.WINDOW_SERVICE );
Display display = wm.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics( metrics );
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
// find out if status bar has already been subtracted from screenHeight
display.getRealMetrics( metrics );
int physicalHeight = metrics.heightPixels;
int statusBarHeight = getStatusBarHeight( context );
int navigationBarHeight = getNavigationBarHeight( context );
int heightDelta = physicalHeight - screenHeight;
if ( heightDelta == 0 || heightDelta == navigationBarHeight )
{
screenHeight -= statusBarHeight;
}
return new Point( screenWidth, screenHeight );
}
public static int getStatusBarHeight( Context context )
{
Resources resources = context.getResources();
int resourceId = resources.getIdentifier( "status_bar_height", "dimen", "android" );
return ( resourceId > 0 ) ? resources.getDimensionPixelSize( resourceId ) : 0;
}
public static int getNavigationBarHeight( Context context )
{
Resources resources = context.getResources();
int resourceId = resources.getIdentifier( "navigation_bar_height", "dimen", "android" );
return ( resourceId > 0 ) ? resources.getDimensionPixelSize( resourceId ) : 0;
}
The helper methods are explained in another of my SO answers.
This Gist contains an extended versions that supports immersve mode too.