公司项目中使用了popWindow,并且需求指明了popWindow必须是和Activity类似的全屏模式,并且从页面底部弹出!


当popWindow所有设计完毕后,从底部弹出popWindow,发现设置在popWindow的上的titlebar一部分被压入状态栏的底部了,也就是说全屏是全屏了,但是超过了应有的部分!


解决方案:


为了达到良好的兼容性,我们可以如下变现代码

/**



* 用于获取状态栏的高度。



*



* @return 返回状态栏高度的像素值。



*/


private
int
getStatusBarHeight() {



int
statusBarHeight =
0
;



try
{



Class<?> c = Class.forName(
"com.android.internal.R$dimen"
);



Object o = c.newInstance();



Field field = c.getField(
"status_bar_height"
);



int
x = (Integer) field.get(o);



statusBarHeight = getResources().getDimensionPixelSize(x);



}
catch
(Exception e) {



e.printStackTrace();



Rect frame =
new
Rect();



getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);



statusBarHeight = frame.top;



}



return
statusBarHeight;


}

还可以使用Resource对象获取(推荐这种方式)

        
private
int
getStatusBarHeight() {



int
result =
0
;



int
resourceId = getResources().getIdentifier(
"status_bar_height"
,
"dimen"
,
"android"
);



if
(resourceId >
0
) {



result = res.getDimensionPixelSize(resourceId);



}



return
result;



}

-----------------------------------2015-01-29 更新--------------------------------------

公司有测试人员发现,FlymeOS4.x/Android4.4.4出现 了问题,让人一头雾水,因此,这里把问题再次改正一下,目前Android4.4.4的系统不多,只检测到魅族的FlymeOS4.x有问题,所以对FlymeOS着重处理一下。

手写判断是否是Flyme OsS 4.x.x

?

1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


private
boolean
isFlymeOs4x()


{



String sysVersion = android.os.Build.VERSION.RELEASE;



if
(
"4.4.4"
.equals(sysVersion))



{



String sysIncrement = android.os.Build.VERSION.INCREMENTAL;



String displayId = android.os.Build.DISPLAY;



if
(!TextUtils.isEmpty(sysIncrement))



{



return
sysIncrement.contains(
"Flyme_OS_4"
);



}



else



{



return
displayId.contains(
"Flyme OS 4"
);



}



}



return
false
;


}

然后PopWindow改为

?

1


2


3


4


5


6


7


8


9


10


int
statusBarHeight = getStatusBarHeight();


if
(isFlymeOs4x())


{



searchFlightListWindow.setHeight(screenMetrics.heightPixels-statusBarHeight*
2
);



//至于这里为什么乘以2,我只能说,除了鬼鬼们,只有魅族自己知道,我是发现获得的StatusBarHeight偏小,所以乘以2,实践检验是正确的,但也很无语



searchFlightListWindow.showAtLocation(findViewById(R.id.main), Gravity.BOTTOM,
0
,
0
);


}
else
{



searchFlightListWindow.setHeight(screenMetrics.heightPixels-statusBarHeight);



searchFlightListWindow.showAtLocation(findViewById(R.id.main), Gravity.BOTTOM,
0
,
0
);


}

----------------------------

View contentView = getWindow().getDecorView().findViewById(android.R.id.content);

View contentView = getWindow().getDecorView().getChildAt(0);

View titleView = findViewById(Window.ID_ANDROID_CONTENT);

-------------------------2015-05-05更新,沉浸式状态栏---------------------------------

?

1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42


43


44


45


46


47


48


49


50


51


52


53


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72


73


74


75


76


77


78


79


80


81


82


83


84


85


86


87


88


89


90


91


92


93


94


95


96


97


98


99


100


101


102


103


104


105


106


107


108


109


110


111


112


113


114


115


116


117


118


119


120


121


122


123


124


125


126


127


128


129


130


131


132


133


134


135


136


137


138


139


140


141


142


143


144


145


146


147


148


149


150


151


152


153


154


155


156


157


158


159


160


161


162


163


164


165


166


167


168


169


170


171


172


173


174


175


176


177


178


179


180


181


182


183


184


185


186


187


188


189


190


191


192


193


194


195


196


197


198


199


200


201


202


203


204


205


206


207


208


209


210


211


212


213


214


215


216


217


218


219


220


221


222


223


224


225


226


227


228


