Display metrics minus status bar? - android

I need to get the dimensions of the display rectangle that the application can use on the device. For that I tried using:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
My problem is that it gives me the height of the whole display and the display has a "status / notification" bar on top that the application can't use.
I need the acual dimension that the application can use.
To help you understand the question better I'll leave an image:

The biggest trick to all of this is that you can't usually gain access to a true value of that view's size until layout is complete. Which means onCreate() (and often onResume() also) are too early in the process to do the calculation. The following code will get you a view representing the content view of the Activity, at which point you can examine its height and width:
View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
Log.d("DISPLAY", content.getWidth() + " x " + content.getHeight());
This also accounts for any title views you may have set in the Activity. You could also obtain a reference to the root layout you set as the content view when the XML is inflated and do the same thing if that layout is set to fill_parent in both dimensions.
A good method where I often make calls like this is onWindowFocusChanged() which will be called at the point when your Activity is just about visible to the user.
Hope that Helps!

This call is independent of the point of time you call it:
...
Point dimensions = getDisplayDimensions(context);
int width = dimensions.x;
int height = dimensions.y;
...
#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 trick is that it compares the screen display metrics (what you want modulo the status bar) and the "real metrics", which is the physical pixels of the device.
The status bar height then is subtracted ad-hoc if that did not happen yet.
(In my tests the navigation bar, containing back and home buttons, was already subtracted.)

Related

Detect soft navigation bar availability in onePlusOne device progmatically?

I need to check if a device has the soft navigation bar, and I followed the suggestions here.
It works great, except on onePlus devices, for some reason, this code:
int id = resources.getIdentifier("config_showNavigationBar", "bool", android");
return id > 0 && resources.getBoolean(id);
returns false, although the soft navigation bar is displayed.
Any idea how can I get the correct result?
I prefer not to calculate the real width and available width, it seems like expensive operation.
Thanks.
See this answer. There is no way be 100% sure, though.
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
if (hasBackKey && hasHomeKey) {
// no navigation bar, unless it is enabled in the settings
} else {
// 99% sure there's a navigation bar
}
Edit
Another approach
public boolean hasNavBar (Resources resources) {
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
return id > 0 && resources.getBoolean(id);
}
Yes you can try this:
WindowManager mgr = (WindowManager) getSystemService(WINDOW_SERVICE);
boolean hasSoftKey = Utils.hasSoftKeys(mgr, NPTApplication.this);
public static boolean hasSoftKeys(WindowManager windowManager, Context c) {
boolean hasSoftwareKeys = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Display d = windowManager.getDefaultDisplay();
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
d.getRealMetrics(realDisplayMetrics);
int realHeight = realDisplayMetrics.heightPixels;
int realWidth = realDisplayMetrics.widthPixels;
DisplayMetrics displayMetrics = new DisplayMetrics();
d.getMetrics(displayMetrics);
int displayHeight = displayMetrics.heightPixels;
int displayWidth = displayMetrics.widthPixels;
hasSoftwareKeys = (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
} else {
boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
hasSoftwareKeys = !hasMenuKey && !hasBackKey;
}
return hasSoftwareKeys;
}
no will not work that way you have to compute the size
the method used is detailed in this SO answer;
How to get height and width of navigation bar programmatically
Well, there is a method hasPermanentMenuKey which checks if the hardware MenuKey is present, usually Samsung devices has it on left size of Home button.
So if it returns true, it means the phone has hardware keys, and if it's false, then simply it means phone has navigation bar.
The method is:
ViewConfiguration.hasPermanentMenuKey()
I find it pretty useful for myself.
//The method has ability to return 0 when the navigation bar was hidden.
private fun getNavigationBarHeight(context: Context): Int {
val display = context.windowManager?.defaultDisplay
return if (display == null) {
0
} else {
val realMetrics = DisplayMetrics()
display.getRealMetrics(realMetrics)
val metrics = DisplayMetrics()
display.getMetrics(metrics)
realMetrics.heightPixels - metrics.heightPixels
}
}

Android: Obtaining the dimension of the button

I am having a dynamic layout where there is a imagebutton named ButtonQ.
I would like to set the dimension of the ButtonQ and then to see if it is correct, I have added a toast.
#Override
protected void onStart()
{
super.onStart();
measure_dimension();
}
private static Point getDisplaySize(final Display display)
{
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}
public void measure_dimension()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = getDisplaySize(display);
int screen_width = size.x;
int screen_height = size.y;
int target_height = Math.min(screen_height, 600);
int target_width = Math.min(screen_width, 600);
int target_dimension = Math.min(target_height, target_width);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(target_dimension, target_dimension); // width, height
buttonQ.setLayoutParams(layoutParams);
image_height = target_height;
image_width = target_width;
Toast.makeText(Game_middle.this, "buttonQ height:"+ buttonQ.getHeight() +"\nbuttonQ width=" + buttonQ.getWidth(), Toast.LENGTH_LONG).show();
}
Question:
The toast reports the height and the width of ButtonQ are both 0.
Why?
I'd use the analogue way you're setting your height and width: via getLayoutParams(). If you want to set the params dynamically, I wouldn't use pixels directly but the dp unit, using TypedValue.COMPLEX_UNIT_DIP.
Regarding to synchronization, in that example I'd definitely use asynchronous mechanisms, such as CountDownLatch or Semaphore mechanisms. It's quite more secure this way than using temporary timers. You may want to check the CountDownLatch(1) example in the reference page for that purpose.
Try this to get the button dimensions where popLayout is the button name in your case
popupLayout.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
width = popupLayout.getMeasuredWidth();
height = popupLayout.getMeasuredHeight();

