879479119 / react-native-shadow

A SVG shadow component powered with react-native-svg,which can provide shadow on Android like iOS ^_^
MIT License
612 stars 82 forks source link

Do I have to know previously what will be my View dimensions? #34

Open zygama opened 6 years ago

zygama commented 6 years ago

Hello,

all is in the title, I would like to know if for using this lib I need to know in advance what will be the height and the width of my View? Because it's not my case, my View can have elements added or deleted.

Is there a workaround for my case?

Thank you :)

chinookng commented 6 years ago

I'm also facing this issue. @zygama have you been able to figure it out?

zygama commented 6 years ago

Not yet...

ws7one commented 5 years ago

Has there been a solution for this yet?

jcorkhill commented 5 years ago

Has anyone found a solution to this yet? @zygama @ws7one @chinookng

hardrese7 commented 5 years ago

hey guys, I believe onLayout will resolve your issue. That event let you know view's dimensions. Please take a look next video: https://caster.io/lessons/advanced-react-native-getting-the-screen-or-a-views-dimensions

hardrese7 commented 5 years ago

code example:


import React from 'react';
import { BoxShadow } from 'react-native-shadow';

function getShadowSettings(width, height) {
  return {
    width: width,
    height: height,
    color: colors.third,
    border: 6,
    opacity: 0.1,
    x: 0,
    y: 1,
  };
}

class ShadowBox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      width: 0,
      height: 0,
      calculated: false,
    };
  }

  render() {
     const { width, height, calculated } = this.state;
    const { children } = this.props;
    const childrenWithProps = React.Children.map(children, child =>
      React.cloneElement(child, {
        onLayout: e => {
          const { width, height } = e.nativeEvent.layout;
          this.setState({ width, height, calculated: true });
        },
      }),
    );
    if (!calculated) {
      return childrenWithProps;
    }
    const shadowSettings = getShadowSettings(width, height);
    return <BoxShadow setting={shadowSettings}>{childrenWithProps}</BoxShadow>;
}
jcorkhill commented 5 years ago

@hardrese7 Thanks for the information and the code snippet. I'll try it later today and get back to you.

hardrese7 commented 5 years ago

@JamieCorkhill You are welcome, I faced with the same issue today :) There is just one requirement for ShadowBox component, it should have only one child now.

canpoyrazoglu commented 5 years ago

@hardrese7 I've tried the snippet, though it's completely messing up my layout.

hardrese7 commented 5 years ago

@canpoyrazoglu try the new version:

import React from 'react';
import { BoxShadow } from 'react-native-shadow';
import { View } from 'react-native';

export function getShadowSettings(width, height) {
  return {
    width: width,
    height: height,
    color: '#18304C',
    border: 6,
    opacity: 0.05,
    x: 0,
    y: 1,
  };
}

class ShadowBox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      width: 0,
      height: 0,
      calculated: false,
    };
  }

  onLayout(e) {
    const { width, height } = e.nativeEvent.layout;
    this.setState({ width, height, calculated: true });
  }

  render() {
    const { children, shadowSettings: customShadowSettings = {} } = this.props;
    if (React.Children.count(children) < 1) {
      throw Error('ShadowBox should have at least one child');
    }
    let childrenWithProps = children;
    if (React.Children.count(childrenWithProps) > 1) {
      childrenWithProps = <View>{children}</View>;
    }
    childrenWithProps = React.cloneElement(
      React.Children.only(childrenWithProps),
      {
        onLayout: this.onLayout.bind(this),
      },
    );
    const { width, height, calculated } = this.state;
    if (!calculated) {
      return childrenWithProps;
    }
    const shadowSettings = {
      ...getShadowSettings(width, height),
      ...customShadowSettings,
    };
    return (
      <View {...this.props}>
        <BoxShadow setting={shadowSettings}>{childrenWithProps}</BoxShadow>
      </View>
    );
  }
}
canpoyrazoglu commented 5 years ago

@hardrese7 nope, still messing it up (though comparably better than the first one).

It also errors on line React.Children.only(childrenWithProps) (though runs anyway).

canpoyrazoglu commented 5 years ago

I think I'll give up on this library and just apply a lame stretched PNG shadow below my views.