Android 水滴屏、全屏适配
Android 水滴屏、全屏适配
何谓刘海屏?何谓水滴屏?
上述两种屏幕都可以统称为刘海屏,不过对于右侧较小的刘海,业界一般称为水滴屏或美人尖。
目前国内流行的手机厂商主要有:vivo、oppo、华为、小米。各厂商对刘海屏的适配都大不相同,各自有各自对刘海屏的适配API,具体的适配方法可以阅读相应的官网:
VIVO: https://dev.vivo.com.cn/documentCenter/doc/103
OPPO: https://open.oppomobile.com/wiki/doc#id=10159
小米: https://dev.mi.com/console/doc/detail?pId=1293
华为: https://developer.huawei.com/consumer/cn/devservice/doc/50114?from=timeline
下面介绍几种适配方法:
1.StatusBarUtil
工具类
1.1 StatusBarUtil
工具类
public class StatusBarUtil {
//透明度
public static final int DEFAULT_STATUS_BAR_ALPHA = 112;
private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view;
private static final int FAKE_TRANSLUCENT_VIEW_ID = R.id.statusbarutil_translucent_view;
private static final int TAG_KEY_HAVE_SET_OFFSET = -123;
/**
* 设置状态栏颜色
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
public static void setColor(Activity activity, @ColorInt int color) {
setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
} else {
decorView.addView(createStatusBarView(activity, color, statusBarAlpha));
}
setRootView(activity);
}
}
/**
* 为滑动返回界面设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
*/
public static void setColorForSwipeBack(Activity activity, int color) {
setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 为滑动返回界面设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColorForSwipeBack(Activity activity, @ColorInt int color,
@IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content));
View rootView = contentView.getChildAt(0);
int statusBarHeight = getStatusBarHeight(activity);
if (rootView != null && rootView instanceof CoordinatorLayout) {
final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) rootView;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
coordinatorLayout.setFitsSystemWindows(false);
contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
boolean isNeedRequestLayout = contentView.getPaddingTop() < statusBarHeight;
if (isNeedRequestLayout) {
contentView.setPadding(0, statusBarHeight, 0, 0);
coordinatorLayout.post(new Runnable() {
@Override
public void run() {
coordinatorLayout.requestLayout();
}
});
}
} else {
coordinatorLayout.setStatusBarBackgroundColor(calculateStatusColor(color, statusBarAlpha));
}
} else {
contentView.setPadding(0, statusBarHeight, 0, 0);
contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
}
setTransparentForWindow(activity);
}
}
/**
* 设置状态栏纯色 不加半透明效果
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
public static void setColorNoTranslucent(Activity activity, @ColorInt int color) {
setColor(activity, color, 0);
}
/**
* 设置状态栏纯色 不加半透明效果 字体为黑色
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
public static void setColorNoTranslucentLightMode(Activity activity, @ColorInt int color) {
setColor(activity, color, 0);
//setLightMode(activity);
}
/**
* 设置状态栏颜色(5.0以下无半透明效果,不建议使用)
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
*/
@Deprecated
public static void setColorDiff(Activity activity, @ColorInt int color) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
transparentStatusBar(activity);
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
// 移除半透明矩形,以免叠加
View fakeStatusBarView = contentView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(color);
} else {
contentView.addView(createStatusBarView(activity, color));
}
setRootView(activity);
}
/**
* 使状态栏半透明
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
*/
public static void setTranslucent(Activity activity) {
setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 使状态栏半透明
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
*/
public static void setTranslucent(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
setTransparent(activity);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 针对根布局是 CoordinatorLayout, 使状态栏半透明
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
*/
public static void setTranslucentForCoordinatorLayout(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
transparentStatusBar(activity);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 设置状态栏全透明
*
* @param activity 需要设置的activity
*/
public static void setTransparent(Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
transparentStatusBar(activity);
setRootView(activity);
}
/**
* 使状态栏透明(5.0以上半透明效果,不建议使用)
* <p>
* 适用于图片作为背景的界面,此时需要图片填充到状态栏
*
* @param activity 需要设置的activity
*/
@Deprecated
public static void setTranslucentDiff(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
setRootView(activity);
}
}
/**
* 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 为DrawerLayout 布局设置状态栏颜色,纯色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
setColorForDrawerLayout(activity, drawerLayout, color, 0);
}
/**
* 为DrawerLayout 布局设置状态栏颜色,纯色 字体为黑色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
public static void setColorNoTranslucentForDrawerLayoutLightMode(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
setColorForDrawerLayout(activity, drawerLayout, color, 0);
setLightMode(activity);
}
/**
* 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color,
@IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
// 生成一个状态栏大小的矩形
// 添加 statusBarView 到布局中
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(color);
} else {
contentLayout.addView(createStatusBarView(activity, color), 0);
}
// 内容布局不是 LinearLayout 时,设置padding top
if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1)
.setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),
contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 设置 DrawerLayout 属性
*
* @param drawerLayout DrawerLayout
* @param drawerLayoutContentLayout DrawerLayout 的内容布局
*/
private static void setDrawerLayoutProperty(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) {
ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
drawerLayout.setFitsSystemWindows(false);
drawerLayoutContentLayout.setFitsSystemWindows(false);
drawerLayoutContentLayout.setClipToPadding(true);
drawer.setFitsSystemWindows(false);
}
/**
* 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用)
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
*/
@Deprecated
public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 生成一个状态栏大小的矩形
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA));
} else {
// 添加 statusBarView 到布局中
contentLayout.addView(createStatusBarView(activity, color), 0);
}
// 内容布局不是 LinearLayout 时,设置padding top
if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout);
}
}
/**
* 为 DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA);
}
/**
* 为 DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout,
@IntRange(from = 0, to = 255) int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
setTransparentForDrawerLayout(activity, drawerLayout);
addTranslucentView(activity, statusBarAlpha);
}
/**
* 为 DrawerLayout 布局设置状态栏透明
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
// 内容布局不是 LinearLayout 时,设置padding top
if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
}
// 设置属性
setDrawerLayoutProperty(drawerLayout, contentLayout);
}
/**
* 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用)
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
*/
@Deprecated
public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置状态栏透明
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// 设置内容布局属性
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
contentLayout.setFitsSystemWindows(true);
contentLayout.setClipToPadding(true);
// 设置抽屉布局属性
ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);
vg.setFitsSystemWindows(false);
// 设置 DrawerLayout 属性
drawerLayout.setFitsSystemWindows(false);
}
}
/**
* 为头部是 ImageView 的界面设置状态栏全透明
*
* @param activity 需要设置的activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTransparentForImageView(Activity activity, View needOffsetView) {
setTranslucentForImageView(activity, 0, needOffsetView);
}
/**
* 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度)
*
* @param activity 需要设置的activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageView(Activity activity, View needOffsetView) {
setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
}
/**
* 为头部是 ImageView 的界面设置状态栏透明
*
* @param activity 需要设置的activity
* @param statusBarAlpha 状态栏透明度
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
View needOffsetView) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return;
}
setTransparentForWindow(activity);
addTranslucentView(activity, statusBarAlpha);
if (needOffsetView != null) {
Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET);
if (haveSetOffset != null && (Boolean) haveSetOffset) {
return;
}
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity),
layoutParams.rightMargin, layoutParams.bottomMargin);
needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true);
}
}
/**
* 为 fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) {
setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
}
/**
* 为 fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) {
setTranslucentForImageViewInFragment(activity, 0, needOffsetView);
}
/**
* 为 fragment 头部是 ImageView 的设置状态栏透明
*
* @param activity fragment 对应的 activity
* @param statusBarAlpha 状态栏透明度
* @param needOffsetView 需要向下偏移的 View
*/
public static void setTranslucentForImageViewInFragment(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
View needOffsetView) {
setTranslucentForImageView(activity, statusBarAlpha, needOffsetView);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
clearPreviousSetting(activity);
}
}
/**
* 隐藏伪状态栏 View
*
* @param activity 调用的 Activity
*/
public static void hideFakeStatusBarView(Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
fakeStatusBarView.setVisibility(View.GONE);
}
View fakeTranslucentView = decorView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);
if (fakeTranslucentView != null) {
fakeTranslucentView.setVisibility(View.GONE);
}
}
@TargetApi(Build.VERSION_CODES.M)
public static void setLightMode(Activity activity) {
setMIUIStatusBarDarkIcon(activity, true);
setMeizuStatusBarDarkIcon(activity, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
}
@TargetApi(Build.VERSION_CODES.M)
public static void setDarkMode(Activity activity) {
setMIUIStatusBarDarkIcon(activity, false);
setMeizuStatusBarDarkIcon(activity, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
}
/**
* 修改 MIUI V6 以上状态栏颜色
*/
private static void setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
Class<? extends Window> clazz = activity.getWindow().getClass();
try {
@SuppressLint("PrivateApi")
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
int darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(activity.getWindow(), darkIcon ? darkModeFlag : 0, darkModeFlag);
} catch (Exception e) {
//e.printStackTrace();
}
}
/**
* 修改魅族状态栏字体颜色 Flyme 4.0
*/
private static void setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
try {
WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (darkIcon) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
activity.getWindow().setAttributes(lp);
} catch (Exception e) {
//e.printStackTrace();
}
}
///
@TargetApi(Build.VERSION_CODES.KITKAT)
private static void clearPreviousSetting(Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
if (fakeStatusBarView != null) {
decorView.removeView(fakeStatusBarView);
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
rootView.setPadding(0, 0, 0, 0);
}
}
/**
* 添加半透明矩形条
*
* @param activity 需要设置的 activity
* @param statusBarAlpha 透明值
*/
private static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);
if (fakeTranslucentView != null) {
if (fakeTranslucentView.getVisibility() == View.GONE) {
fakeTranslucentView.setVisibility(View.VISIBLE);
}
fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
} else {
contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));
}
}
/**
* 生成一个和状态栏大小相同的彩色矩形条
*
* @param activity 需要设置的 activity
* @param color 状态栏颜色值
* @return 状态栏矩形条
*/
private static View createStatusBarView(Activity activity, @ColorInt int color) {
return createStatusBarView(activity, color, 0);
}
/**
* 生成一个和状态栏大小相同的半透明矩形条
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param alpha 透明值
* @return 状态栏矩形条
*/
private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) {
// 绘制一个和状态栏一样高的矩形
View statusBarView = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
return statusBarView;
}
/**
* 设置根布局参数
*/
private static void setRootView(Activity activity) {
ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);
for (int i = 0, count = parent.getChildCount(); i < count; i++) {
View childView = parent.getChildAt(i);
if (childView instanceof ViewGroup) {
childView.setFitsSystemWindows(true);
((ViewGroup) childView).setClipToPadding(true);
}
}
}
/**
* 设置透明
*/
private static void setTransparentForWindow(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
activity.getWindow()
.getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.getWindow()
.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* 使状态栏透明
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
private static void transparentStatusBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* 创建半透明矩形 View
*
* @param alpha 透明值
* @return 半透明 View
*/
private static View createTranslucentStatusBarView(Activity activity, int alpha) {
// 绘制一个和状态栏一样高的矩形
View statusBarView = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID);
return statusBarView;
}
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
public static int getStatusBarHeight(Context context) {
// 获得状态栏高度
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
/***
* 只能作用于activity
*/
public static void setTaskBarColored(Activity context, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window w = context.getWindow();
w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//status bar height
int statusBarHeight = getStatusBarHeight(context);
View view = new View(context);
view.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
view.getLayoutParams().height = statusBarHeight;
((ViewGroup) w.getDecorView()).addView(view);
//view.setBackgroundColor(context.getResources().getColor(R.color.colorPrimaryTaskBar));
view.setBackgroundColor(color);
}
}
/**
* 计算状态栏颜色
*
* @param color color值
* @param alpha alpha值
* @return 最终的状态栏颜色
*/
private static int calculateStatusColor(@ColorInt int color, int alpha) {
if (alpha == 0) {
return color;
}
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
/***
* Android设置背景图延伸到状态栏
* https://www.codenong.com/cs106491245/
* @param context
*/
public static void transparentStatusBarForImage(Activity context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.0 全透明实现
//getWindow.setStatusBarColor(Color.TRANSPARENT)
Window window = context.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//4.4 全透明状态栏
context.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
// 设置状态栏文字颜色为黑色
public static void setStatusBarLightMode(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = activity.getWindow().getDecorView();
int systemUiVisibility = decorView.getSystemUiVisibility();
decorView.setSystemUiVisibility(systemUiVisibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
// 设置状态栏文字颜色为白色
public static void setStatusBarDarkMode(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = activity.getWindow().getDecorView();
int systemUiVisibility = decorView.getSystemUiVisibility();
decorView.setSystemUiVisibility(systemUiVisibility & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
// 设置状态栏(纯)颜色
public static void setStatusBarColor(Activity activity, int colorResId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(colorResId));
}
}
public static void setStatusBarColor(Dialog dialog, int colorResId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = dialog.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(dialog.getContext().getResources().getColor(colorResId));
}
}
/***
* 设置dialog的状态栏的字体颜色
* @param dialog DialogFragment
*/
public static void setStatusBarLightMode(Dialog dialog) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = dialog.getWindow().getDecorView();
int systemUiVisibility = decorView.getSystemUiVisibility();
decorView.setSystemUiVisibility(systemUiVisibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
}
1.2 AndroidManifest.xml
<!--适配华为(huawei)刘海屏-->
<meta-data
android:name="android.notch_support"
android:value="true" />
<!--适配小米(xiaomi)刘海屏-->
<meta-data
android:name="notch.config"
android:value="portrait|landscape" />
<!-- 适配全面屏 -->
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
1.3 ids.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="statusbarutil_fake_status_bar_view" />
<item type="id" name="statusbarutil_translucent_view" />
</resources>
2.NotchScreenTool
第三方库
2.1 代码
// 支持显示到刘海区域
NotchScreenManager.getInstance().setDisplayInNotch(this);
// 获取刘海屏信息
NotchScreenManager.getInstance().getNotchInfo(this, new INotchScreen.NotchScreenCallback() {
@Override
public void onResult(INotchScreen.NotchScreenInfo notchScreenInfo) {
Log.i(TAG, "Is this screen notch? " + notchScreenInfo.hasNotch);
if (notchScreenInfo.hasNotch) {
for (Rect rect : notchScreenInfo.notchRects) {
Log.i(TAG, "notch screen Rect = " + rect.toShortString());
}
}
}
});
2.2 AndroidManifest.xml
在 <application>
标签中增加属性:android:resizeableActivity="false"
或者不设置
同时在节点下增加一个meta-data
标签:
<!-- Render on full screen up to screen aspect ratio of 2.4 -->
<!-- Use a letterbox on screens larger than 2.4 -->
<meta-data android:name="android.max_aspect" android:value="2.4" />
2.3 githup
3.ImmersionBar
第三方库
3.1 依赖
// 基础依赖包,必须要依赖
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.2'
// kotlin扩展(可选)
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.2'
// fragment快速实现(可选)已废弃
implementation 'com.geyifeng.immersionbar:immersionbar-components:3.2.2'
3.2 关于全面屏与刘海
关于全面屏
在manifest加入如下配置,四选其一,或者都写
① 升级targetSdkVersion为25以上版本,现在基本都是25以上了,所以以下三个没有必要配置了
② 在manifest的Application节点中加入
android:resizeableActivity="true"
③ 在manifest的Application节点中加入
android:maxAspectRatio="2.4"
④ 在manifest的Application节点下加入
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
关于刘海屏
在manifest的Application节点下加入,vivo和oppo没有找到相关配置信息
<!--适配华为(huawei)刘海屏-->
<meta-data
android:name="android.notch_support"
android:value="true"/>
<!--适配小米(xiaomi)刘海屏-->
<meta-data
android:name="notch.config"
android:value="portrait|landscape" />
3.3 Api详解
-
基础用法
ImmersionBar.with(this).init();
-
高级用法(每个参数的意义)
ImmersionBar.with(this) .transparentStatusBar() //透明状态栏,不写默认透明色 .transparentNavigationBar() //透明导航栏,不写默认黑色(设置此方法,fullScreen()方法自动为true) .transparentBar() //透明状态栏和导航栏,不写默认状态栏为透明色,导航栏为黑色(设置此方法,fullScreen()方法自动为true) .statusBarColor(R.color.colorPrimary) //状态栏颜色,不写默认透明色 .navigationBarColor(R.color.colorPrimary) //导航栏颜色,不写默认黑色 .barColor(R.color.colorPrimary) //同时自定义状态栏和导航栏颜色,不写默认状态栏为透明色,导航栏为黑色 .statusBarAlpha(0.3f) //状态栏透明度,不写默认0.0f .navigationBarAlpha(0.4f) //导航栏透明度,不写默认0.0F .barAlpha(0.3f) //状态栏和导航栏透明度,不写默认0.0f .statusBarDarkFont(true) //状态栏字体是深色,不写默认为亮色 .navigationBarDarkIcon(true) //导航栏图标是深色,不写默认为亮色 .autoDarkModeEnable(true) //自动状态栏字体和导航栏图标变色,必须指定状态栏颜色和导航栏颜色才可以自动变色哦 .autoStatusBarDarkModeEnable(true,0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦 .autoNavigationBarDarkModeEnable(true,0.2f) //自动导航栏图标变色,必须指定导航栏颜色才可以自动变色哦 .flymeOSStatusBarFontColor(R.color.btn3) //修改flyme OS状态栏字体颜色 .fullScreen(true) //有导航栏的情况下,activity全屏显示,也就是activity最下面被导航栏覆盖,不写默认非全屏 .hideBar(BarHide.FLAG_HIDE_BAR) //隐藏状态栏或导航栏或两者,不写默认不隐藏 .addViewSupportTransformColor(toolbar) //设置支持view变色,可以添加多个view,不指定颜色,默认和状态栏同色,还有两个重载方法 .titleBar(view) //解决状态栏和布局重叠问题,任选其一 .titleBarMarginTop(view) //解决状态栏和布局重叠问题,任选其一 .statusBarView(view) //解决状态栏和布局重叠问题,任选其一 .fitsSystemWindows(true) //解决状态栏和布局重叠问题,任选其一,默认为false,当为true时一定要指定statusBarColor(),不然状态栏为透明色,还有一些重载方法 .supportActionBar(true) //支持ActionBar使用 .statusBarColorTransform(R.color.orange) //状态栏变色后的颜色 .navigationBarColorTransform(R.color.orange) //导航栏变色后的颜色 .barColorTransform(R.color.orange) //状态栏和导航栏变色后的颜色 .removeSupportView(toolbar) //移除指定view支持 .removeSupportAllView() //移除全部view支持 .navigationBarEnable(true) //是否可以修改导航栏颜色,默认为true .navigationBarWithKitkatEnable(true) //是否可以修改安卓4.4和emui3.x手机导航栏颜色,默认为true .navigationBarWithEMUI3Enable(true) //是否可以修改emui3.x手机导航栏颜色,默认为true .keyboardEnable(true) //解决软键盘与底部输入框冲突问题,默认为false,还有一个重载方法,可以指定软键盘mode .keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) //单独指定软键盘模式 .setOnKeyboardListener(new OnKeyboardListener() { //软键盘监听回调,keyboardEnable为true才会回调此方法 @Override public void onKeyboardChange(boolean isPopup, int keyboardHeight) { LogUtils.e(isPopup); //isPopup为true,软键盘弹出,为false,软键盘关闭 } }) .setOnNavigationBarListener(onNavigationBarListener) //导航栏显示隐藏监听,目前只支持华为和小米手机 .setOnBarListener(OnBarListener) //第一次调用和横竖屏切换都会触发,可以用来做刘海屏遮挡布局控件的问题 .addTag("tag") //给以上设置的参数打标记 .getTag("tag") //根据tag获得沉浸式参数 .reset() //重置所以沉浸式参数 .init(); //必须调用方可应用以上所配置的参数
在Activity中实现沉浸式
-
java用法
ImmersionBar.with(this).init();
-
kotlin用法
immersionBar { statusBarColor(R.color.colorPrimary) navigationBarColor(R.color.colorPrimary) }
在Fragment中实现沉浸式
在Fragment使用ImmersionBar
- 第一种,fragment如果配合viewpager2使用的话,并且使用了Behavior指定了BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,直接在fragment的onResume里直接实现沉浸式
- 第二种,当使用show()和hide()来控制Fragment显示隐藏的时候,直接在fragment的onResume与onHiddenChanged(参数hidden为false)方法里实现沉浸式
第三种(废弃),你的Fragment直接继承SimpleImmersionFragment或者ImmersionFragment类,在initImmersionBar方法中实现沉浸式代码,只有当immersionBarEnabled返回为true才可以走initImmersionBar方法哦,不过immersionBarEnabled默认返回已经为true了,如果当前Fragment不想走沉浸式方法,请将immersionBarEnabled设置为false第四种(废弃),如果你的Fragment不能继承SimpleImmersionFragment或者ImmersionFragment类,请参考SimpleImmersionFragment实现SimpleImmersionOwner接口,或者参考ImmersionFragment实现ImmersionOwner接口
在Activity使用ImmersionBar
- 第一种,当结合viewpager2使用的时候,请使用viewpager2的registerOnPageChangeCallback的方法监听沉浸式
- 第二种,当结合viewpager使用的时候,请使用viewpager的addOnPageChangeListener的方法监听沉浸式,参考demo中FragmentThreeActivity这个类
- 第三种,当使用show()和hide()来控制Fragment显示隐藏的时候,请在tab切换的时候使用ImmersionBar,参考demo中FragmentFourActivity这个类
使用Fragment第三方框架Fragmentation实现沉浸式
- 参考demo中FragmentFiveActivity和BaseFiveFragment这个类
在Dialog中实现沉浸式,具体实现参考demo
-
①结合dialogFragment使用,可以参考demo中的BaseDialogFragment这个类
ImmersionBar.with(this).init();
-
②其他dialog,关闭dialog的时候必须调用销毁方法
ImmersionBar.with(this, dialog).init();
销毁方法:
java中
ImmersionBar.destroy(this, dialog);
kotlin中
destroyImmersionBar(dialog)
在PopupWindow中实现沉浸式,具体实现参考demo
重点是调用以下方法,但是此方法会导致有导航栏的手机底部布局会被导航栏覆盖,还有底部输入框无法根据软键盘弹出而弹出,具体适配请参考demo。
popupWindow.setClippingEnabled(false);
状态栏与布局顶部重叠解决方案,六种方案根据不同需求任选其一
-
① 使用dimen自定义状态栏高度,不建议使用,因为设备状态栏高度并不是固定的
在values-v19/dimens.xml文件下
<dimen name="status_bar_height">25dp</dimen>
在values/dimens.xml文件下
<dimen name="status_bar_height">0dp</dimen>
然后在布局界面添加view标签,高度指定为status_bar_height
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/darker_gray" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="@dimen/status_bar_height" android:background="@color/colorPrimary" /> <android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:title="方法一" app:titleTextColor="@android:color/white" /> </LinearLayout>
-
② 使用系统的fitsSystemWindows属性,使用该属性不会导致输入框与软键盘冲突问题,不要再Fragment使用该属性,只适合纯色状态栏
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:fitsSystemWindows="true"> </LinearLayout>
然后使用ImmersionBar时候必须指定状态栏颜色
ImmersionBar.with(this) .statusBarColor(R.color.colorPrimary) .init();
- 注意:ImmersionBar一定要在设置完布局以后使用,
-
③ 使用ImmersionBar的fitsSystemWindows(boolean fits)方法,只适合纯色状态栏
ImmersionBar.with(this) .fitsSystemWindows(true) //使用该属性,必须指定状态栏颜色 .statusBarColor(R.color.colorPrimary) .init();
-
④ 使用ImmersionBar的statusBarView(View view)方法,可以用来适配渐变色状态栏、侧滑返回
在标题栏的上方增加View标签,高度指定为0dp
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/darker_gray" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="0dp" android:background="@color/colorPrimary" /> <android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:title="方法四" app:titleTextColor="@android:color/white" /> </LinearLayout>
然后使用ImmersionBar的statusBarView方法,指定view就可以啦
ImmersionBar.with(this) .statusBarView(view) .init(); //或者 //ImmersionBar.setStatusBarView(this,view);
-
⑤ 使用ImmersionBar的titleBar(View view)方法,原理是设置paddingTop,可以用来适配渐变色状态栏、侧滑返回
ImmersionBar.with(this) .titleBar(view) //可以为任意view,如果是自定义xml实现标题栏的话,标题栏根节点不能为RelativeLayout或者ConstraintLayout,以及其子类 .init(); //或者 //ImmersionBar.setTitleBar(this, view);
-
⑥ 使用ImmersionBar的titleBarMarginTop(View view)方法,原理是设置marginTop,只适合纯色状态栏
ImmersionBar.with(this) .titleBarMarginTop(view) //可以为任意view .statusBarColor(R.color.colorPrimary) //指定状态栏颜色,根据情况是否设置 .init(); //或者使用静态方法设置 //ImmersionBar.setTitleBarMarginTop(this,view);
解决EditText和软键盘的问题
-
第一种方案
ImmersionBar.with(this) .keyboardEnable(true) //解决软键盘与底部输入框冲突问题 // .keyboardEnable(true, WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE // | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) //软键盘自动弹出 .init();
-
第二种方案 不使用keyboardEnable方法,只需要在布局的根节点(最外层节点)加上android:fitsSystemWindows="true"属性即可,只适合纯色状态栏
当白色背景状态栏遇到不能改变状态栏字体为深色的设备时,解决方案
ImmersionBar.with(this)
.statusBarDarkFont(true, 0.2f) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.init();
状态栏和导航栏其它方法
-
public static boolean hasNavigationBar(Activity activity)
判断是否存在导航栏
-
public static int getNavigationBarHeight(Activity activity)
获得导航栏的高度
-
public static int getNavigationBarWidth(Activity activity)
获得导航栏的宽度
-
public static boolean isNavigationAtBottom(Activity activity)
判断导航栏是否在底部
-
public static int getStatusBarHeight(Activity activity)
获得状态栏的高度
-
public static int getActionBarHeight(Activity activity)
获得ActionBar的高度
-
public static boolean hasNotchScreen(Activity activity)
是否是刘海屏
-
public static boolean getNotchHeight(Activity activity)
获得刘海屏高度
-
public static boolean isSupportStatusBarDarkFont()
判断当前设备支不支持状态栏字体设置为黑色
-
public static boolean isSupportNavigationIconDark()
判断当前设备支不支持导航栏图标设置为黑色
-
public static void hideStatusBar(Window window)
隐藏状态栏
4.EdgeUtils
EdgeUtils:安卓沉浸式方案(edge to edge)封装
原文地址:https://blog.csdn.net/fromVillageCoolBoy/article/details/137922998
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!