android get screen size of the other screen orientation

since android 3.0 there is a navigation bar with back and home button on the display. Now if I get the screen size like this
ClockLwp.ScreenHeight = getWindowManager().getDefaultDisplay().getHeight();
ClockLwp.ScreenWidth = getWindowManager().getDefaultDisplay().getWidth();
of this
getResources().getDisplayMetrics().widthPixels
getResources().getDisplayMetrics().heightPixels
I get different values for the landscape and portrait. Here is an example what I mean:
Acer Iconia A500 portrait mode : 800 x 1232
Acer Iconia A500 landscape mode : 1280 x 752
AFAIK this goes for all devices with such a navigation bar. (e.g. Samsung Galaxy Nexus, GalaxyTab 10.1 etc.)
Now my question is, if I am in portrait mode how can I get the values of landscape mode and the other way around?
since android 3 there is no way with the public api to retrive the raw heigth and width . You can go through reflection. Look for getRawHeigth/Width
EDIT (26 September 2014): I reformulated my text to contain a full answer and not just comment to Dmitri solution.
Here is the part that we are using to calculate the navigation bar height before rotation:
DisplayMetrics metrics = new DisplayMetrics();
mFragment.getActivity().getWindowManager().getDefaultDisplay()
.getMetrics(metrics);
/*
* We need to take system resources here to verify navigation
* bar height. Application resources also contains navigation bar
* height but this value is not valid for some devices e.g. Nexus 7 (2012)!
*/
Resources appRes = getResources();
Resources sysRes = Resources.getSystem();
boolean landscapeMode = (metrics.widthPixels > metrics.heightPixels);
/* Check if the device has navigation bar. There is no direct API for
* that so we use some hacking that may not always work,
* (see http://stackoverflow.com/questions/16092431/check-for-navigation-bar)
* but this method should be enough for most devices.
* TODO: Find a more consistent way. For our needs it is currently enough as we
* support limited set of devices.
*/
boolean hasNavigationBar = !ViewConfiguration.get(getContext()).hasPermanentMenuKey();
int navBarHeight = 0;
int navBarHeightRotated = 0;
if (hasNavigationBar) {
int barHeightDimId = 0;
int barHeightDimIdRotated = 0;
if (landscapeMode) {
barHeightDimId = sysRes.getIdentifier(
"navigation_bar_height_landscape", "dimen", "android");
barHeightDimIdRotated = sysRes.getIdentifier(
"navigation_bar_height", "dimen", "android");
} else {
barHeightDimIdRotated = sysRes.getIdentifier(
"navigation_bar_height_landscape", "dimen", "android");
barHeightDimId = sysRes.getIdentifier("navigation_bar_height",
"dimen", "android");
}
if (barHeightDimId != 0) {
navBarHeight = appRes.getDimensionPixelSize(barHeightDimId);
}
if (barHeightDimIdRotated != 0) {
navBarHeightRotated = appRes
.getDimensionPixelSize(barHeightDimIdRotated);
}
NCLogs.i("MyApp", String.format("Android navigation bar height: %d (current), %d (after rotation)", navBarHeight, navBarHeightRotated));
}
then we can calculate our view width and height after rotation:
int realScreenHeight = metrics.heightPixels + navBarHeight;
// We expect to not have decor views near the left or right borders
int realScreenWidth = metrics.widthPixels;
/*
* Height of decor views: system status bar + any application addtional elements +
* + system navigation bar
*/
int decorHeightRotated = realScreenHeight - getHeight() - navBarHeight + navBarHeightRotated;
int viewWidthRotated = realScreenHeight;
int viewHeightRotated = (realScreenWidth - decorHeightRotated);
NCLogs.i("MyApp", String.format("Width after rotation: %d, Height after rotation: %d", viewWidthRotated, viewHeightRotated));
Here is solution that works for me. I've got real screen size and then subtract navigation bar height.
// get navigation bar height for landscape and portrait modes
Resources resources = activity.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
int resourceIdLandscape = resources.getIdentifier("navigation_bar_height_landscape", "dimen", "android");
int portraitNavBarHeight = 0;
int landscapeNavBarHeight = 0;
boolean hasPermanentMenuKey = ViewConfiguration.get(activity).hasPermanentMenuKey();
if (resourceId > 0 && !hasPermanentMenuKey) {
portraitNavBarHeight = resources.getDimensionPixelSize(resourceId);
}
if (resourceIdLandscape > 0 && !hasPermanentMenuKey) {
landscapeNavBarHeight = resources.getDimensionPixelSize(resourceIdLandscape);
}
// get real screen size
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
Display disp = wm.getDefaultDisplay();
int API_LEVEL = android.os.Build.VERSION.SDK_INT;
if (API_LEVEL >= 17) {
disp.getRealMetrics(displayMetrics);
} else {
disp.getMetrics(displayMetrics);
}
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
// size for orientation
int portraitHeight;
int portraitWidth;
int landscapeHeight;
int landscapeWidth;
if(width > height) {
portraitHeight = width - portraitNavBarHeight;
portraitWidth = height;
landscapeHeight = height - landscapeNavBarHeight;
landscapeNavBarHeight = width;
} else {
portraitHeight = height - portraitNavBarHeight;
portraitWidth = width;
landscapeHeight = width - landscapeNavBarHeight;
landscapeNavBarHeight = height;
}
If your application has status bar
public static int getStatusBarHeight(Context context) {
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
return resources.getDimensionPixelSize(resourceId);
}
return 0;
}

