獲取屏幕寬,高的方法,包括考慮到通知欄,導航欄等等

平常我們做開發的時候,常用的方法就是獲取屏幕寬高,但是真正的屏幕寬高是什麼,顧名思義,屏幕的寬是屏幕的寬,但是屏幕的高到底是指哪一部分的高,整體的高?還是顯示區域的高,此時屏幕的高是指包括導航欄和狀態欄嗎,還是不包括,如果沒有系統導航欄的時候,屏幕的高是指哪,如果有導航欄呢?沒有具體的定義,所以,我總結了一些屏幕高度方法.

 

/**
	 * 通過反射拿到屏幕實際的高度(包括狀態欄和導航欄),獲取的是正常豎屏的高
	 */
	public int getScreenRealHeight() {
		int dpi = 0;
		Display display = ((Activity) mContext).getWindowManager().getDefaultDisplay();
		DisplayMetrics dm = new DisplayMetrics();
		@SuppressWarnings("rawtypes")
		Class c;
		try {
			c = Class.forName("android.view.Display");
			@SuppressWarnings("unchecked")
			Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
			method.invoke(display, dm);
			if (isScreenLandscape()) {
				dpi = dm.widthPixels;
			} else {
				dpi = dm.heightPixels;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (dpi == 0) {
			if (isScreenLandscape()) {
				dpi = getScreenWidth();
			} else {
				if (ImmersionBar.hasNotchScreen((Activity) mContext)) {
					dpi = getScreenAvailableHeight() + getNotchHeight() + getNavigationBarHeight();
				} else {
					dpi = getScreenAvailableHeight() + getStatusBarHeight() + getNavigationBarHeight();
				}
			}
		}
		return dpi;
	}

 

	/**
	 * 計算屏幕可用高度(如果底部導航欄顯示,高度爲底部導航欄上到頂部狀態欄下,如果底部導航欄不顯示,高度爲屏幕底部到頂部狀態欄下)
	 */
	public int getScreenAvailableHeight() {
		Rect rect = new Rect();
		mWindow.getDecorView().getWindowVisibleDisplayFrame(rect);
		if (isScreenLandscape()) {
			return rect.right - rect.left;
		} else {
			return rect.bottom - rect.top;
		}
	}
	/**
	 * 獲取導航欄虛擬按鍵的高度,如果虛擬按鍵隱藏就返回0,否則返回虛擬按鍵的高度
	 */
	public int getNavigationBarHeight() {
		if (isNavigationBarShow()) {
			return calculateNavigationBarHeight();
		} else {
			mNavigationBarHeight = 0;
			return mNavigationBarHeight;
		}
	}
/**
	 * 計算虛擬按鍵的高度
	 */
	private int calculateNavigationBarHeight() {
		if (mNavigationBarHeight == 0) {
			try {
				Class<?> clazz = Class.forName("com.android.internal.R$dimen");
				Object object = clazz.newInstance();
				int height = Integer.parseInt(clazz.getField("navigation_bar_height").get(object).toString());
				mNavigationBarHeight = mContext.getResources().getDimensionPixelSize(height);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		if (mNavigationBarHeight == 0) {
			Resources res = mContext.getResources();
			int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
			if (resourceId > 0) {
				mNavigationBarHeight = res.getDimensionPixelSize(resourceId);
			}
		}

		if (mNavigationBarHeight == 0) {
			Rect rect = new Rect();
			mWindow.getDecorView().getWindowVisibleDisplayFrame(rect);
			Point realSize = new Point();
			mWindowManager.getDefaultDisplay().getRealSize(realSize);
			mNavigationBarHeight = realSize.y - rect.bottom;
		}
		return mNavigationBarHeight;
	}
/**
	 * 判斷虛擬導航欄是否顯示
	 *
	 * @return true(顯示虛擬導航欄),false(不顯示或不支持虛擬導航欄)
	 */
	public boolean isNavigationBarShow() {
		//判斷小米手機是否開啓了全面屏,開啓了,直接返回false
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
			if (Settings.Global.getInt(mContext.getContentResolver(), "force_fsg_nav_bar", 0) != 0) {
				return false;
			}
		}
		if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
			int screenRealHeight = getScreenRealHeight();
			int statusBarHeight = getStatusBarHeight();
			int screenAvailableHeight = getScreenAvailableHeight();

			return screenAvailableHeight + statusBarHeight < screenRealHeight;
		} else {
			//其他手機根據屏幕真實高度與顯示高度是否相同來判斷
			Display d = mWindowManager.getDefaultDisplay();

			DisplayMetrics realDisplayMetrics = new DisplayMetrics();
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
				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;

			return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
		}
	}

 

/**
	 * 判斷當前屏幕方向是否爲橫屏
	 *
	 * @return true 橫屏  false 豎屏
	 */
	public boolean isScreenLandscape() {
		Configuration mConfiguration = mContext.getResources().getConfiguration(); //獲取設置的配置信息
		int ori = mConfiguration.orientation; //獲取屏幕方向
		return ori == Configuration.ORIENTATION_LANDSCAPE;
	}

以上方法是自己總結的,每個方法都有說明,這裏就不再具體說明了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章