Android 顶部导航栏适配
程序员文章站
2022-03-13 19:53:17
背景自定义TitleLayoutpackage com.bjx.bjxcommon.view;import android.content.Context;import android.util.AttributeSet;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.constraintlayout.widget.ConstraintLayout.....
背景
自定义TitleLayout
package com.bjx.bjxcommon.view;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.bjx.bjxcommon.utils.ViewUtils;
public class TitleLayout extends ConstraintLayout {
public TitleLayout(@NonNull Context context) {
this(context, null);
}
public TitleLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TitleLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setPadding(0, ViewUtils.getStatusBarHeight(getContext()), 0, 0);
}
}
ViewUtils
package com.bjx.bjxcommon.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.provider.Settings;
import androidx.recyclerview.widget.RecyclerView;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.TextView;
import com.bjx.bjxcommon.CommonApp;
import java.lang.reflect.Method;
/**
* 文 件 名:
* 功 能:
* 作 者:liming
* 时 间:2017/8/22
**/
public class ViewUtils {
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
public static int getStatusBarHeight(Context context) {
int statusBarHeight = 0;
try {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
} catch (Exception e) {
e.printStackTrace();
if (isAllScreenDevice(context)) {
statusBarHeight = 80;
} else {
statusBarHeight = 63;
}
}
return statusBarHeight;
}
/**
* 转换dip为px
* * @param context
*
* @param dip
* @return
*/
public static int dp2px(Context context, int dip) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
}
/**
* //转换px为dip
*
* @param context
* @param px
* @return
*/
public static int px2dp(Context context, int px) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (px / scale + 0.5f * (px >= 0 ? 1 : -1));
}
/**
* 转换sp为PX
*
* @param context
* @param spValue
* @return
*/
public static int sp2px(Context context, float spValue) {
float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 转换sp为PX
*
* @param context
* @param pxValue
* @return
*/
public static int px2sp(Context context, float pxValue) {
float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 获取屏幕的宽度
*/
public static int getWindowsWidth(Activity activity) {
if (activity == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
/**
* 获取屏幕的高度
*/
public static int getWindowsHeight(Activity activity) {
if (activity == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
public static boolean isSlideToBottom(RecyclerView recyclerView) {
if (recyclerView == null) return false;
if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())
return true;
return false;
}
/**
* @param tv
* @param drawableId
*/
public static void setDrawableLeft(TextView tv, int drawableId) {
if (drawableId == 0) {
return;
}
Drawable drawable = CommonApp.getContext().getResources().getDrawable(drawableId);
// 这一步必须要做,否则不会显示.
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
tv.setCompoundDrawables(drawable, null, null, null);
}
/**
* @param tv
* @param drawableId
*/
public static void setDrawableRight(TextView tv, int drawableId) {
if (drawableId == 0) {
tv.setCompoundDrawables(null, null, null, null);
return;
}
Drawable drawable = CommonApp.getContext().getResources().getDrawable(drawableId);
// 这一步必须要做,否则不会显示.
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
tv.setCompoundDrawables(null, null, drawable, null);
}
/**
* @param tv
* @param drawableId
*/
public static void setDrawableBottom(TextView tv, int drawableId) {
if (drawableId == 0) {
return;
}
Drawable drawable = CommonApp.getContext().getResources().getDrawable(drawableId);
// 这一步必须要做,否则不会显示.
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
tv.setCompoundDrawables(null, null, null, drawable);
}
/**
* @param tv
* @param drawableId
*/
public static void setDrawableTop(TextView tv, int drawableId) {
if (drawableId == 0) {
return;
}
Drawable drawable = CommonApp.getContext().getResources().getDrawable(drawableId);
// 这一步必须要做,否则不会显示.
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
tv.setCompoundDrawables(null, drawable, null, null);
}
private volatile static boolean mHasCheckAllScreen;
private volatile static boolean mIsAllScreenDevice;
//判断是否为全面屏
public static boolean isAllScreenDevice(Context context) {
if (mHasCheckAllScreen) {
return mIsAllScreenDevice;
}
mHasCheckAllScreen = true;
mIsAllScreenDevice = false;
// 低于 API 21的,都不会是全面屏。。。
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false;
}
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (windowManager != null) {
Display display = windowManager.getDefaultDisplay();
Point point = new Point();
display.getRealSize(point);
float width, height;
if (point.x < point.y) {
width = point.x;
height = point.y;
} else {
width = point.y;
height = point.x;
}
if (height / width >= 1.97f) {
mIsAllScreenDevice = true;
}
}
return mIsAllScreenDevice;
}
/**
* 根据百分比改变颜色透明度
*
* @param color 要改变的颜色值
* @param fraction 透明度
* @return
*/
public static int changeAlpha(int color, float fraction) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
int alpha = (int) (Color.alpha(color) * fraction);
return Color.argb(alpha, red, green, blue);
}
public static void setWidthHeightWithRatio(View view, int width, int widthRatio, int heightRatio) {
if (width <= 0) width = view.getWidth();
int height = width * heightRatio / widthRatio;
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams != null) {
layoutParams.height = height;
layoutParams.width = width;
view.setLayoutParams(layoutParams);
}
}
public static void setRatio2(View view, int width, int widthRatio, int heightRatio) {
if (width <= 0) width = view.getWidth();
int height = width * heightRatio / widthRatio;
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams != null) {
layoutParams.height = (int) (height * 1.0f / 2);
layoutParams.width = (int) (width * 1.0f / 2);
view.setLayoutParams(layoutParams);
}
}
/**
* 获取是否有虚拟按键
* 通过判断是否有物理返回键反向判断是否有虚拟按键
*
* @param context
* @return
*/
public static boolean checkDeviceHasNavigationBar(Context context) {
boolean hasMenuKey = ViewConfiguration.get(context)
.hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap
.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (!hasMenuKey & !hasBackKey) {
// 做任何你需要做的,这个设备有一个导航栏
return true;
}
return false;
}
//获取虚拟按键的高度
public static int getNavigationBarHeight(Context context) {
int result = 0;
if (checkDeviceHasNavigationBar(context)) {
Resources res = context.getResources();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
}
return result;
}
public boolean isNavigationBarShow(Activity activity) {
if (activity == null) {
return false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Display display = activity.getWindowManager().getDefaultDisplay();
Point size = new Point();
Point realSize = new Point();
display.getSize(size);
display.getRealSize(realSize);
boolean result = realSize.y != size.y;
return realSize.y != size.y;
} else {
boolean menu = ViewConfiguration.get(activity).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (menu || back) {
return false;
} else {
return true;
}
}
}
/**
* @param context
* @return 返回true表示显示虚拟导航键、false表示隐藏虚拟导航键
*/
public static boolean hasNavigationBar(Context context) {
//navigationGestureEnabled()从设置中取不到值的话,返回false,因此也不会影响在其他手机上的判断
return deviceHasNavigationBar() && !navigationGestureEnabled(context);
}
/**
* 获取主流手机设置中的"navigation_gesture_on"值,判断当前系统是使用导航键还是手势导航操作
*
* @param context app Context
* @return false 表示使用的是虚拟导航键(NavigationBar),
* true 表示使用的是手势, 默认是false
*/
private static boolean navigationGestureEnabled(Context context) {
int val = Settings.Global.getInt(context.getContentResolver(), getDeviceInfo(), 0);
return val != 0;
}
/**
* 获取设备信息(目前支持几大主流的全面屏手机,亲测华为、小米、oppo、魅族、vivo、三星都可以)
*
* @return
*/
private static String getDeviceInfo() {
String brand = Build.BRAND;
if (TextUtils.isEmpty(brand)) return "navigationbar_is_min";
if (brand.equalsIgnoreCase("HUAWEI") || "HONOR".equals(brand)) {
return "navigationbar_is_min";
} else if (brand.equalsIgnoreCase("XIAOMI")) {
return "force_fsg_nav_bar";
} else if (brand.equalsIgnoreCase("VIVO")) {
return "navigation_gesture_on";
} else if (brand.equalsIgnoreCase("OPPO")) {
return "navigation_gesture_on";
} else if (brand.equalsIgnoreCase("samsung")) {
return "navigationbar_hide_bar_enabled";
} else {
return "navigationbar_is_min";
}
}
/**
* 判断设备是否存在NavigationBar
*
* @return true 存在, false 不存在
*/
public static boolean deviceHasNavigationBar() {
boolean haveNav = false;
try {
//1.通过WindowManagerGlobal获取windowManagerService
// 反射方法:IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService();
Class<?> windowManagerGlobalClass = Class.forName("android.view.WindowManagerGlobal");
Method getWmServiceMethod = windowManagerGlobalClass.getDeclaredMethod("getWindowManagerService");
getWmServiceMethod.setAccessible(true);
//getWindowManagerService是静态方法,所以invoke null
Object iWindowManager = getWmServiceMethod.invoke(null);
//2.获取windowMangerService的hasNavigationBar方法返回值
// 反射方法:haveNav = windowManagerService.hasNavigationBar();
Class<?> iWindowManagerClass = iWindowManager.getClass();
Method hasNavBarMethod = iWindowManagerClass.getDeclaredMethod("hasNavigationBar");
hasNavBarMethod.setAccessible(true);
haveNav = (Boolean) hasNavBarMethod.invoke(iWindowManager);
} catch (Exception e) {
e.printStackTrace();
}
return haveNav;
}
public static void postDelayed500(View view, Runnable runnable) {
if (view == null || runnable == null) return;
view.postDelayed(runnable, 500);
}
public static void postDelayed300(View view, Runnable runnable) {
if (view == null || runnable == null) return;
view.postDelayed(runnable, 300);
}
public static void postDelayed2000(View view, Runnable runnable) {
if (view == null || runnable == null) return;
view.postDelayed(runnable, 2000);
}
public static void postDelayed(View view, Runnable runnable, long delayMillis) {
if (view == null || runnable == null) return;
view.postDelayed(runnable, delayMillis);
}
}
使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<com.bjx.bjxcommon.view.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.bjx.bjxcommon.view.TitleLayout>
</LinearLayout>
这样就可以了,不管是挖孔屏还是凹凸屏,还是以前的都是可以适配的
本文地址:https://blog.csdn.net/houdada_/article/details/112522366