react-native-signature-canvas icon indicating copy to clipboard operation
react-native-signature-canvas copied to clipboard

Only dots are drawn on Android

Open VashaMasha opened this issue 3 years ago • 16 comments

Hello! When I try to draw something fast instead of the expected shape I see only one dot. I've noticed that in this case calls only onBegin prop, onEnd is not calling.

Could you please tell what can i do with this problem?

How I use the component: (onBegin() and onEnd() are needed for disabling and enabling the parent component's scrollView)

<Signature
        ref={ref}
        onOK={handleSignature}
        webStyle={webStyle}
        descriptionText={signatureError}
        trimWhitespace={true}
        onBegin={() => { 
            !pressed ? setSignatureErrorText("") : {}
            onBegin ? onBegin() : {};
        }}
        onEnd={() => { 
            ref.current?.readSignature();
            onEnd ? onEnd() : {};
        }}
  />

VashaMasha avatar Mar 09 '21 08:03 VashaMasha

Hope you can provide complete code that can run

YanYuanFE avatar Mar 15 '21 03:03 YanYuanFE

Sorry for taking so long Here is my component and video with behavior playback

On the video you can see that when I've got the dot inside the signature field (making a sharp move) I am not able to use scroll anymore

https://user-images.githubusercontent.com/36168154/111494165-4d101d80-874f-11eb-9385-a7a1eb53d3b8.mov

import React, {useState, useRef } from 'react';
import { StyleSheet, ScrollView, View, Dimensions, Pressable, Text } from 'react-native';
import Signature, { SignatureViewRef } from 'react-native-signature-canvas';

const windowWidth  = Dimensions.get('window').width

const SignatureScreen = () => {
    const [isScrollEnabled, setScrollEnabled] = useState(true)
    const ref = useRef<SignatureViewRef>(null);
    const [signatureValue, setSignatureValue] = useState("");

    const handleSignature = (signature: any) => {
        setSignatureValue(signature)
    };

    const onClearButtonPress = () => {
        setScrollEnabled(true)
        setSignatureValue("")
        ref.current?.clearSignature()
    }

    const webStyle = `
        .m-signature-pad--body {
            position: absolute;
            bottom: 0px;
            top: 0px;
            left: 0px;
            right: 0px;
            border: none;
        }
        .m-signature-pad--footer
            .button.clear {
                display: none
            }
            .button.save {
                display: none
            }
        .m-signature-pad--footer {
            display: none
        }
    `;

    return (
        <ScrollView scrollEnabled={isScrollEnabled} contentContainerStyle={styles.container}>
            <View style={[styles.signatureWrapper, { height: windowWidth}]}>
                <Signature
                    ref={ref}
                    onOK={handleSignature}
                    webStyle={webStyle}
                    trimWhitespace={true}
                    onBegin={() => setScrollEnabled(false)}
                    onEnd={() => { 
                        ref.current?.readSignature();
                        setScrollEnabled(true)
                    }}
                />
            </View>
            <View style={styles.bottomButtons}>
                <Pressable style={styles.transparentButton} onPress={onClearButtonPress} >
                    <Text>clear signature</Text>
                </Pressable>
            </View>
            <View style={{height: 500}}>
                <Text>White space</Text>
            </View>
        </ScrollView>
    )
}

const styles = StyleSheet.create({
    container: {
        padding: 20,
    },
    signatureWrapper: {
        padding: 2,
        borderWidth: 2,
        borderRadius: 10
    },
    bottomButtons: {
        alignItems: 'center'
    },
    transparentButton: {
        paddingTop: 7,
        paddingBottom: 11,
        marginTop: 14,
        marginBottom: 10
    },
    text: {
        paddingTop: 12,
        paddingBottom: 15,
        color: "#1f2229",
        fontSize: 15
    }
})

export default SignatureScreen;

VashaMasha avatar Mar 17 '21 15:03 VashaMasha

Sorry for keeping you waiting. I used your code to reproduce this problem. I think this problem is caused by using ScrollView. The onEnd event is not triggered when the scroll is too fast. When I set scrollEnabled to false, it It works normally. I have no good solution for the time being. If you have a good solution, please PR and sorry again.

YanYuanFE avatar Mar 20 '21 14:03 YanYuanFE

Unfortunately I can't do without scrolling(( Thank you for your time! If I find a solution, I will PR.

VashaMasha avatar Mar 22 '21 09:03 VashaMasha

Facing the same issue on Android with Modal. Any solution would be appreciated @YanYuanFE Screenshot_20210417-195822

randomittin avatar Apr 17 '21 18:04 randomittin

Same here even without a scroll view, this happens on certain devices. I narrowed it down to the fact that if the signature screen is the first one rendered it works, but having a transition to it from any other screen breaks the behavior, and only dots are drawn.

omerts avatar Apr 29 '21 03:04 omerts

I had the same issue.

I have my SignaturePad inside the Modal Screen .

My parent component of the Screen was a TouchableOpacity (so that I can close modal on clicking outside ) and I was wrapping my SignaturePad inside it and it was causing this issue.

But it worked properly in IOS

After replacing my TouchableOpacity to View the issue didn't occurred again.

Eventually I ended up adding a close button to close my modal screen.

I hope this helps someone who has similar component like mine.

ameyalinge-21 avatar Apr 30 '21 14:04 ameyalinge-21

Same problem if signature too fast, the component cannot be used in the report with a scrollView

dylanfcsr avatar Sep 20 '21 12:09 dylanfcsr

Try to add androidHardwareAccelerationDisabled={true} to your SignatureScreen component. I think on Android it may be related to hardware acceleration. Turning it off will slow component performance a bit, but you should get a better plot.

Michael-AYK avatar Feb 24 '23 09:02 Michael-AYK

Same here even without a scroll view, this happens on certain devices. I narrowed it down to the fact that if the signature screen is the first one rendered it works, but having a transition to it from any other screen breaks the behavior, and only dots are drawn.

I'm having the same issue, is there any way to fix this?

jn394 avatar Apr 28 '23 19:04 jn394

@jn394 "I had the same error, I had wrapped my SignatureScreen in the following code block:

<View onLayout={onSignatureLayout} {...panResponder.panHandlers} style={{ width: imgWidth, height: imgHeight }}

Removing it solved my error, I hope it helps you."

Florido14 avatar May 04 '23 18:05 Florido14

I used the nestedScrollEnabled={true} prop with the WebView component, and that resolved the issue and I used patch-package to create a patch file. <WebView bounces={false} source={source} ref={webViewRef} onError={renderError} onMessage={getSignature} javaScriptEnabled={true} scrollEnabled={scrollable} androidLayerType="hardware" style={[webviewContainerStyle]} onLoadEnd={() => setLoading(false)} nestedScrollEnabled={true} />

huult avatar Aug 09 '23 10:08 huult

Same problem here... even though it works perfectly on iOS

None of the solutions above worked for me.

Torugok9 avatar Jan 03 '24 15:01 Torugok9

Same problem here... even though it works perfectly on iOS

None of the solutions above worked for me.

10 seconds later i found out that i was wrapping my canvas with TouchableWithoutFeedback in my dynamic form, so i removed and it works fine.

It was like this:

  return (
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <View>
        {renderInputType(text)}
      </View>
    </TouchableWithoutFeedback>
  );

now it looks like this ( when text == A it'll render the canvas ) :

  return text !== 'A'  ? (
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <View>
        {renderInputType(text)}
      </View>
    </TouchableWithoutFeedback>
  ) : (
    <View>
      {renderInputType(text)}
    </View>
  );

Torugok9 avatar Jan 03 '24 15:01 Torugok9

androidLayerType="hardware"

worked for me !

ajmalomerr avatar Jan 24 '24 05:01 ajmalomerr