我创建了一个CustomView SignatureView.java,它扩展了LinearLayout以捕获Android Native中的签名。
并创建了SignatureCapturePackage.java和SignatureCaptureViewManager.java
public class SignatureCaptureMainView extends LinearLayout {
....
public void saveImage(){
//Save image to file
}
}
这是Package类
public class SignatureCapturePackage implements ReactPackage {
private Activity mCurrentActivity;
public RSSignatureCapturePackage(Activity activity) {
mCurrentActivity = activity;
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
return Arrays.<ViewManager>asList(new SignatureCaptureViewManager(mCurrentActivity));
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Arrays.asList();
}
}
这是ViewManager类
public class SignatureCaptureViewManager extends ViewGroupManager<SignatureCaptureMainView> {
private Activity mCurrentActivity;
public static final String PROPS_SAVE_IMAGE_FILE="saveImageFileInExtStorage";
public static final String PROPS_VIEW_MODE = "viewMode";
public RSSignatureCaptureViewManager(Activity activity) {
mCurrentActivity = activity;
}
@Override
public String getName() {
return "SignatureView";
}
@ReactProp(name = PROPS_SAVE_IMAGE_FILE)
public void setSaveImageFileInExtStorage(SignatureCaptureMainView view, @Nullable Boolean saveFile) {
Log.d("React View manager setSaveFileInExtStorage:", "" + saveFile);
if(view!=null){
view.setSaveFileInExtStorage(saveFile);
}
}
@ReactProp(name = PROPS_VIEW_MODE)
public void setViewMode(SignatureCaptureMainView view, @Nullable String viewMode) {
Log.d("React View manager setViewMode:", "" + viewMode);
if(view!=null){
view.setViewMode(viewMode);
}
}
@Override
public SignatureCaptureMainView createViewInstance(ThemedReactContext context) {
Log.d("React"," View manager createViewInstance:");
return new SignatureCaptureMainView(context, mCurrentActivity);
}
}
这是Signature.js包
var React = require('react-native');
var {
PropTypes,
requireNativeComponent,
View,
} = React;
class SignatureCapture extends React.Component {
constructor() {
super();
this.onChange = this.onChange.bind(this);
}
onChange(event) {
console.log("Signature ON Change Event");
if (!this.props.onSaveEvent) {
return;
}
this.props.onSaveEvent({
pathName: event.nativeEvent.pathName,
encoded: event.nativeEvent.encoded,
});
}
render() {
return (
<SignatureView {...this.props} style={{flex: 1}} onChange={this.onChange} />
);
}
save(){
}
}
SignatureCapture.propTypes = {
...View.propTypes,
saveImageFileInExtStorage: PropTypes.bool,
viewMode:PropTypes.string
};
var SignatureView = requireNativeComponent('SignatureView', SignatureCapture, {
nativeOnly: {onChange: true}
});
module.exports = SignatureCapture;
我正在使用ReactNative中的模块
<SignatureCapture
onSaveEvent={this._onSaveEvent}
saveImageFileInExtStorage={false}
viewMode={"portrait"}/>
一切都很有效。但我只有在反应方面发生一些点击事件时才需要保存图像。即,我必须从reactnative js代码调用SignatureCaptureMainView的saveImage()方法。
我怎样才能实现它?。请帮助
答案 0 :(得分:9)
根据@agent_hunt给出的指针。
检查此blog以获取解释
我在SignatureCaptureViewManager中使用了ui manager命令。发布我的解决方案
new DataTable().Compute("2-3/4*12", null) // Works fine, answer is -7;
new DataTable().Compute("2 / 0", null) // Works but not correct, answer is 8;
new DataTable().Compute("100 / 0", null) // Works but not correct, answer is 8;
new DataTable().Compute("2.0 / 0", null) // Throw System.DivideByZeroException as estimated.
为了向ViewManager发送命令,我在Signature Capture组件中添加了此方法
public class SignatureCaptureViewManager extends ViewGroupManager<SignatureCaptureMainView> {
private Activity mCurrentActivity;
public static final String PROPS_SAVE_IMAGE_FILE="saveImageFileInExtStorage";
public static final String PROPS_VIEW_MODE = "viewMode";
public static final int COMMAND_SAVE_IMAGE = 1;
public SignatureCaptureViewManager(Activity activity) {
mCurrentActivity = activity;
}
@Override
public String getName() {
return "SignatureView";
}
@ReactProp(name = PROPS_SAVE_IMAGE_FILE)
public void setSaveImageFileInExtStorage(SignatureCaptureMainView view, @Nullable Boolean saveFile) {
Log.d("React View manager setSaveFileInExtStorage:", "" + saveFile);
if(view!=null){
view.setSaveFileInExtStorage(saveFile);
}
}
@ReactProp(name = PROPS_VIEW_MODE)
public void setViewMode(SignatureCaptureMainView view, @Nullable String viewMode) {
Log.d("React View manager setViewMode:", "" + viewMode);
if(view!=null){
view.setViewMode(viewMode);
}
}
@Override
public SignatureCaptureMainView createViewInstance(ThemedReactContext context) {
Log.d("React"," View manager createViewInstance:");
return new SignatureCaptureMainView(context, mCurrentActivity);
}
@Override
public Map<String,Integer> getCommandsMap() {
Log.d("React"," View manager getCommandsMap:");
return MapBuilder.of(
"saveImage",
COMMAND_SAVE_IMAGE);
}
@Override
public void receiveCommand(
SignatureCaptureMainView view,
int commandType,
@Nullable ReadableArray args) {
Assertions.assertNotNull(view);
Assertions.assertNotNull(args);
switch (commandType) {
case COMMAND_SAVE_IMAGE: {
view.saveImage();
return;
}
default:
throw new IllegalArgumentException(String.format(
"Unsupported command %d received by %s.",
commandType,
getClass().getSimpleName()));
}
}
}
这就是我在父签名组件
中使用SignatureCapture组件的方法class SignatureCapture extends React.Component {
constructor() {
super();
this.onChange = this.onChange.bind(this);
}
onChange(event) {
console.log("Signature ON Change Event");
if (!this.props.onSaveEvent) {
return;
}
this.props.onSaveEvent({
pathName: event.nativeEvent.pathName,
encoded: event.nativeEvent.encoded,
});
}
render() {
return (
<SignatureView {...this.props} style={{flex: 1}} onChange= {this.onChange} />
);
}
saveImage(){
UIManager.dispatchViewManagerCommand(
React.findNodeHandle(this),
UIManager.SignatureView.Commands.saveImage,
[],
);
}
}
SignatureCapture.propTypes = {
...View.propTypes,
rotateClockwise: PropTypes.bool,
square:PropTypes.bool,
saveImageFileInExtStorage: PropTypes.bool,
viewMode:PropTypes.string
};
var SignatureView = requireNativeComponent('SignatureView', SignatureCapture, {
nativeOnly: {onChange: true}
});
module.exports = SignatureCapture;
答案 1 :(得分:4)
我需要一个解决方案,让我从组件实例方法返回值(在我的例子中为Promises)。使用receiveCommand
并不允许我这样做。
我能够使用UIManagerModule.addUIBlock
解决此问题,类似于https://stackoverflow.com/a/31936516/194065:
public class MyViewModule extends ReactContextBaseJavaModule {
public static final String TAG = MyViewModule.class.getSimpleName();
public MyViewModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "MyView";
}
@ReactMethod
public void someMethod(final int viewId, final Promise promise) {
withMyView(viewId, promise, new MyViewHandler() {
@Override
public void handle(MyView view) {
String value = view.someMethod();
promise.resolve(value)
}
});
}
private void withMyView(final int viewId, final Promise promise, final MyViewHandler handler) {
UIManagerModule uiManager = getReactApplicationContext().getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
@Override
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
View view = nativeViewHierarchyManager.resolveView(viewId);
if (view instanceof MyView) {
MyView myView = (MyView) view;
handler.handle(myView);
}
else {
Log.e(TAG, "Expected view to be instance of MyView, but found: " + view);
promise.reject("my_view", "Unexpected view type");
}
}
});
}
}
用法:
import React, { Component } from 'react';
import { NativeModules, requireNativeComponent, findNodeHandle } from "react-native";
const MyViewFunctions = NativeModules.MyView;
class MyView extends Component {
someMethod() {
MyViewFunctions.someMethod(findNodeHandle(this.nativeCmp));
}
render() {
return (
<RCTMyView
ref={cmp => this.nativeCmp = cmp}
{...this.props}
/>
);
}
const RCMyView = requireNativeComponent('RCMyView', MyView);
export default MyView;
答案 2 :(得分:2)
请参阅tong1