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

[Android] skew transform not working

Open usrbowe opened this issue 5 years ago • 31 comments

Steps To Reproduce

  1. Try to set skewX for View component: transforms: [{ skewX: '45deg' }}
  2. Doesn't change the skew of View on Android (works on iOS)

Describe what you expected to happen:

Basically skewX doesn't apply any skew on the view on Android. Here is comparison between iOS/Android:

also skewY doesn't render same as on iOS (which looks more correct) Screenshot 2020-01-02 at 2 13 00 PM

React Native version:

System:
    OS: macOS Mojave 10.14.6
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 1.50 GB / 16.00 GB
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 12.13.0 - ~/.nvm/versions/node/v12.13.0/bin/node
    Yarn: 1.19.1 - ~/.yarn/bin/yarn
    npm: 6.12.0 - ~/.nvm/versions/node/v12.13.0/bin/npm
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
    Android SDK:
      API Levels: 25, 28, 29
      Build Tools: 28.0.3, 29.0.2
      System Images: android-28 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
  IDEs:
    Android Studio: 3.5 AI-191.8026.42.35.5977832
    Xcode: 11.3/11C29 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9.0 => 16.9.0 
    react-native: 0.61.5 => 0.61.5

Related issues

  • [x] https://github.com/facebook/react-native/issues/12212

Snack demo

https://snack.expo.io/@usrbowe2/e9b920

Resources

In case anyone interested, here is the source code for skew code:

  1. This is called for SkewX: MatrixMathHelper.applySkewX(helperMatrix, convertToRadians(transform, transformType)); in file: Libraries/StyleSheet/processTransform.js
  2. Which laters uses this matrix helper to apply transformation: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/uimanager/MatrixMathHelper.java

usrbowe avatar Jan 02 '20 06:01 usrbowe

This is real problem!

MarekJavurek avatar Jan 03 '20 12:01 MarekJavurek

I faced this issue too in android but for iOS, it is working fine.

HarshitMadhav avatar Jan 04 '20 04:01 HarshitMadhav

i also have this issue, anyone have a workaround? I had search this issue on google, there have many people said use the native canvas have no problem, so whether modify the MatrixMathHelper.java could resolve this issue?

JX0829 avatar Jan 06 '20 02:01 JX0829

@JX0829 As of now I have searched a lot for workarounds but found nothing. Sadly, I had to remove skew for android.

HarshitMadhav avatar Jan 06 '20 06:01 HarshitMadhav

A live preview of this issue can be found at the example in https://deploy-preview-1613--react-native.netlify.com/docs/next/transforms

DaniAkash avatar Feb 09 '20 02:02 DaniAkash

I found this package: https://github.com/wumke/react-native-skewable-view It skews the shape of the view in android but not images and texts that are inside... As work around you can also try using canvas, with for example this package: https://github.com/iddan/react-native-canvas#readme. But personally when I try ctx.drawImage(img, width, height) I get an error: "JSON.stringify cannot serialize cyclic structures." So I'm still facing this problem for images.

Valegox avatar Apr 13 '20 12:04 Valegox

For images I just recreated it by myself: I croped 100 same images with ImageEditor and aligned each part in offset to create the one I needed...

Valegox avatar Apr 13 '20 20:04 Valegox

I can see that skew style rules are still not working correctly on Android with RN v0.64.2.

Even the example provided on the transforms documentation page doesn't work:

anroid-skew-not-working

However it works on iOS as described in the original issue:

ios-skew-working

Can we reopen this issue as it seems like the applied fix didn't resolve the reported issue?

ramyma avatar Jun 09 '21 01:06 ramyma

I'm still facing this issue. SkewY works, skewX doesn't. Skew works properly on iOS but it doesn't on android

ghaschel avatar Jun 22 '21 23:06 ghaschel

reopening for now.

@ramyma @ghaschel can either of you try if it still repros with RN 65 RC2?

kelset avatar Jun 23 '21 09:06 kelset

I'll take a look as soon as I can. But just in advance, it is still not working on your documentation using the next version

ghaschel avatar Jun 24 '21 18:06 ghaschel

@kelset it still happens.

This is when using skewX on android (nothing happens): image

and this is when happens when using skewY on android (as visible, the view is not skewed, but instead, rotated): image

Btw: This IS on RN 65 RC2

ghaschel avatar Jul 06 '21 17:07 ghaschel

I would like to point out that it seems like on Android the skew y operation is doing a bit of rotation as well if you compare it to the iOS result (which I think should be the correct result).

So, on Android, skew x is not working at all, and skew y is doing something but not the intended result.

ramyma avatar Jul 11 '21 12:07 ramyma

did anyone figure out how to make skewX work on Android? We are currently running 0.64.2 and skewX still doesn't work.

Podlipny avatar Aug 04 '21 08:08 Podlipny

Hello to everyone! Any news about this problem? I'm using RN 0.65.1 and skewX still doesn't work.

Any workaround would be fine.

danieldulcettiBN avatar Nov 03 '21 11:11 danieldulcettiBN

One solution can be to use a combination of rotates (x,y,z) to produce a similar effect.

It will not be exactly similar to Skew but with some trial and error we can produce something similar.