229


230


231


232


233


234


235


236


237


238


239


240


241


242


243


244


245


246


247


248


249


250


251


252


253


254


255


256


257


258


259


260


261


262


263


264


265


266


267


268


269


270


271


272


273


274


275


276


277


278


279


280


281


282


283


284


285


286


287


288


289


290


291


292


293


294


295


296


297


298


299


300


301


302


303


304


305


306


307


308


309


310


311


312


313


314


315


316


317


318


319


320


321


322


323


324


325


326


327


328


329


330


331


332


333


334


335


336


337


338


339


340


341


342


343


344


345


346


347


348


349


350


351


352


353


354


355


356


357


358


359


360


361


362


363


364


365


366


367


368


369


370


371


372


373


374


375


376


377


378


379


380


381


382


383


384


385


386


387


388


389


390


391


392


393


394


395


396


397


398


399


400


401


402


403


404


405


406


407


408


409


410


411


412


413


414


415


416


417


418


419


420


421


422


423


424


425


426


427


428


429


430


431


432


433


434


435


436


437


438


439


440


441


442


443


444


445


446


447


448


449


450


451


452


453


454


455


456


457


458


459


460


461


462


463


464


465


466


467


468


469


470


471


472


473


474


475


476


477


478


479


480


481


482


483


484


485


486


487


488


489


490


491


492


493


494


495


496


497


498


499


500


501


502


503


504


505


506


507


508


509


510


511


512


513


514


515


516


517


518


519


520


521


522


523


524


525


526


527


528


529


530


531


532


533


534


535


536


537


538


539


540


541


542


543


544


545


546


public
class
SystemBarTintManager {



/**



* The default system bar tint color value.



*/



public
static
final
int
DEFAULT_TINT_COLOR =
0x99000000
;






private
final
SystemBarConfig mConfig;



private
boolean
mStatusBarAvailable;



private
boolean
mNavBarAvailable;



private
boolean
mStatusBarTintEnabled;



private
boolean
mNavBarTintEnabled;



private
View mStatusBarTintView;



private
View mNavBarTintView;



private
static
boolean
sIsMiuiV6;



private
static
String sNavBarOverride =
null
;






static
{



Method methodGetter =
null
;



try
{



Class<?> sysClass = Class.forName(
"android.os.SystemProperties"
);



methodGetter = sysClass.getDeclaredMethod(
"get"
, String.
class
);



sIsMiuiV6 =
"V6"
.equals((String) methodGetter.invoke(sysClass,
"ro.miui.ui.version.name"
));



}
catch
(Exception e) {



e.printStackTrace();



}
finally
{



if
(methodGetter!=
null
)



{



try
{



sNavBarOverride = (String) methodGetter.invoke(
null
,
"qemu.hw.mainkeys"
);



}
catch
(Exception e) {



e.printStackTrace();



sNavBarOverride =
null
;



}



}



}



}



/**



* @param activity The host activity.



*/



@TargetApi
(
19
)



public
SystemBarTintManager(Activity activity) {









Window win = activity.getWindow();



ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();






if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {



// check theme attrs



int
[] attrs = {android.R.attr.windowTranslucentStatus,android.R.attr.windowTranslucentNavigation};



TypedArray a = activity.obtainStyledAttributes(attrs);



try
{



mStatusBarAvailable = a.getBoolean(
0
,
false
);



mNavBarAvailable = a.getBoolean(
1
,
false
);



}
finally
{



a.recycle();



}






// check window flags



WindowManager.LayoutParams winParams = win.getAttributes();



int
bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;



if
((winParams.flags & bits) !=
0
) {



mStatusBarAvailable =
true
;



}



bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;



if
((winParams.flags & bits) !=
0
) {



mNavBarAvailable =
true
;



}



}






mConfig =
new
SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);



// device might not have virtual navigation keys



if
(!mConfig.hasNavigtionBar()) {



mNavBarAvailable =
false
;



}






if
(mStatusBarAvailable) {



setupStatusBarView(activity, decorViewGroup);



}



if
(mNavBarAvailable) {



setupNavBarView(activity, decorViewGroup);



}






}






/**



* Enable tinting of the system status bar.



*



* @param enabled True to enable tinting, false to disable it (default).



*/



public
void
setStatusBarTintEnabled(
boolean
enabled) {



mStatusBarTintEnabled = enabled;



if
(mStatusBarAvailable) {



mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);



}



}






