React-native-ui-kitten: Custom Card Body

Created on 1 Oct 2020  Â·  11Comments  Â·  Source: akveo/react-native-ui-kitten

💬 Question

Looking at the documentation, it seems like the Card component is designed for only as the main content. Is there a way to enable a custom flex content inside as well? I tried using a custom layout with as the child, but the layout is not showing up correctly, and flex is not having the expected behavior.

UI Kitten and Eva version

| Package | Version |
| ----------- | ----------- |
| @eva-design/eva | 2.0.0 |
| @ui-kitten/components | 5.0.0 |

Help wanted

Most helpful comment

@artyorsh

If you run the code below, you'd see the child components of Card do not follow the flexDirection: 'row' property but rather stubbornly get rendered in a column.

import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
import { Card, Text } from '@ui-kitten/components';

export const WriterItem = (props) => {
    return (
        <Card style={styles.card}>
            <View>
                <Image source={props.source} style={styles.cover}></Image>
            </View>
            <Text category="h5">The Vampire</Text>
        </Card>
    );
};

const styles = StyleSheet.create({
    card: {
        width: '95%',
        display: 'flex',
        flexDirection: 'row',
    },
    cover: {
        width: 60,
        height: 60,
    },
});

All 11 comments

What do you mean with custom flex? Could you please also provide a sample code?

@artyorsh

If you run the code below, you'd see the child components of Card do not follow the flexDirection: 'row' property but rather stubbornly get rendered in a column.

import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
import { Card, Text } from '@ui-kitten/components';

export const WriterItem = (props) => {
    return (
        <Card style={styles.card}>
            <View>
                <Image source={props.source} style={styles.cover}></Image>
            </View>
            <Text category="h5">The Vampire</Text>
        </Card>
    );
};

const styles = StyleSheet.create({
    card: {
        width: '95%',
        display: 'flex',
        flexDirection: 'row',
    },
    cover: {
        width: 60,
        height: 60,
    },
});

I'm having wired behavior same as @parkerqueen with flex props on a card. It doesn't respect all flex related props!

This all happens due to this line.
I agree that this is not expected behavior and as a workaround which covers every styling use cases my only suggestion would be using the structure like this:

const MyCard = ({ contentContainerStyle, children, ...props }) => (
  <Card {...props}>
    <View style={[{ marginHorizontal: -24, marginVertical: -16 }, contentContainerStyle]}>
      {children}
    </View>
  </Card>
);

Also covers https://github.com/akveo/react-native-ui-kitten/issues/1037. See an example

What you suggested dosen't work on android. At least flex direction had no effect.
I found out that when you set a fixed height & width for the root body view, it solves the problems of flex direction.
I tried using '100%' on height & width it doesn't work. And you can't use flex=1 for cards body :facepalm:.
So it is a fixed size only.

@eyalyoli I had just launched the example by the link I shared to clarify this and it worked. Could you please try that?

@artyorsh sorry for not beign specific. Using your code and chaning it to:

<MyCard 
            style={{ marginVertical: 8, flex:1 }}
            contentContainerStyle={{ flex:1, flexDirection: 'row', justifyContent:'center', alignItems:'center' }}>
...
</MyCard>

flex on the card takes effect, but not on the body. This works as if card's body had no height. But when you set height=400 you'll get the needed results. I was wrong, the same issue effects web view.

Hope you could help with that.

@eyalyoli could you please clarify then which result you need to achieve?

This is the behaviour of card (top) vs view (bottom) with the same prop styling:
image

I tried to make the view in the same structure as the card. The problem is that flex: 1 is not working as you would think in a View.
Card code:

<MyCard
            style={{ marginVertical: 8, flex: 1 }}
            contentContainerStyle={{
              flex: 1,
              flexDirection: 'row',
              justifyContent: 'center',
              alignItems: 'center',
            }}>
            <Image
              style={{ width: 80, height: 80 }}
              source={{
                uri:
                  'https://akveo.github.io/react-native-ui-kitten/images/Artboard-1.png',
              }}
            />
            <Text style={{ margin: 12 }} category="h5">
              Title
            </Text>
            <Text style={{ margin: 12 }}>
              Text Text
            </Text>
</MyCard>

View code:

 <View style={{ marginVertical: 8, flex: 1 }}> //this is the card
            <View //this is the root view that used in the card
              style={{
                flex: 1,
                flexDirection: 'row',
                justifyContent: 'center',
                alignItems: 'center',
                borderWidth: 2,
              }}>
              <Image
                style={{ width: 80, height: 80 }}
                source={{
                  uri:
                    'https://akveo.github.io/react-native-ui-kitten/images/Artboard-1.png',
                }}
              />
              <Text style={{ margin: 12 }} category="h5">
                Title
              </Text>
              <Text style={{ margin: 12 }}>
              Text Text
            </Text>
            </View>
</View>

This is just an example of a more complex case in which I have an image as a header & other information in the body of a card and I need to make it scale dynamiclly with different screen sizes (using flex).

@artyorsh should I reopen this as a bug?
I noticed that when flex in footer seems to work fine.

Ok, for everyone who needs complex card content that is very responsive to screen size, I managed to do so using my own card implementation.

<View
      style={[
        {
          borderRadius: 15,
          borderWidth: 1,
          margin: 20,
          borderColor: theme["color-basic-300"],
          overflow: "hidden",
          flex: 1,
        },
        style,
      ]}
    >
      <View>{header()}</View>
      <View> // 1
        <View>{children}</View>
        <Divider />
        <View>{footer()}</View>
      </View>
    </View>

You can do whatever you need with the sizes and flexboxes, I wrapped the footer and the chidren with a view (marked 1) becuase my header is just an image.
This will look very similar to kitten's card component.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shiqian123 picture shiqian123  Â·  3Comments

domsterthebot picture domsterthebot  Â·  3Comments

jeloagnasin picture jeloagnasin  Â·  3Comments

sobiso picture sobiso  Â·  3Comments

betodasilva picture betodasilva  Â·  3Comments