Android-虚拟导航键显示隐藏监听及自动设定高度

虚拟导航键显示隐藏监听及自动设定高度

问题描述

某些型号在某些布局下使用虚拟导航栏不能自动调整布局,导致遮挡。特别是华为手机。。。

问题解决步骤

  1. 获取根布局
  2. 设置 ViewTree 的全局界面监听
  3. 当捕获到界面更新时,去判断虚拟导航键是否弹出或隐藏然后做出相应的操作

实现

1. 获取根布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MainActivity implements ViewTreeObserver.OnGlobalLayoutListener{
//虚拟导航栏自适应
FrameLayout content;
private boolean mLayoutComplete = false;

...
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
content = (FrameLayout) findViewById(android.R.id.content);
}


//捕获界面监听
@Override
public void onGlobalLayout() {
...
}

...
}

2. 设置监听

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
content = (FrameLayout) findViewById(android.R.id.content);
content.post(new Runnable() {
@Override
public void run() {
mLayoutComplete = true;
LogUtils.d("content 布局完成");
}
});
content.getViewTreeObserver().addOnGlobalLayoutListener(this);
}

3. 捕获监听事件并做出虚拟导航是否隐藏的相应操作

捕获监听
1
2
3
4
5
6
@Override
public void onGlobalLayout() {
LogUtils.d("onGlobalLayout");
if (!mLayoutComplete) return;
onNavigationBarStatusChanged();
}
虚拟导航是否隐藏的相应操作

在这里我判断虚拟导航键是否弹出的依据是 当前屏幕真实高度 是否大于 屏幕高度

1
2
3
4
5
6
7
8
9
protected void onNavigationBarStatusChanged() { 
//这里的操作是为虚拟导航键留出相应高度,以适应某些型号在使用虚拟导航栏不能自动调整布局,导致遮挡。
if (ScreenUtils.getRealHeight() > ScreenUtils.getHeight()) {
getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0,ScreenUtils.getNavigationBarHeight(this));
getWindow().setNavigationBarColor(Color.parseColor("#000000"));
} else {
getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, 0);
}
}

4.其他方法

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
public class ScreenUtils {
/**
* 非全面屏下 虚拟键高度(无论是否隐藏)
* @param context
* @return
*/
public static int getNavigationBarHeight(Context context){
int result = 0;
int resourceId = context.getResources().getIdentifier("navigation_bar_height","dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}

/**
* 获取手机屏幕高度
*/
public static int getHeight() {
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) BaseApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}

/**
* 获取屏幕真实高度(包括虚拟键盘)
*
*/
public static int getRealHeight() {
WindowManager windowManager = (WindowManager) BaseApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
display.getRealMetrics(dm);
} else {
display.getMetrics(dm);
}
int realHeight = dm.heightPixels;
return realHeight;
}

}

总结

以下为封装代码

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
/**
* @ClassName: ScreenUtils
* @Description:
* @Author: pinguoooo
* @Date: 2020/9/1 13:48
*/
public class ScreenUtils {

/**
* 非全面屏下 虚拟键高度(无论是否隐藏)
*
* @param context
* @return
*/
public static int getNavigationBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}


/**
* 获取手机屏幕高度
*/
public static int getHeight() {
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) BaseApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}

/**
* 获取屏幕真实高度(包括虚拟键盘)
*/
public static int getRealHeight() {
WindowManager windowManager = (WindowManager) BaseApplication.getInstance().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
display.getRealMetrics(dm);
} else {
display.getMetrics(dm);
}
int realHeight = dm.heightPixels;
return realHeight;
}

public interface NavigationListener {
void show();

void hide();
}


//虚拟导航栏显示/隐藏
public static void setNavigationListener(final View rootView, final NavigationListener navigationListener) {
if (rootView == null || navigationListener == null) {
return;
}

rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (ScreenUtils.getRealHeight() > ScreenUtils.getHeight()) {
//显示虚拟按键
if (navigationListener != null) {
navigationListener.show();
}
} else {
//隐藏虚拟按键
if (navigationListener != null) {
navigationListener.hide();
}
}
}
});

}
}

注: 在使用 setNavigationListener 时,传入的 rootView 为对应的 android.R.id.content 布局(FrameLayout 类型),传入别的可能没有效果。在这里我判断虚拟导航键是否弹出的依据是 当前屏幕真实高度 是否大于 屏幕高度

之后在使用时只需要对出现虚拟导航栏出现覆盖问题的 Activity 添加对 rootView 的监听,即可方便的实现虚拟导航栏隐藏与显示的监听。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
content = (FrameLayout) findViewById(android.R.id.content);
ScreenUtils.setNavigationListener(content, new ScreenUtils.NavigationListener() {
@Override
public void show() {
// 虚拟导航栏显示的操作
}

@Override
public void hide() {
// 虚拟导航栏隐藏的操作
}
});
}

Android-虚拟导航键显示隐藏监听及自动设定高度

http://example.com/2021/06/25/Android-虚拟导航键显示隐藏监听及自动设定高度/

Author

Pinguoooo

Posted on

2021-06-25

Updated on

2021-06-25

Licensed under

Comentarios

:D 一言句子获取中...

Loading...Wait a Minute!