/**



* set status bar darkmode



* @param darkmode



* @param activity



*/



public
void
setStatusBarDarkMode(
boolean
darkmode, Activity activity) {



if
(sIsMiuiV6) {



Class<?
extends
Window> clazz = activity.getWindow().getClass();



try
{



int
darkModeFlag =
0
;



Class<?> layoutParams = Class.forName(
"android.view.MiuiWindowManager$LayoutParams"
);



Field field = layoutParams.getField(
"EXTRA_FLAG_STATUS_BAR_DARK_MODE"
);



darkModeFlag = field.getInt(layoutParams);



Method extraFlagField = clazz.getMethod(
"setExtraFlags"
,
int
.
class
,
int
.
class
);



extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag :
0
, darkModeFlag);



}
catch
(Exception e) {



e.printStackTrace();



}



}



}






/**



* Enable tinting of the system navigation bar.



* @param enabled True to enable tinting, false to disable it (default).



*/



public
void
setNavigationBarTintEnabled(
boolean
enabled) {



mNavBarTintEnabled = enabled;



if
(mNavBarAvailable) {



mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);



}



}






/**



* Apply the specified color tint to all system UI bars.



*



* @param color The color of the background tint.



*/



public
void
setTintColor(
int
color) {



setStatusBarTintColor(color);



setNavigationBarTintColor(color);



}






/**



* Apply the specified drawable or color resource to all system UI bars.



*



* @param res The identifier of the resource.



*/



public
void
setTintResource(
int
res) {



setStatusBarTintResource(res);



setNavigationBarTintResource(res);



}






/**



* Apply the specified drawable to all system UI bars.



*



* @param drawable The drawable to use as the background, or null to remove it.



*/



public
void
setTintDrawable(Drawable drawable) {



setStatusBarTintDrawable(drawable);



setNavigationBarTintDrawable(drawable);



}






/**



* Apply the specified alpha to all system UI bars.



*



* @param alpha The alpha to use



*/



public
void
setTintAlpha(
float
alpha) {



setStatusBarAlpha(alpha);



setNavigationBarAlpha(alpha);



}






/**



* Apply the specified color tint to the system status bar.



*



* @param color The color of the background tint.



*/



public
void
setStatusBarTintColor(
int
color) {



if
(mStatusBarAvailable) {



mStatusBarTintView.setBackgroundColor(color);



}



}






/**



* Apply the specified drawable or color resource to the system status bar.



*



* @param res The identifier of the resource.



*/



public
void
setStatusBarTintResource(
int
res) {



if
(mStatusBarAvailable) {



mStatusBarTintView.setBackgroundResource(res);



}



}






/**



* Apply the specified drawable to the system status bar.



*



* @param drawable The drawable to use as the background, or null to remove it.



*/



@SuppressWarnings
(
"deprecation"
)



public
void
setStatusBarTintDrawable(Drawable drawable) {



if
(mStatusBarAvailable) {



mStatusBarTintView.setBackgroundDrawable(drawable);



}



}






/**



* Apply the specified alpha to the system status bar.



*



* @param alpha The alpha to use



*/



@TargetApi
(
11
)



