(关于这个问题)
我想在React Native中创建一个组件,该组件具有与本机WebView完全相同的功能,只是覆盖了其一些方法。
我遵循了本机页面中的教程,带有模块和UI视图(我认为这是正确的方法),但我无法获得我想要的东西。
我能做的:
// .../com/project/permissionwebview/
public class PermissionWebviewView extends LinearLayout{
private Context context;
public PermissionWebviewView(Context context) {
super(context);
this.context = context;
init();
}
public void init() {
inflate(this.context, R.layout.permissionwebview, this);
}
}
和我的视图经理:
// .../com/project/permissionwebview
public class PermissionWebviewViewManager extends SimpleViewManager<PermissionWebviewView> {
public static final String REACT_CLASS = "PermissionWebviewViewManager";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public PermissionWebviewView createViewInstance(ThemedReactContext context) {
return new PermissionWebviewView(context); //If your customview has more constructor parameters pass it from here.
}
}
布局的XML:
// .../res/layout/permissionwebview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<WebView android:id="@+id/permission_webview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
我能够从React Antial称其为单位,但是什么也没有显示,什么也不会发生。
我想要的只是一个自定义元素,它称为本机一个(在这种情况下为 WebView
),因此它呈现完全相同(相同的道具,相同的方法),在必要时仅覆盖其某些方法(在我的情况下,,onPermissionRequest()
)。
哪种方法是正确的方法?我如何(在哪里)调用父级/超级WebView?
编辑1
我认为我已经运行了,但是我不知道它是否是正确的方法,因为我仍然不知道如何传递所有参数反应本机组件(<PermissionWebview />
)到本机WebView
元素:
// .../com/project/permissionwebview/
public class PermissionWebviewView extends LinearLayout{
private Context context;
private WebView myWebView;
public PermissionWebviewView(Context context) {
super(context);
this.context = context;
init();
}
public void init() {
inflate(this.context, R.layout.permissionwebview, this);
myWebView = (WebView)findViewById(R.id.permission_webview);
myWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(final PermissionRequest request) {
request.grant(request.getResources());
}
});
myWebView.loadUrl("https://staticWebSite.Until/Parameters/Are/Passed");
}
}
谢谢!
我能够最终通过在github上的react-native-website repo中从Android上使用的扩展WebView
来工作。此代码中有很多来自链接上的示例以及WebView
的实际反应本机实现。
我计划提交一个带有一些更改的拉动请求,以便为了实际构建Java,还可以检索我包装的实际WebView
所需的参考(并非每个人都需要此)。
请注意,某些类是嵌套的,而名称需要比GitHub的示例中的进一步资格:
:这是我要做的。就我而言,我需要将应用程序缓存清单功能添加到WebView
。您可能不需要所有这些导入语句,并且可能需要添加其他信息:
customwebviewmanager.java:
import android.os.Build;
import android.view.ViewGroup.LayoutParams;
import android.webkit.ConsoleMessage;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import android.webkit.CookieManager;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.views.webview.WebViewConfig;
import com.facebook.react.views.webview.ReactWebViewManager;
@ReactModule(name = CustomWebViewManager.REACT_CLASS)
public class CustomWebViewManager extends ReactWebViewManager {
protected static final String REACT_CLASS = "MyCustomWebView";
protected static class CustomReactWebViewClient extends ReactWebViewManager.ReactWebViewClient { }
protected static class CustomReactWebView extends ReactWebViewManager.ReactWebView {
public CustomReactWebView(ThemedReactContext reactContext) {
super(reactContext);
}
}
public CustomWebViewManager() {
mWebViewConfig = new WebViewConfig() {
public void configWebView(WebView webView) {
}
};
}
public CustomWebViewManager(WebViewConfig webViewConfig) {
mWebViewConfig = webViewConfig;
}
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected ReactWebView createReactWebViewInstance(ThemedReactContext reactContext) {
return new CustomReactWebView(reactContext);
}
// I had to override this in order to enable my needed WebView functionality
@Override
protected WebView createViewInstance(ThemedReactContext reactContext) {
ReactWebView webView = createReactWebViewInstance(reactContext);
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage message) {
if (ReactBuildConfig.DEBUG) {
return super.onConsoleMessage(message);
}
// Ignore console logs in non debug builds.
return true;
}
@Override
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
});
reactContext.addLifecycleEventListener(webView);
mWebViewConfig.configWebView(webView);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(false);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAppCacheMaxSize(1024*1024*8);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setAppCacheEnabled(true);
// not sure if the below is needed, but at least one post indicated that it was so I did this with my package name to be safe
webView.getSettings().setAppCachePath("data/data/<your package name here>/cache");
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webView.getSettings().setAllowFileAccessFromFileURLs(true);
// Fixes broken full-screen modals/galleries due to body height being 0.
webView.setLayoutParams(
new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
if (ReactBuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
return webView;
}
@Override
protected void addEventEmitters(ThemedReactContext reactContext, WebView view) {
// Do not register default touch emitter and let WebView implementation handle touches
view.setWebViewClient(new CustomReactWebViewClient());
}
}
customwebviewpackage.java
import java.util.Arrays;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
public class CustomWebViewPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new CustomWebViewManager());
}
}
customwebview.jsx
'use strict';
import * as PropTypes from 'prop-types';
import * as React from 'react';
import {
requireNativeComponent,
WebView
} from 'react-native';
/**
* Renders a native WebView via our custom wrapper.
* Necessary because the RN WebView does not turn on the App Cache functionality by default.
* Can't make this a .tsx file due to TS problems around spreading the this.props into the child WebView.
*/
class CustomWebView extends React.Component {
static propTypes = WebView.propTypes;
render() {
return (
<WebView
{...this.props}
ref={(view) => {
this.props.wrappedRef(view);
}}
nativeConfig={{component: MyCustomWebView}}
/>
);
}
}
const MyCustomWebView = requireNativeComponent('MyCustomWebView', CustomWebView,
WebView.extraNativeComponentConfig);
export default CustomWebView;
注意wrappedRef
属性。我添加了这一点,因为我的CustomWebView
的消费者需要对实际渲染的WebView
进行引用。这是由于它需要在那里参考功能,例如postMessage()
。消费者通过箭头功能,该功能设置了对消费类中属性的引用。如您所见,该功能在传递给ref
的内容中被调用。