Eg. <View style={{ transform: [ { rotateZ: "345deg" } ] }}> <View style={[styles.box, { transform: [ { rotateX: "30deg" }, { rotateY: "330deg" }, { rotateZ: "30deg" } ] }]}> <Text style={styles.text}>Rotate X,Y,Z (similar to skew)</Text> </View> </View>

MFQuraishi avatar Jan 08 '22 18:01 MFQuraishi

still not wroking... any solution ?

rvuyyuru1 avatar Jul 18 '22 05:07 rvuyyuru1

  • My turn, still not working? I've tried using skew but bleh... not working

  • A work arround solution might be using a png image with the figure as a backgroud with ImageBackground (This isn't the prettier solution but works for now):

Here's an example: Err ... Err

thlindustries avatar Oct 28 '22 15:10 thlindustries

Version 0.70.5, skewX still doesn't work

DieTime avatar Nov 09 '22 22:11 DieTime

skewX and skewY are not working on android mobile phones. But it works only in IOS.

I use transform: [{ skewX: '45deg' }].

bilal882 avatar Feb 01 '23 12:02 bilal882

Is this issue abandoned?

itsramiel avatar Mar 11 '23 09:03 itsramiel

Is this issue abandoned?

Definitely not, the problem stills there :/

thlindustries avatar Mar 22 '23 01:03 thlindustries

The root cause here is that Android does not natively support a skew property. The way we apply transforms is to decompose them and set the individual view properties: https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java#L431-L447

Suggestions welcome on how to achieve the desired behaviour in Android.

javache avatar May 04 '23 10:05 javache

It sounds like it is not possible at the moment to achieve the expected behaviour. Android View doesn't even provide the setTransformation(Matrix) method to do the skew.

DieTime avatar May 09 '23 11:05 DieTime

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Nov 06 '23 05:11 github-actions[bot]

Still valid

itsramiel avatar Nov 06 '23 06:11 itsramiel

still having this problem

brent-charlton avatar Nov 24 '23 11:11 brent-charlton

I found another workaround but it's a bit difficult to implement and might not work for all use cases. In my case I was trying to make a "register" ribbon. What I did is make the view way too wide, rotate it 45 degrees, and put it in another view that with overflow: hidden. Note you will need to do some math to figure out what the width of the outer view should be, because it wont account for the fact the inner view is rotated 45 degrees. Here is my implementation for reference

interface RibbonProps {
    text: string
    color: string
    textColor: string,
    styles?: StyleProp<ViewStyle>
}

function toRadians (angle: number): number {
    return angle * (Math.PI / 180);
}

const Ribbon: React.FC<RibbonProps> = (props: RibbonProps) => {

    const [ribbonWidth, setRibbonWidth] = React.useState(1); // cant be 0 or we'll try to divide by 0
    const [ribbonHeight, setRibbonHeight] = React.useState(1); // cant be 0 or we'll try to divide by 0
    const [containerWidth, setContainerWidth] = React.useState(1); // cant be 0 or we'll try to divide by 0
    const [containerHeight, setContainerHeight] = React.useState(1); // cant be 0 or we'll try to divide by 0


    const onBannerLayout = (event: LayoutChangeEvent) => {
        const { height, width } = event.nativeEvent.layout;
        setRibbonHeight(height);
        setRibbonWidth(width);
    }

    const onContainerLayout = (event: LayoutChangeEvent) => {
        const { height, width } = event.nativeEvent.layout;
        setContainerHeight(height);
        setContainerWidth(width);
    }



    const styles = StyleSheet.create({
        ribbon: {
            transform: [{ rotate: '45deg' }],
            alignItems: "center",
            justifyContent: "center",
            width: "1000%",
        },
        container: {
            overflow: "hidden",
            alignItems: "center",
            justifyContent: "center",
            flex: 1,
            width: ((ribbonHeight / Math.sin(toRadians(45))) + (containerHeight / Math.tan(toRadians(45))))
        }
    });


    return (
        <View style={[styles.container, props.styles]} onLayout={onContainerLayout}>
            <View style={[styles.ribbon, { backgroundColor: props.color }]} onLayout={onBannerLayout}>
                <AppText style={{ color: props.textColor, padding: 0 }}>{props.text}</AppText>
            </View>
        </View>
    );
};

export default Ribbon;

GNUGradyn avatar Nov 25 '23 19:11 GNUGradyn

As of today, 2024.2.21, the skew transform still not working, in the official documentation! skewX not working at all! skewY looks like only a rotate ? 😓😓😓 WX20240221-102237@2x

likeSo avatar Feb 21 '24 02:02 likeSo

2024 and still same issue :(

zane-commeatio avatar Apr 15 '24 10:04 zane-commeatio

It looks like view.setSkewX and view.setSkewY doesn't apply here:

https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java#L545

However, Android's View doesn't have setSkewX and setSkewY methods

But it has setTransformation (as part of View > dispatchProvideStructure) which can apply the whole Matrix. This requires API level 23. https://developer.android.com/reference/android/view/ViewStructure#setTransformation(android.graphics.Matrix)

For such case, we even don't need to perform matrix decomposition.

Update: Another option is override getChildStaticTransformation like suggested here

MaxGraey avatar Jun 01 '24 08:06 MaxGraey