public
void
setStatusBarAlpha(
float
alpha) {



if
(mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {



mStatusBarTintView.setAlpha(alpha);



}



}






/**



* Apply the specified color tint to the system navigation bar.



*



* @param color The color of the background tint.



*/



public
void
setNavigationBarTintColor(
int
color) {



if
(mNavBarAvailable) {



mNavBarTintView.setBackgroundColor(color);



}



}






/**



* Apply the specified drawable or color resource to the system navigation bar.



*



* @param res The identifier of the resource.



*/



public
void
setNavigationBarTintResource(
int
res) {



if
(mNavBarAvailable) {



mNavBarTintView.setBackgroundResource(res);



}



}






/**



* Apply the specified drawable to the system navigation bar.



*



* @param drawable The drawable to use as the background, or null to remove it.



*/



@SuppressWarnings
(
"deprecation"
)



public
void
setNavigationBarTintDrawable(Drawable drawable) {



if
(mNavBarAvailable) {



mNavBarTintView.setBackgroundDrawable(drawable);



}



}






/**



* Apply the specified alpha to the system navigation bar.



*



* @param alpha The alpha to use



*/



@TargetApi
(
11
)



public
void
setNavigationBarAlpha(
float
alpha) {



if
(mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {



mNavBarTintView.setAlpha(alpha);



}



}






/**



* Get the system bar configuration.



* @return The system bar configuration for the current device configuration.



*/



public
SystemBarConfig getConfig() {



return
mConfig;



}






/**



* Is tinting enabled for the system status bar?



* @return True if enabled, False otherwise.



*/



public
boolean
isStatusBarTintEnabled() {



return
mStatusBarTintEnabled;



}






/**



* Is tinting enabled for the system navigation bar?



* @return True if enabled, False otherwise.



*/



public
boolean
isNavBarTintEnabled() {



return
mNavBarTintEnabled;



}






private
void
setupStatusBarView(Context context, ViewGroup decorViewGroup) {



mStatusBarTintView =
new
View(context);



LayoutParams params =
new
LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());



params.gravity = Gravity.TOP;



if
(mNavBarAvailable && !mConfig.isNavigationAtBottom()) {



params.rightMargin = mConfig.getNavigationBarWidth();



}



mStatusBarTintView.setLayoutParams(params);



mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);



mStatusBarTintView.setVisibility(View.GONE);



decorViewGroup.addView(mStatusBarTintView);



}






private
void
setupNavBarView(Context context, ViewGroup decorViewGroup) {



mNavBarTintView =
new
View(context);



LayoutParams params;



if
(mConfig.isNavigationAtBottom()) {



params =
new
LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());



params.gravity = Gravity.BOTTOM;



}
else
{



params =
new
LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);



params.gravity = Gravity.RIGHT;



}



mNavBarTintView.setLayoutParams(params);



mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);



mNavBarTintView.setVisibility(View.GONE);



decorViewGroup.addView(mNavBarTintView);



}






/**



* Class which describes system bar sizing and other characteristics for the current



* device configuration.



*



*/



public
static
class
SystemBarConfig {






private
static
final
String STATUS_BAR_HEIGHT_RES_NAME =
"status_bar_height"
;



private
static
final
String NAV_BAR_HEIGHT_RES_NAME =
"navigation_bar_height"
;



private
static
final
String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME =
"navigation_bar_height_landscape"
;



private
static
final
String NAV_BAR_WIDTH_RES_NAME =
"navigation_bar_width"
;



private
static
final
String SHOW_NAV_BAR_RES_NAME =
"config_showNavigationBar"
;






private
final
boolean
mTranslucentStatusBar;



private
final
boolean
mTranslucentNavBar;



private
final
int
mStatusBarHeight;



private
final
int
mActionBarHeight;



private
final
boolean
mHasNavigationBar;



private
final
int
mNavigationBarHeight;



private
final
int
mNavigationBarWidth;



private
final
boolean
mInPortrait;



private
final
float
mSmallestWidthDp;






private
SystemBarConfig(Activity activity,
boolean
translucentStatusBar,
boolean
traslucentNavBar) {



Resources res = activity.getResources();



mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);



mSmallestWidthDp = getSmallestWidthDp(activity);



mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);



mActionBarHeight = getActionBarHeight(activity);



mNavigationBarHeight = getNavigationBarHeight(activity);



mNavigationBarWidth = getNavigationBarWidth(activity);



mHasNavigationBar = (mNavigationBarHeight >
0
);



mTranslucentStatusBar = translucentStatusBar;



mTranslucentNavBar = traslucentNavBar;



}






@TargetApi
(
14
)



private
int
getActionBarHeight(Context context) {



int
result =
0
;



if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {



TypedValue tv =
new
TypedValue();



context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv,
true
);



result = context.getResources().getDimensionPixelSize(tv.resourceId);



}



return
result;



}






@TargetApi
(
14
)



private
int
getNavigationBarHeight(Context context) {



Resources res = context.getResources();



int
result =
0
;



if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {



if
(!hasNavBar(context)) {



String key;



if
(mInPortrait) {



key = NAV_BAR_HEIGHT_RES_NAME;



}
else
{



key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;



}



return
getInternalDimensionSize(res, key);



}



}



return
result;



}






@TargetApi
(
14
)



private
int
getNavigationBarWidth(Context context) {



Resources res = context.getResources();



int
result =
0
;



if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {



if
(!hasNavBar(context))



{



return
getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);



}



}



