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);
            });
    }

这下是真的完美解决咯,大家如果也遇到这样的困扰,希望可以帮到你们哦~
步骤写得很清楚,如果有不懂的可以留言,如果觉得有帮助记得给小姐姐点赞哈💗

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值