Home > Mobile >  Touchable Opacity not working when nested inside View component but works if Touchable opacity is ma
Touchable Opacity not working when nested inside View component but works if Touchable opacity is ma

Time:01-24

I have the following component created for showing an image card on screen. Inside this card there is an image that I am trying to make touchable, however, its does seem to work and when I try clicking on it, nothing happens.

But if I make the Touchable opacity as a parent component below, then the complete image card component becomes touchable and it works on screen. However, I do not want that and only want to target sub elements in this below card component. Not sure how to fix this!

import React, { useState } from "react";
import {
  View,
  Image,
  Text,
  StyleSheet,
  TouchableOpacity,  
} from "react-native";
const ImageCardView = ({
  title,
  category,
  Price,
  description,
  imageUrl,
  rating,
}) => {
return (
    <View style={{ backgroundColor: "#d3c4de" }}>
      <View style={styles.cardContainer}>
        <RedCircle />
        <TouchableOpacity onPress={() => navigation.navigate("showCase")}>
          <Image
            source={{
              uri: imageUrl,
            }}
            style={styles.image}
          />
        </TouchableOpacity>

        <SeparatorVertical />
        <View style={styles.textContainer}>
          <Text style={styles.title}>{title}</Text>
          <Text style={styles.category}>{category}</Text>
          <Text style={styles.price}>${Price}</Text>

          <SeparatorHorizontal />
          <Text numberOfLines={2} style={styles.description}>
            {description}
          </Text>
          <View style={styles.rightBottom}>
            <TouchableOpacity
              style={styles.button}
              onPress={() => setIsPressed(!isPressed)}
            >
              <Text>Add To Cart</Text>
            </TouchableOpacity>

            {/* {isPressed && (
              <View
                style={{
                  backgroundColor: "white",
                  paddingLeft: 16,
                  paddingRight: 16,
                }}
              >
                <View
                  style={{
                    flexDirection: "row",
                    alignItems: "center",
                    paddingBottom: 12,
                  }}
                >
                  <TouchableOpacity
                    disabled={!items.length}
                    onPress={removeItemFromBasket}
                  >
                    <Icon
                      name="minus-circle"
                      size={40}
                      color={items.length > 0 ? "#00CCBB" : "gray"}
                    />
                  </TouchableOpacity>
                  <Text>{items.length}</Text>
                  <TouchableOpacity onPress={addItemToBasket}>
                    <Icon name="plus-circle" size={40} color="#00CCBB" />
                  </TouchableOpacity>
                </View>
              </View>
            )} */}

            <View style={styles.ratingContainer}>
              {[...Array(5)].map((star, i) => {
                const ratingValue = i   1;
                return (
                  <Text
                    key={i}
                    style={[
                      styles.star,
                      ratingValue <= rating && styles.filledStar,
                    ]}
                  >
                    &#9733;
                  </Text>
                );
              })}
            </View>
          </View>
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  cardContainer: {
    flexDirection: "row",
    alignItems: "center",
    backgroundColor: "white",
    borderRadius: 5,
    overflow: "hidden",
    marginVertical: 10,
    marginLeft: 3,
    width: "98%",
    height: 300,
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5,
  },
  image: {
    width: 150,
    height: 228,
    resizeMode: "cover",
  },
  textContainer: {
    paddingLeft: 10,
  },
  title: {
    fontWeight: "bold",
    fontSize: 20,
    marginBottom: 10,
  },
  category: {
    color: "#d6c3b9",
  },
  price: {
    fontSize: 20,
    fontWeight: "bold",
    color: "#05c3fa",
  },
  description: {
    flexDirection: "row",
    flexWrap: "wrap",
    fontSize: 15,
    color: "#666",
    marginBottom: 20,
  },
  ratingContainer: {
    flexDirection: "row",
    alignItems: "center",
  },
  button: {
    alignItems: "center",
    backgroundColor: "#5cb85c",
    borderRadius: 5,
    padding: 10,
  },
  rightBottom: {
    flexDirection: "row",
  },
  star: {
    fontSize: 18,
    color: "#888",
  },
  filledStar: {
    color: "#ffd700",
  },
});

export default ImageCardView;

enter image description here

CodePudding user response:

Without seeing the all the code, my suggestion is to make sure your TouchableOpacity is being imported from "react-native" and not from "react-native-gesture-handler" or some other npm package like "react-native-web".

CodePudding user response:

