Joh*_*ohn 11 android reactjs react-native react-android
我创建了一个CustomView SignatureView.java,它扩展了LinearLayout以捕获Android Native中的签名.
并创建了SignatureCapturePackage.java和SignatureCaptureViewManager.java
public class SignatureCaptureMainView extends LinearLayout {
....
public void saveImage(){
//Save image to file
}
}
Run Code Online (Sandbox Code Playgroud)
这个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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是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);
}
}
Run Code Online (Sandbox Code Playgroud)
这是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;
Run Code Online (Sandbox Code Playgroud)
我在这里使用ReactNative中的Module
<SignatureCapture
onSaveEvent={this._onSaveEvent}
saveImageFileInExtStorage={false}
viewMode={"portrait"}/>
Run Code Online (Sandbox Code Playgroud)
一切都很有效.但是我必须在反应方面发生一些点击事件时才保存图像.即,我必须从reactnative js代码调用SignatureCaptureMainView的saveImage()方法.
我怎样才能实现它?.请帮助
Joh*_*ohn 11
根据@agent_hunt给出的指针.
查看此博客以获得解释
我在SignatureCaptureViewManager中使用了ui manager命令.发布我的解决方案
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()));
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了向ViewManager发送命令,我在Signature Capture组件中添加了此方法
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;
Run Code Online (Sandbox Code Playgroud)
这就是我在父Signature组件中使用SignatureCapture组件的方法
class Signature extends Component {
render() {
return (
<View style={{ flex: 1, flexDirection: "column" }}>
<SignatureCapture
style={{ flex: 8 }}
ref="sign",
onSaveEvent={this._onSaveEvent}
saveImageFileInExtStorage={false}
viewMode={"portrait"}/>
<TouchableHighlight style={{ flex: 2 }}
onPress={() => { this.saveSign() } } >
<Text>Save</Text>
</TouchableHighlight>
</View>
);
}
// Calls Save method of native view and triggers onSaveEvent callback
saveSign() {
this.refs["sign"].saveImage();
}
_onSaveEvent(result) {
//result.encoded - for the base64 encoded png
//result.pathName - for the file path name
console.log(result);
}
}
export default Signature;
Run Code Online (Sandbox Code Playgroud)
我需要一个解决方案,让我从组件实例方法(在我的例子中为 Promises)返回值。使用receiveCommand不允许我这样做。
我能够使用UIManagerModule.addUIBlock类似于/sf/answers/2235556151/来解决这个问题:
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");
}
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6049 次 |
| 最近记录: |