react native 安卓(特别是小米手机)全面屏是否开虚拟按键的适配
Posted 春春小姐姐做前端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react native 安卓(特别是小米手机)全面屏是否开虚拟按键的适配相关的知识,希望对你有一定的参考价值。
react native 安卓(特别是小米手机)全面屏是否开虚拟按键的适配
做rn蛮久了,遇到的坑无数,谢谢大家带我爬过的坑,这次我也来分享一下,希望帮助到有需要的人!
大家先看先后效果对比:
没开虚拟按键的时候完美:
开了虚拟按键之后,显示不全了:
处理之后的效果:
产生的原因:
andorid全面屏幕中 Dimensions.get(‘window’).height 计算屏幕高度时会自动减少StatusBar 的高度
解决方案:
const { width,height } = Dimensions.get('window');
let deviceHeight = height/width > 1.8 ? height+ NativeModules.StatusBarManager.HEIGHT: height;
然后将deviceHeight设成我们的内容高度就行了!
到这里我以为完美解决了哈哈,其实还有另一个大坑等着呢!
测试了几乎所有主流机型,基本都没问题很完美,唯独小米手机,真的是坑啊!
这时候小米全面屏手机开启虚拟按键的状态是对的,可是没开按键的时候下面没有铺满,缺了一大截,其原因就是它不管开不开按键它的height/width 都大于 1.8 ,因为它的Dimensions.get(‘window’).height不随开不开按键而变化,始终是那个那么高,所以根本无法用这个比例来判断了!
查阅很多资料,rn不好解决了,只能用调用原生方法试试了,结果终于完美解决,步骤我也给大家贴出来:
1.在com.xx.xx创建包名milletAdaptation;
编写 Module,在milletAdaptation包下创建MilletAdaptation.java,代码如下:
package com.项目工程名.milletAdaptation;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import com.facebook.react.ReactApplication;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.swordsmanapp.MainActivity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import java.lang.reflect.Method;
public class MilletAdaptation extends ReactContextBaseJavaModule{
DisplayMetrics metrics = new DisplayMetrics();
public MilletAdaptation(ReactApplicationContext reactContext) {
super(reactContext);
}
@NonNull
@Override
public String getName() {
return "MilletAdaptation";
}
@ReactMethod
public void getHeight(final Promise promise) {
int height = metrics.heightPixels;
Activity activty = MainActivity.getActivity();
if (isXiaoMi(getReactApplicationContext())) {
height += getNavigationBarHeight(activty);
}else {
height=0 ;
}
promise.resolve(height);
}
/**
* 获取底部虚拟按键高度
* @param context
* @return
*/
public static int getNavigationBarHeight(Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
try {
@SuppressWarnings("rawtypes")
Class c = Class.forName("android.view.Display");
@SuppressWarnings("unchecked")
Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
method.invoke(display, dm);
return dm.heightPixels - display.getHeight();
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* 判断是否是小米手机 并且是否开启全面屏
*
* @return
*/
public static boolean isXiaoMi(Context context) {
if (Build.MANUFACTURER.equals("Xiaomi")) {
return Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0) != 0;
}
return false;
}
@Override
public void initialize() {
MainActivity.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
}
@Override
public boolean canOverrideExistingModule() {
return false;
}
@Override
public void onCatalystInstanceDestroy() {
}
}
2.编写 Package,在milletAdaptation包下创建MilletAdaptationPackage.java,代码如下:
package com.项目工程名.milletAdaptation;
import com.swordsmanapp.milletAdaptation.MilletAdaptation;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MilletAdaptationPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new MilletAdaptation(reactContext));
return modules;
}
}
3.最后在 Android 这边要做的最后一件事就是注册这个模块,在MainApplication中注册模块:
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
packages.add(new AlipayReactPackage());
packages.add(new MilletAdaptationPackage()); // <-- 注册模块
return packages;
原生这部分就完成了,在rn端调用:
import {PixelRatio,NativeModules} from 'react-native';
componentDidMount() {
NativeModules.MilletAdaptation.getHeight()
.then((height) => {
// console.log('height:',height);
if(height){
this.setState({
deviceHeight:height/PixelRatio.get() //当是小米手机并且是全面屏没开按键的情况使用这个高度
})
}
})
.catch((err) => {
console.log('err:', err);
});
}
这下是真的完美解决咯,大家如果也遇到这样的困扰,希望可以帮到你们哦~
步骤写得很清楚,如果有不懂的可以留言,如果觉得有帮助记得给小姐姐点赞哈💗
以上是关于react native 安卓(特别是小米手机)全面屏是否开虚拟按键的适配的主要内容,如果未能解决你的问题,请参考以下文章
react native 安卓(特别是小米手机)全面屏是否开虚拟按键的适配