-
Notifications
You must be signed in to change notification settings - Fork 34
/
SystemBarUtil.java
276 lines (260 loc) · 11.6 KB
/
SystemBarUtil.java
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
package com.liyi.sutils.utils;
import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
/**
* 系统状态栏与底部导航栏相关工具类
* <p>仅在 SDK >= 4.4 时有效</p>
* <p>本工具类共分两种模式:着色模式{@link #setDisplayOption} 和 全透明模式{@link #fullTransparentBar}</p>
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public final class SystemBarUtil {
private static final String TAG_STATUS_BAR = "StatusBar";
private static final String TAG_NAVIGATION_BAR = "NavigationBar";
/* 无效的颜色值 */
private static final int INVALID_VAL = -1;
/* 默认的状态栏颜色 */
private static final int DEFAULT_STATUS_COLOR = 0x10000000;
/* 默认的底部导航栏颜色 */
private static final int DEFAULT_NAVIGATION_COLOR = Color.TRANSPARENT;
private SystemBarUtil() {
throw new UnsupportedOperationException("cannot be instantiated");
}
/***********************************************************************************************
**** 沉浸式系统栏(状态栏与导航栏),着色模式,不可全透明(sdk >= 4.4)
**********************************************************************************************/
/**
* 设置状态栏和底部导航栏的显示方式
*
* @param activity activity
* @param fitSystemWindow {@code true}: 内容不会显示到状态栏和导航栏上<br>{@code false}: 内容显示到状态栏和导航栏上
* @param clipToPadding {@code true}: 裁剪 padding 区域,padding 区域不可使用<br>{@code false}: 不裁剪 padding 区域,padding 区域可使用
*/
public static void setDisplayOption(@NonNull Activity activity, boolean fitSystemWindow, boolean clipToPadding) {
// 获取根布局
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
rootView.setClipToPadding(clipToPadding);
rootView.setFitsSystemWindows(fitSystemWindow);
}
/**
* 设置顶部状态栏
*
* @param activity
* @param color 设置顶部状态栏的颜色
*/
public static void setupStatusBar(@NonNull Activity activity, @ColorInt int color) {
int statusHeight = ScreenUtil.getStatusBarHeight();
int statusColor = DEFAULT_STATUS_COLOR;
if (color != INVALID_VAL) {
statusColor = color;
}
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
// 防止重复添加 statusBarView
removeStatusBarView(decorView);
// 绘制一个和状态栏一样高的矩形 View
View statusBarView = createStatusBarView(activity, statusHeight, statusColor);
// 添加 statusBarView 到整个Window的最顶层布局中,这里的 statusBarView 只是作为状态栏的背景,
// 它的 visible 不能影响到状态栏的 visible
decorView.addView(statusBarView);
}
/**
* 绘制一个和状态栏一样高的矩形View
*
* @param activity
* @param statusHeight 绘制的矩形的高度
* @param statusColor 绘制的矩形的颜色
* @return 绘制的矩形 View
*/
private static View createStatusBarView(@NonNull Activity activity, int statusHeight, @ColorInt int statusColor) {
View statusBarView = new View(activity);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, statusHeight);
params.gravity = Gravity.TOP;
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(statusColor);
statusBarView.setTag(TAG_STATUS_BAR);
return statusBarView;
}
/**
* 移除已经存在的 statusBarView
*
* @param decorView
*/
private static void removeStatusBarView(@NonNull ViewGroup decorView) {
View statusBarView = decorView.findViewWithTag(TAG_STATUS_BAR);
if (statusBarView != null) {
decorView.removeView(statusBarView);
}
}
/**
* 设置状态栏的透明度
*
* @param activity
* @param alpha 透明度(0-1)
*/
public static void setStatusBarAlpha(@NonNull Activity activity, @FloatRange(from = 0, to = 1) float alpha) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View statusView = decorView.findViewWithTag(TAG_STATUS_BAR);
if (statusView != null) {
statusView.setAlpha(alpha);
}
}
/**
* 设置状态栏的显示和隐藏
*
* @param activity
* @param isShow {@code true}: 显示<br>{@code false}: 隐藏
*/
public static void showStatusBar(@NonNull Activity activity, boolean isShow) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View statusView = decorView.findViewWithTag(TAG_STATUS_BAR);
if (isShow) {
if (statusView != null) {
statusView.setVisibility(View.VISIBLE);
}
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
if (statusView != null) {
statusView.setVisibility(View.GONE);
}
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
/**
* 设置底部导航栏
*
* @param activity
* @param color 底部导航栏的颜色
*/
public static void setupNavBar(@NonNull Activity activity, @ColorInt int color) {
if (ScreenUtil.hasNavigationBar()) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
int navHeight = ScreenUtil.getNavBarHeight();
int navColor = DEFAULT_NAVIGATION_COLOR;
if (color != INVALID_VAL) {
navColor = color;
}
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
removeNavBarView(decorView);
View navBarView = createNavBarView(activity, navHeight, navColor);
decorView.addView(navBarView);
}
}
/**
* 绘制一个和底部导航栏一样高的矩形 View
*
* @param activity
* @param navHeight 绘制的矩形的高度
* @param navColor 绘制的矩形的颜色
* @return 绘制的矩形 View
*/
private static View createNavBarView(@NonNull Activity activity, int navHeight, @ColorInt int navColor) {
View navBarView = new View(activity);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, navHeight);
params.gravity = Gravity.BOTTOM;
navBarView.setLayoutParams(params);
navBarView.setBackgroundColor(navColor);
navBarView.setTag(TAG_NAVIGATION_BAR);
return navBarView;
}
/**
* 移除已经存在的 navBarView
*
* @param decorView
*/
private static void removeNavBarView(@NonNull ViewGroup decorView) {
View navBarView = decorView.findViewWithTag(TAG_NAVIGATION_BAR);
if (navBarView != null) {
decorView.removeView(navBarView);
}
}
/**
* 设置底部导航栏的透明度
*
* @param activity
* @param alpha 透明度(0-1)
*/
public static void setNavBarAlpha(@NonNull Activity activity, @FloatRange(from = 0, to = 1) float alpha) {
if (ScreenUtil.hasNavigationBar()) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View navBarView = decorView.findViewWithTag(TAG_NAVIGATION_BAR);
if (navBarView != null) {
navBarView.setAlpha(alpha);
}
}
}
/**
* 设置底部导航栏的显示和隐藏
*
* @param activity activity
* @param isShow {@code true}: 显示<br>{@code false}: 隐藏
*/
public static void showNavBar(@NonNull Activity activity, boolean isShow) {
if (ScreenUtil.hasNavigationBar()) {
View decorView = activity.getWindow().getDecorView();
if (isShow) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
} else {
decorView.setSystemUiVisibility(View.INVISIBLE);
}
}
}
/***********************************************************************************************
**** 沉浸式系统栏(状态栏与导航栏),全透明模式,(sdk >= 5.0)
**********************************************************************************************/
/**
* 设置系统栏全透明
*
* @param activity
* @param statusBar 状态栏是否全透明
* @param navBar 导航栏是否全透明
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static void fullTransparentBar(Activity activity, boolean statusBar, boolean navBar) {
Window window = activity.getWindow();
window.clearFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
if (statusBar && navBar) {
window.getDecorView().setSystemUiVisibility(
// 全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity 顶端布局部分会被状态遮住
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// 隐藏导航栏
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// 防止系统栏隐藏时内容区域大小发生变化
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(Color.TRANSPARENT);
} else if (statusBar && !navBar) {
window.getDecorView().setSystemUiVisibility(
// 全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity 顶端布局部分会被状态遮住
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// 防止系统栏隐藏时内容区域大小发生变化
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
} else if (!statusBar && navBar) {
window.getDecorView().setSystemUiVisibility(
// 全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity 顶端布局部分会被状态遮住
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// 隐藏导航栏
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// 防止系统栏隐藏时内容区域大小发生变化
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setNavigationBarColor(Color.TRANSPARENT);
}
}
}