我在我的React Native应用程序(RN 0.42)中的bottom: 0
处绘制了一个按钮。这在iOS和大多数Android设备上运行良好。但是在没有物理硬件按钮的Android设备上,按钮栏会在我按钮上方的屏幕上绘制。
所以:在这种情况下,有没有办法检测硬件按钮是物理的还是软件驱动的,以调整我的布局?或者这只是React Native中的一个错误,因为这只发生在模态对话框中?
答案 0 :(得分:5)
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>/
文件夹中,在您看到MainActivity
和MainApplication
的同一级别文件,创建一个名为detecthardware
的新Android资源目录(或任何其他适当的名称)。在其中创建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组件中,请确保从NativeModules
以及react-native
导入Platform
,以便您只在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
答案 1 :(得分: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
}