return
result;



}






private
int
getInternalDimensionSize(Resources res, String key) {



int
result =
0
;



int
resourceId = res.getIdentifier(key,
"dimen"
,
"android"
);



if
(resourceId >
0
) {



result = res.getDimensionPixelSize(resourceId);



}



return
result;



}






@SuppressLint
(
"NewApi"
)



private
float
getSmallestWidthDp(Activity activity) {



DisplayMetrics metrics =
new
DisplayMetrics();



if
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {



activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);



}
else
{



// TODO this is not correct, but we don't really care pre-kitkat



activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);



}



float
widthDp = metrics.widthPixels / metrics.density;



float
heightDp = metrics.heightPixels / metrics.density;



return
Math.min(widthDp, heightDp);



}






/**



* Should a navigation bar appear at the bottom of the screen in the current



* device configuration? A navigation bar may appear on the right side of



* the screen in certain configurations.



*



* @return True if navigation should appear at the bottom of the screen, False otherwise.



*/



public
boolean
isNavigationAtBottom() {



return
(mSmallestWidthDp >=
600
|| mInPortrait);



}






/**



* Get the height of the system status bar.



*



* @return The height of the status bar (in pixels).



*/



public
int
getStatusBarHeight() {



return
mStatusBarHeight;



}






/**



* Get the height of the action bar.



*



* @return The height of the action bar (in pixels).



*/



public
int
getActionBarHeight() {



return
mActionBarHeight;



}






/**



* Does this device have a system navigation bar?



*



* @return True if this device uses soft key navigation, False otherwise.



*/



public
boolean
hasNavigtionBar() {



return
mHasNavigationBar;



}






/**



* Get the height of the system navigation bar.



*



* @return The height of the navigation bar (in pixels). If the device does not have



* soft navigation keys, this will always return 0.



*/



public
int
getNavigationBarHeight() {



return
mNavigationBarHeight;



}






/**



* Get the width of the system navigation bar when it is placed vertically on the screen.



*



* @return The width of the navigation bar (in pixels). If the device does not have



* soft navigation keys, this will always return 0.



*/



public
int
getNavigationBarWidth() {



return
mNavigationBarWidth;



}






/**



* Get the layout inset for any system UI that appears at the top of the screen.



*



* @param withActionBar True to include the height of the action bar, False otherwise.



* @return The layout inset (in pixels).



*/



public
int
getPixelInsetTop(
boolean
withActionBar) {



return
(mTranslucentStatusBar ? mStatusBarHeight :
0
) + (withActionBar ? mActionBarHeight :
0
);



}






/**



* Get the layout inset for any system UI that appears at the bottom of the screen.



*



* @return The layout inset (in pixels).



*/



public
int
getPixelInsetBottom() {



if
(mTranslucentNavBar && isNavigationAtBottom()) {



return
mNavigationBarHeight;



}
else
{



return
0
;



}



}






/**



* Get the layout inset for any system UI that appears at the right of the screen.



*



* @return The layout inset (in pixels).



*/



public
int
getPixelInsetRight() {



if
(mTranslucentNavBar && !isNavigationAtBottom()) {



return
mNavigationBarWidth;



}
else
{



return
0
;



}



}






private
boolean
hasNavBar(Context context) {



Resources res = context.getResources();



int
resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME,
"bool"
,
"android"
);



if
(resourceId !=
0
) {



boolean
hasNav = res.getBoolean(resourceId);



// check override flag (see static block)



if
(
"1"
.equals(sNavBarOverride)) {



hasNav =
false
;



}
else
if
(
"0"
.equals(sNavBarOverride)) {



hasNav =
true
;



}



return
hasNav;



}
else
{
// fallback



return
!hasPermanentMenuKey(context);



}



}






private
boolean
hasPermanentMenuKey(Context cxt) {



try
{



WindowManager wm = (WindowManager) cxt.getSystemService(Context.WINDOW_SERVICE);






ViewConfiguration config = ViewConfiguration.get(cxt);



Field menuKeyField = ViewConfiguration.
class



.getDeclaredField(
"sHasPermanentMenuKey"
);



if
(menuKeyField !=
null
) {



menuKeyField.setAccessible(
true
);



return
menuKeyField.getBoolean(config);



}



}
catch
(Exception e) {



e.printStackTrace();



}






return
false
;



}






}