确定是否在 React Native 中在屏幕上绘制硬件按钮 [英] Determine whether hardware buttons are drawn on screen in React Native

查看:31
本文介绍了确定是否在 React Native 中在屏幕上绘制硬件按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 React Native 应用程序 (RN 0.42) 的 bottom: 0 处绘制了一个按钮.这在 iOS 和大多数 Android 设备上运行良好.但在没有物理硬件按钮的 Android 设备上,按钮栏会绘制在我按钮正上方的屏幕上.

I draw a button at bottom: 0 in my React Native app (RN 0.42). This works pretty well on iOS and the most Android devices. But on Android devices with no physical hardware buttons, the button bar is drawn on the screen right above my button.

那么:在这种情况下,有没有办法检测硬件按钮是物理驱动还是软件驱动来调整我的布局?或者这只是 React Native 中的一个错误,因为这只发生在模态对话框中?

So: Is there a way to detect whether the hardware buttons are physical or software driven to adjust my layout in this case? Or is this just a bug in React Native since this only happens in modal dialogs?

Nexus(绿色按钮的样式为:bottom: 45,硬件按钮呈现在屏幕上):

Nexus (the green button has the style: bottom: 45 and the hardware buttons are rendered on the screen):

Galaxy S5:(这个设备有真正的硬件按钮,所以bottom: 45太多了):

Galaxy S5: (this device has real hardware buttons, so the bottom: 45 is too much):

推荐答案

似乎很容易使用 Java 来确定Android 设备是否有物理按钮,因此要在 React Native 中访问它,我会创建一个 Native Module 包装器,用于返回 ViewConfiguration.get(context).hasPermanentMenuKey() 的结果.

It appears to be easy using Java to determine whether an Android device has a physical button, so to access that in React Native I would make a Native Module wrapper to return the result of ViewConfiguration.get(context).hasPermanentMenuKey().

您可以在 Android Studio 中打开 React Native 项目的 /android 目录,然后在 /app/src/main/java// 文件夹,在您看到 MainActivityMainApplication 文件的同一级别,创建一个名为 detecthardware(或任何其他合适的名称).在其中创建 DetectHardwareModule.java 并包含以下内容:

You can open the /android directory of your React Native project in Android Studio, then within the /app/src/main/java/<com.companyname.appname>/ folder, at the same level where you see MainActivity and MainApplication files, create a new Android resource directory called detecthardware (or any other appropriate name). Within that create DetectHardwareModule.java and include this:

package com.companyname.appname.detecthardware;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactMethod;

import java.util.List;

public class DetectHardwareModule extends ReactContextBaseJavaModule {

    public DetectHardwareModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "DetectHardware";
    }

    @ReactMethod
    public void hasHardwareButtons(final Callback callback) {
        callback.invoke(ViewConfiguration.get(getReactApplicationContext()).hasPermanentMenuKey());
    }
}

然后创建 DetectHardwarePackage.java 并包含这个:

Then create DetectHardwarePackage.java and include this:

package com.companyname.appname.detecthardware;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
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 DetectHardwarePackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new DetectHardwareModule(reactContext));
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

在 MainApplication.java 中,您需要包含一个 getPackages方法,以便 JavaScript 代码可以访问它:

Inside your MainApplication.java you'll need to include a getPackages method so the JavaScript code can access it:

@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new DetectHardwarePackage()
    );
}

现在在你的 React Native 组件中,确保你从 react-nativePlatform 导入 NativeModules 以便你只运行在 Android 上时的功能.在 componentDidMount 中:

Now within your React Native component, make sure you import NativeModules from react-native, as well as Platform so that you only run the function when on Android. In componentDidMount:

componentDidMount() {
    if (Platform.OS === 'android') {
        NativeModules.DetectHardware.hasHardwareButtons(function(result) {
            this.setState({hasHardwareButtons: result})
        }.bind(this));
    }
}

最后在您的 render 函数中,如果平台是 android 并且 hasHardwareButtons 为真,则计算 bottom 数量为 0,否则为 45:

And finally within your render function, calculate the bottom amount to be 0 if the platform is android and hasHardwareButtons is true, otherwise 45:

var bottom = (Platform.OS === 'android' && this.state.hasHardwareButtons) ? 0 : 45

这篇关于确定是否在 React Native 中在屏幕上绘制硬件按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