How do I get screen sizes from a service?

From an activity I would do it like this
Display display = getWindowManager().getDefaultDisplay();
int x = display.getWidth();
Yet a service ( keyboard ) doesn't seem to support it... any other ideas?
Thanks!
Use getSystemService(WINDOW_SERVICE)
Display display = ( (WindowManager)getSystemService(WINDOW_SERVICE) ).getDefaultDisplay();
int x = display.getWidth();
int y = display.getHeight();

Height of status bar in Android [duplicate]

This question already has answers here:
Height of statusbar?
(14 answers)
Closed 2 years ago.
What's the height of the status bar in Android? Is it always the same?
From my measurements it seems that it's 25dp, but I'm not sure if it has the same height on all platforms.
(I want to know this to properly implement a fade transition from an activity that doesn't have status bar to one that does)
this question was answered before...
Height of statusbar?
Update::
Current method:
ok, the height of the status bar depends on the screen size, for example in a device
with 240 X 320 screen size the status bar height is 20px, for a device with 320 X 480 screen size the status bar height is 25px, for a device with 480 x 800 the status bar height must be 38px
so i recommend to use this script to get the status bar height
Rect rectangle = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
int statusBarHeight = rectangle.top;
int contentViewTop =
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight= contentViewTop - statusBarHeight;
Log.i("*** Elenasys :: ", "StatusBar Height= " + statusBarHeight + " , TitleBar Height = " + titleBarHeight);
(old Method) to get the Height of the status bar on the onCreate() method of your Activity, use this method:
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Out of all the code samples I've used to get the height of the status bar, the only one that actually appears to work in the onCreate method of an Activity is this:
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Apparently the actual height of the status bar is kept as an Android resource. The above code can be added to a ContextWrapper class (e.g. an Activity).
Found at http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/
Hardcoding the size or using reflection to get the value of status_bar_height is considered bad practice. Chris Banes talked about this in at the Droidcon New York. The recommended way of getting the status bar size is via the OnApplyWindowInsetsListener:
myView.setOnApplyWindowInsetsListener { view, insets -> {
val statusBarSize = insets.systemWindowInsetTop
return insets
}
This was added in API 20 and is also backported via ViewAppCompat.
On MDPI devices, the status bar is 25px. We can use this as the base and multiply it by the density (rounded up) to get the status bar height on any device:
int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);
For reference: ldpi=.75, mdpi=1, hdpi=1.5, xhdpi=2
I've merged some solutions together:
public static int getStatusBarHeight(final Context context) {
final Resources resources = context.getResources();
final int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
return resources.getDimensionPixelSize(resourceId);
else
return (int) Math.ceil((VERSION.SDK_INT >= VERSION_CODES.M ? 24 : 25) * resources.getDisplayMetrics().density);
}
another alternative:
final View view = findViewById(android.R.id.content);
runJustBeforeBeingDrawn(view, new Runnable() {
#Override
public void run() {
int statusBarHeight = getResources().getDisplayMetrics().heightPixels - view.getMeasuredHeight();
}
});
EDIT: Alternative to runJustBeforeBeingDrawn: https://stackoverflow.com/a/28136027/878126
According to Material Guidance; height of status bar is 24 dp.
If you want get status bar height in pixels you can use below method:
private static int statusBarHeight(android.content.res.Resources res) {
return (int) (24 * res.getDisplayMetrics().density);
}
which can be called from activity with:
statusBarHeight(getResources());
The default height used to be 25dp. With Android Marshmallow (API 23) the height was reduced to 24dp.
Update: Please be aware that since the age of notches and punch-whole-cameras began, using a static height for the status bar no longer works. Please use window insets instead!
this also work with the refrence link
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Official height is 24dp,
as is stated officially by Google on Android Design webpage.
I have the same problem of having to get the status bar height in an onCreate. This works for me.
private static final int LOW_DPI_STATUS_BAR_HEIGHT = 19;
private static final int MEDIUM_DPI_STATUS_BAR_HEIGHT = 25;
private static final int HIGH_DPI_STATUS_BAR_HEIGHT = 38;
Inside the onCreate:
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
int statusBarHeight;
switch (displayMetrics.densityDpi) {
case DisplayMetrics.DENSITY_HIGH:
statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT;
break;
case DisplayMetrics.DENSITY_MEDIUM:
statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
break;
case DisplayMetrics.DENSITY_LOW:
statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT;
break;
default:
statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
}
See:
http://developer.android.com/reference/android/util/DisplayMetrics.html
http://developer.android.com/guide/practices/ui_guidelines/icon_design.html
Kotlin version that combines two best solutions
fun getStatusBarHeight(): Int {
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
return if (resourceId > 0) resources.getDimensionPixelSize(resourceId)
else Rect().apply { window.decorView.getWindowVisibleDisplayFrame(this) }.top
}
Takes status_bar_height value if present
If status_bar_height is not present, calculates the status bar height from Window decor
Yes when i try it with View it provides the result of 25px.
Here is the whole code :
public class SpinActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout lySpin = new LinearLayout(this);
lySpin.setOrientation(LinearLayout.VERTICAL);
lySpin.post(new Runnable()
{
public void run()
{
Rect rect = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int contentViewTop =
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight = contentViewTop - statusBarHeight;
System.out.println("TitleBarHeight: " + titleBarHeight
+ ", StatusBarHeight: " + statusBarHeight);
}
}
}
}
240x320 - 20px
320x480 - 25px
480x800+ - 38px
Try this:
Rect rect = new Rect();
Window win = this.getWindow();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight = contentViewTop - statusBarHeight;
Log.d("ID-ANDROID-CONTENT", "titleBarHeight = " + titleBarHeight );
it didn't work for me in the onCreate method for the activity, but did when I put it in an onClickListener and gave me a measurement of 25
the height of the status bar is 24dp in android 6.0
<!-- Height of the status bar -->
<dimen name="status_bar_height">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
you can find the answer in the source code: frameworks\base\core\res\res\values\dimens.xml
To solve this, I used a combination approach.
This is necessary as on tablets the system bar already subtracts it's pixels when display.getHeight() is called.
So I first check if a system bar is present, and then Ben Claytons approach, which works fine on phones.
public int getStatusBarHeight() {
int statusBarHeight = 0;
if (!hasOnScreenSystemBar()) {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
}
return statusBarHeight;
}
private boolean hasOnScreenSystemBar() {
Display display = getWindowManager().getDefaultDisplay();
int rawDisplayHeight = 0;
try {
Method getRawHeight = Display.class.getMethod("getRawHeight");
rawDisplayHeight = (Integer) getRawHeight.invoke(display);
} catch (Exception ex) {
}
int UIRequestedHeight = display.getHeight();
return rawDisplayHeight - UIRequestedHeight > 0;
}
Thanks to #Niklas +1 this is the correct way to do it.
public class MyActivity extends Activity implements android.support.v4.View.OnApplyWindowInsetsListener {
Rect windowInsets;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
View rootview = findViewById(android.R.id.content);
android.support.v4.View.ViewCompat.setOnApplyWindowInsetsListener(rootview, this);
}
android.support.v4.View.WindowInsetsCompat android.support.v4.View.OnApplyWindowInsetsListener.OnApplyWindowInsets(View v, android.support.v4.View.WindowInsetsCompat insets)
{
windowInsets = new Rect();
windowInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
//StatusBarHeight = insets.getSystemWindowInsetTop();
//Refresh/Adjust view accordingly
return insets;
}
}
Please excuse me if the code isn't 100% correct, converted it from Xamarin C# but this is the just of it. Works with Notches, etc.
Toggled Fullscreen Solution:
This solution may look like a workaround, but it actually accounts for whether your app is fullscreen (aka hiding the status bar) or not:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int barheight = size.y - findViewById(R.id.rootView).getHeight();
This way, if your app is currently fullscreen, barheight will equal 0.
Personally I had to use this to correct absolute TouchEvent coordinates to account for the status bar as so:
#Override
public boolean onTouch(View view,MotionEvent event) {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int YCoord = (int)event.getRawY() - size.y + rootView.getHeight());
}
And that will get the absolute y-coordinate whether the app be fullscreen or not.
Enjoy
The reason why the top answer does not work for some people is because you cannot get the dimensions of a view until it is ready to render. Use an OnGlobalLayoutListener to get said dimensions when you actually can:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
// Nice one, Google
decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Rect rect = new Rect();
decorView.getWindowVisibleDisplayFrame(rect);
rect.top; // This is the height of the status bar
}
}
}
This is the most reliable method.
On Android 4.1 and higher, you can set your application's content to appear behind the status bar, so that the content doesn't resize as the status bar hides and shows. To do this, use SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN. You may also need to use SYSTEM_UI_FLAG_LAYOUT_STABLE to help your app maintain a stable layout.
When you use this approach, it becomes your responsibility to ensure that critical parts of your app's UI (for example, the built-in controls in a Maps application) don't end up getting covered by system bars. This could make your app unusable. In most cases you can handle this by adding the android:fitsSystemWindows attribute to your XML layout file, set to true. This adjusts the padding of the parent ViewGroup to leave space for the system windows. This is sufficient for most applications.
In some cases, however, you may need to modify the default padding to get the desired layout for your app. To directly manipulate how your content lays out relative to the system bars (which occupy a space known as the window's "content insets"), override fitSystemWindows(Rect insets). The fitSystemWindows() method is called by the view hierarchy when the content insets for a window have changed, to allow the window to adjust its content accordingly. By overriding this method you can handle the insets (and hence your app's layout) however you want.
form:
https://developer.android.com/training/system-ui/status.html#behind
If you know exactly the size VS height
like
for example in a device with 320 X 480 screen size the status bar height is 25px, for a device with 480 x 800 the status bar height must be 38px
then you can just get the width of your view / the screen size you can just use an if else statement to get the height of status bar
Since multi-window mode is available now, your app may not have statusbar on top.
Following solution handle all the cases automatically for you.
android:fitsSystemWindows="true"
or programatically
findViewById(R.id.your_root_view).setFitsSystemWindows(true);
you may also get root view by
findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)
For more details on getting root-view refer - https://stackoverflow.com/a/4488149/9640177
This issue recently became relevant for me because of the notch in my Pixel 3XL. I really liked android developer's solution, but I wanted to be able to get the status bar height at will, since it was specifically necessary for a full screen animation that I needed to play. The function below enabled a reliable query:
private val DEFAULT_INSET = 96
fun getInsets(view: View?): Int {
var inset = DEFAULT_INSET
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Safe because only P supports notches
inset = view?.rootWindowInsets?.stableInsetTop ?: DEFAULT_INSET
}
return inset
}
fun blurView(rootView: View?, a: SpacesActivity?) {
val screenBitmap = getBitmapFromView(rootView!!)
val heightDifference = getInsets(rootView)
val croppedMap = Bitmap.createBitmap(
screenBitmap, 0, heightDifference,
screenBitmap.width,
screenBitmap.height - heightDifference)
val blurredScreen = blurBitmap(croppedMap)
if (blurredScreen != null) {
val myDrawable = BitmapDrawable(a!!.resources, blurredScreen)
a.errorHudFrameLayout?.background = myDrawable
a.appBarLayout?.visibility = View.INVISIBLE
}
}
And then in the activity class:
fun blurView() {
this.runOnUiThread {
Helper.blurView(this)
}
}
You will of course want to make pass a weak reference of the activity to the static Helper class method parameter, but for the sake of brevity I refrained in this example. The blurBitmapand errorHudFrameLayout are omitted for the same reason, since they don't directly pertain to obtaining the height of the status bar.

Categories

Resources