Check the below code and logs, it's working fine:

import React, { useState } from "react";
import {
    View,
    Image,
    Text,
    StyleSheet,
    TouchableOpacity,
} from "react-native";
const App = ({
    title,
    category,
    Price,
    description,
    imageUrl,
    rating,
}) => {
    const [isPressed, setIsPressed] = useState(false)
    return (
        <View style={{ backgroundColor: "#d3c4de" }}>
            <View style={styles.cardContainer}>
                <TouchableOpacity onPress={() => {
                    console.log("on pressed!!!!")
                    navigation.navigate("showCase")
                }
                }>
                    <Image
                        source={{
                            uri: imageUrl,
                        }}
                        style={styles.image}
                    />
                </TouchableOpacity>

                <View style={styles.textContainer}>
                    <Text style={styles.title}>{title}</Text>
                    <Text style={styles.category}>{category}</Text>
                    <Text style={styles.price}>${Price}</Text>

                    <Text numberOfLines={2} style={styles.description}>
                        {description}
                    </Text>
                    <View style={styles.rightBottom}>
                        <TouchableOpacity
                            style={styles.button}
                            onPress={() => {
                                console.log("Add to card pressed!!!!")
                                setIsPressed(!isPressed)
                            }}>
                            <Text>Add To Cart</Text>
                        </TouchableOpacity>

                        {isPressed && (
                            <View
                                style={{
                                    backgroundColor: "white",
                                    paddingLeft: 16,
                                    paddingRight: 16,
                                }}
                            >
                                <View
                                    style={{
                                        flexDirection: "row",
                                        alignItems: "center",
                                        paddingBottom: 12,
                                    }}
                                >
                                    <TouchableOpacity
                                        disabled={!items.length}
                                        onPress={removeItemFromBasket}
                                    >
                                        <Icon
                                            name="minus-circle"
                                            size={40}
                                            color={items.length > 0 ? "#00CCBB" : "gray"}
                                        />
                                    </TouchableOpacity>
                                    <Text>{items.length}</Text>
                                    <TouchableOpacity onPress={addItemToBasket}>
                                        <Icon name="plus-circle" size={40} color="#00CCBB" />
                                    </TouchableOpacity>
                                </View>
                            </View>
                        )}

                        <View style={styles.ratingContainer}>
                            {[...Array(5)].map((star, i) => {
                                const ratingValue = i   1;
                                return (
                                    <Text
                                        key={i}
                                        style={[
                                            styles.star,
                                            ratingValue <= rating && styles.filledStar,
                                        ]}
                                    >
                                        &#9733;
                                    </Text>
                                );
                            })}
                        </View>
                    </View>
                </View>
            </View>
        </View>
    );
};

const styles = StyleSheet.create({
    cardContainer: {
        flexDirection: "row",
        alignItems: "center",
        backgroundColor: "white",
        borderRadius: 5,
        overflow: "hidden",
        marginVertical: 10,
        marginLeft: 3,
        width: "98%",
        height: 300,
        shadowColor: "#000",
        shadowOffset: {
            width: 0,
            height: 2,
        },
        shadowOpacity: 0.25,
        shadowRadius: 3.84,
        elevation: 5,
    },
    image: {
        width: 150,
        height: 228,
        resizeMode: "cover",
    },
    textContainer: {
        paddingLeft: 10,
    },
    title: {
        fontWeight: "bold",
        fontSize: 20,
        marginBottom: 10,
    },
    category: {
        color: "#d6c3b9",
    },
    price: {
        fontSize: 20,
        fontWeight: "bold",
        color: "#05c3fa",
    },
    description: {
        flexDirection: "row",
        flexWrap: "wrap",
        fontSize: 15,
        color: "#666",
        marginBottom: 20,
    },
    ratingContainer: {
        flexDirection: "row",
        alignItems: "center",
    },
    button: {
        alignItems: "center",
        backgroundColor: "#5cb85c",
        borderRadius: 5,
        padding: 10,
    },
    rightBottom: {
        flexDirection: "row",
    },
    star: {
        fontSize: 18,
        color: "#888",
    },
    filledStar: {
        color: "#ffd700",
    },
});

export default App;

For navigation, you need to get it referenced from parent props.

CodePudding user response:

Thanks everyone. I got it fixed, in my case somehow the component was blocking the Touchable opacity, so included that inside my Touchable capacity to include the with the image and it started working

  • Related