【问题标题】:Determine whether hardware buttons are drawn on screen in React Native在 React Native 中判断是否在屏幕上绘制硬件按钮
【发布时间】:2017-11-24 08:44:29
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: android react-native


    【解决方案1】:

    appears to be easy 使用 Java 来确定 Android 设备是否具有物理按钮,因此要在 React Native 中访问它,我将创建一个 Native Module 包装器以返回 ViewConfiguration.get(context).hasPermanentMenuKey() 的结果。

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

    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 并包含以下内容:

    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 代码可以访问它:

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

    现在在您的 React Native 组件中,确保您从 react-nativePlatform 导入 NativeModules,以便您仅在 Android 上运行该函数。在componentDidMount

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

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

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

    【讨论】:

    • 谢谢,这很好!
    • MainApplication.java中不需要导入new DetectHardwarePackage()吗?
    • 我有错误 --> 错误:找不到符号 => callback.invoke(ViewConfiguration.get(getReactApplicationContext()).hasPermanentMenuKey());
    【解决方案2】:

    我使用 RN Dimensions 来做到这一点:

    import {Dimensions} from 'react-native';
    
    let deviceHeight = Dimensions.get('screen').height;
    let windowHeight = Dimensions.get('window').height;
    let bottomNavBarHeight = deviceHeight - windowHeight;
    if (bottomNavBarHeight > 0) {
        // onscreen navbar
    } else {
        // not onscreen navbar
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-20
      • 2020-05-15
      相关资源
      最近更新 更多