ScrollView not working (only on android) reactnative - javascript

This is only happening for one of the custom components that I have created. This use to work but it randomly stopped. I have tried to move ScrollView in different parts of the function (before View, around Card ...) but I've had no success. The little scrollbar on the right hand side shows...you just can't scroll. But it works without any issues on iOS
I also tried to give View that wraps ScrollView flex: 1 but no success.
I'm running expo v42
using native base ^2.15.2
The component:
import React from 'react';
import { View, StyleSheet, Image, ScrollView } from 'react-native';
import propTypes from 'prop-types';
import { Card, CardItem } from 'native-base';
export default function ExerciseCard(props) {
const { iconSource, iconType, customStyle, SVG } = props;
return (
<Card style={styles.Card}> // this is from native base
<CardItem style={[styles.ExerciseCard, customStyle]}> // also native base
//icon stuff
// dynamic svg
<View style={styles.TopToBottom}>
<ScrollView>
{props.children} // this can have bunch of text hence why I need to scroll through them
</ScrollView>
</View>
</CardItem>
</Card >

I don't know if it can bring you a solution but I've already encountered this kind of issue, and I had to wrap the content in a touch component like touchableOpacity.
I think the issue depends on the layering / wrapping around the scrollview.

Related

Set React base background color while display mostly uses components

I am currently trying to style a React project in which App.js mainly serves the function of Routing and navigating to its components:
App.js
import {useState, useEffect} from 'react';
import Models from './pages/Models';
import Loadingpage from './pages/Loadingpage';
import Output from './pages/Output';
import './App.css';
import {BrowserRouter, Route, Switch} from "react-router-dom";
function App() {
// state variables and function declarations.....
return (
<Browserouter>
<Switch>
<Route path="/" exact>
{isLoading===true?
<Loadingpage/>
:
<Models/>
</Route>
<Route path="/models/output" exact>
<Output/>
</Route>
</Switch>
</Browserouter>
);
}
The flow works as follows:
If app.js is in a loading state, we render the loading page component. Here is the loading page's entire body:
<div className="Loading page"
style={{
display: 'flex',
alignItems: 'center',
background: "#A0C5E8",
justifyContent: 'center',
}}
>
<FlowerSpinner size={props.size} color={props.color}/>
</div>
When the loading time has elapsed, we render the model page (which consists simply of buttons)
When a button is clicked, the output page is rendered.
The components work completely fine, and they all work the same way the loading page does. They simply render as a component overtop (or so it appears). However, the component pages only render the section of space they take up, which makes it seem like the underlying background needs to be changed somewhere. Here is what happens:
As shown, the pages have their own divs in which their respective background is displayed. I have already tried wrapping each component in a div with the corresponding background color, and the entire app.js in a div as well:
eg.
<div
style={{
display: 'flex',
alignItems: 'center',
background: "#A0C5E8",
justifyContent: 'center',
}}
>
<Loadingpage size={300} color="black"/>
</div>
How do I successfully change the base background color? Help would be greatly appreciated, thanks for reading!
To change the background color of the whole page , you need to apply the style to the body tag of the html and import styles in the index.js or App.js file :
styles.css
body {
background : #A0C5E8
}
index.js or App.js
import './styles.css'
If the background color is different on other pages, consider using a react hook to add and remove classes from the body after the page has changed route.
styles.css
.loading-page {
background : #A0C5E8
}
import React, { useEffect } from "react";
import './styles.css';
function App() {
// state variables and function declarations.....
useEffect(() => {
document.body.classList.add('loading-page');
return function cleanup() {
document.body.classList.remove('landing');
};
});
...
}

Set ImageBackground using Stack Navigator

What I'm facing:
I have a StackNavigator in which I want to set a ImageBacgkround to all it's children screens. The problem is, I've already setted my StackNavigator cardStyle: { backgroundColor: 'transparent' }, following React Navigation Docs, and wrapped it inside a ImageBackground but still can't get it working.
What I've tried:
//My navigator component is more complex, but the concept looks something like this
//for both navigators
const Stack = createStackNavigator();
const MyStackNavigator = () => (
<ImageBackground source=('../assets/my-background.png') resizeMode='cover' style={{flex: 1}}>
//If I change BackgroundColor to 'red' or anything like that, it works fine
//so I think the problem isn't related to styling properties
<Stack.Navigator screenOptions={{cardStyle: { BackgroundColor: 'transparent' } }}>
<Stack.Screen name='Screen1' component={Component1}/>
<Stack.Screen name='Screen2' component={Component2}/>
<Stack.Screen name='Screen3' component={Component3}/>
</Stack.Navigator>
</ImageBackground>
);
export default App() => (
<MyStackNavigator />
);
I've done the same thing in a DrawerNavigator inside my navigator component passing sceneContainerStyle: { backgroundColor: 'transparent' } }} and it actually works. It seems like my StackNavigator ain't rendering it's parent components correctly.
One of my StackNavigator's screens:
One of my DrawerNavigator's screens:
Both navigator's screens layout are wrapped in a transparent container View, so as you can see, the drawer screen is rendering background correctly but the stack screen isn't. Maybe I'm passing wrong props to my StackNavigator?
well with react-navigation 6 you can use the theming option to customize the look for the background to be transparent (Default is rgb(242,242,242)) use a NavigatorContainer to apply the theme
here is an answer that may help

Using React-native-picker-select headless component

I'm trying to use React-Native-Picker-Selects headless component for both iOS and Android. According to the docs found here:
you can pass children (such as a custom button or input) for the component to wrap (for both iOS and Android
Here is a sample of my code:
import React, { Component } from 'react';
import {
View,
Text,
} from 'react-native';
import RNPickerSelect from 'react-native-picker-select';
<View style={{flex:1}}>
<RNPickerSelect
placeholder={{}}
items={MyList}
onValueChange={(itemValue, itemIndex) => {
console.log('itemValue')
}}
style={{...pickerSelectStyles}}
>
<View style={{backgroundColor:'purple', flex:1, justifyContent:'center', alignItems:'center'}}>
<Text>
Test Text where I should be able to touch to get things to happen
</Text>
</View>
</RNPickerSelect>
const pickerSelectStyles = StyleSheet.create({
headlessAndroidContainer: {
flex:1
}
});
<View style={{height:height * 0.5}}>
<Text>test</Text>
</View>
</View>
const pickerSelectStyles = StyleSheet.create({
viewContainer: {
flex:1,
backgroundColor: 'purple',
},
headlessAndroidContainer: {
backgroundColor: 'purple',
flex:1
}
});
What I expect to happen is that on my screen I see two-section, half purple, and half white. The purple section has the text saying that things should happen, and the white section should have Tested. I should be able to tap anywhere on the purple section and my picker with MyList should come up.
This is working as expected on a simulator, but not on a real android device. on a real device, it seems that I'm able to tap around on the purple area, and the picker shows up very sporadically. Any assistance would be greatly appreciated!
Edit: Forgot to mention that this is specifically an android problem, it works on both real and simulated iPhones
Seems like having the RNPickerselect wrapped in a TouchableWithoutFeedback breaks it for some reason, once outside that tag it worked fine.
Adding the latest version (version 5.0) seems to fix this issue. The version I added was 4.4, and I added it to my project maybe 10 days ago. The newest version was released about a week ago, and seems to solve this problem.

How to resize TouchableOpacity according to the component present inside it?

I'm using TouchableOpacity to make a button as I'm learning react-native.
But the problem is, TouchableOpacity takes 100% width of the screen. But, I want to take the size/grow with the component present inside it.
How can I do it?
import React, { Component } from "react";
import { Text, TouchableOpacity } from "react-native";
export default class App extends Component {
render(){
return(
<TouchableOpacity
onPress={() => console.log("Pressed!")}
style={{ backgroundColor: "red" }}
>
<Text>Press me!</Text>
</TouchableOpacity>
);
}
When I decrease the width of the TouchableOpacity like 10 or 20, it automatically increases its height to fit the Text.
So, it possible for TouchableOpacity to grow with the size of component present inside it?
You can actually use alignSelf: 'flex-start' or 'flex-end' depending on which side you want to pin

How to add ripple effect when clicking Card in MUI

Is there a way I can add ripple effect to MUI Card component on click.
And I would also like to know, is it possible to make ripple effect to come on top of the content of Card component, rather that it showing as background.
I noticed that TouchRipple has been moved out of the internal directory.
It's now available in the ButtonBase folder.
Here is how I was able to add ripple effect by using the ButtonBase component -
Basically, you wrap your component, let's say <Card> inside the <ButtonBase> like so, and the ButtonBase takes care of the TouchRipple setting up for you -
<ButtonBase>
<Card>
....
</Card>
</ButtonBase>
Here is a Codesandbox link to working demo.
I know this is not the best way. You could directly use the TouchRipple/Ripple component, but I found this way to be very easy to use.
Hope this helps.
I can see this question was not answered, so I'll provide an up-to-date solution (writing this as material-ui is v. 0.18.7 (stable):
You need to import the ripple higher-order comp. (HOC) as:
import TouchRipple from '#material-ui/core/ButtonBase/TouchRipple';
Then you can wrap any component of you choice with TouchRipple, like:
<TouchRipple>
<div>
MY RIPPLING DIV
</div>
</TouchRipple>
Or, if you need a CSS class-based apporach, you can use materialize lib -> https://react-materialize.github.io/#/
In that case, it's as simple as adding a value to waves prop on a material-ui Button, like:
<Button waves='light'>EDIT ME<Icon left>save</Icon></Button>
2021 Update
The most idiomatic way to add the ripple effect when clicking the Card is using the CardActionArea. This component inherits the props of ButtonBase. It also changes the Card background color when hovered and focused (unlike ButtonBase):
<Card>
<CardActionArea>
<CardContent>
{...}
</CardContent>
</CardActionArea>
</Card>
The approach taken in #xiaofan2406 never worked for me, not to mention passing height, width and position seems easily breakable and might not be possible when using flexbox.
However I managed to make it work like:
<YourComponent>
<TouchRipple>
{children}
</TouchRipple>
</YourComponent>
Here is a Solution 2021 updated
simple You need wrap your custom components with component from material ui .
Then add style padding: 0 that solve.
Here I want my Image should react with ripple effect.
You can customize by wrapping with Grid and props container
import { Button } from "#material-ui/core";
function ImageCard(props){
return (
<Button style={{ padding: 0, borderRadius: "16px" }}>
{/*my custom component you can use any component even material ui component also*/}
<img
src={yourImageUrl}
alt="img"
style={{
height: 200,
width: 400,
borderRadius: "16px",//optional
}}
/>
</Button>
);
}
Using component attribute
Instead of wrapping, you can specify the component attribute as the desired component you want it to be. That is, for this use-case;
import ButtonBase from '#material-ui/core/ButtonBase';
...
<Card component = {ButtonBase}>
<CardContent>
...
</CardContent>
</Card>
If you have issues with height or width of the card, add the sx attribute;
<Card component={ButtonBase} sx={{height:'100%', width:'100%'}}>
...
</Card>
If ButtonBase messes up all other buttons on the page, it's better to use just the Button;
import Button from '#mui/material/Button';
...
<Card component = {Button}>
<CardContent>
...
</CardContent>
</Card>
Using MUI V5 (2022)
You can get the benefit of the component prop, use the <ButtonBase> component to get the ripple effect.
Create a React HOC or simply copy this code into a new file:
import React, { forwardRef } from 'react'
import { ButtonBase } from '#mui/material'
export default function WithTouchRipple(OriginalComponent) {
return (props) => {
const Wrapper = !props.component
? ButtonBase
: forwardRef((ButtonBaseProps, ref) => <ButtonBase component={props.component} {...ButtonBaseProps} ref={ref} />)
return <OriginalComponent {...props} component={Wrapper} />
}
}
Then use it as follows on any component you like:
import { Chip, Card, Stack } from '#mui/material'
import WithTouchRipple from '../WithTouchRipple'
const RippleChip = WithTouchRipple(Chip)
const RippleCard = WithTouchRipple(Card)
const RippleStack = WithTouchRipple(Stack)
<RippleChip component={Link} to={`/users/${id}`} {...chipProps} />
<RippleStack>...</RippleStack>
<RippleCard>...</RippleCard>
If you want the ripple effect to appear on the <Card> component, there is a built-in component for that called <CardActionArea>, and you can use it as follows:
<Card>
<CardActionArea>
<CardContent>
{...}
</CardContent>
</CardActionArea>
</Card>
The official api doesn't seem to support it.
But this is what I do, when I want to use material-ui ripple affect:
Use material-ui/internal/TouchRipple, have a look at its source code
Usage example:
<YourComponent>
<TouchRipple style={style}/>
{children}
</YourComponent>
You need to pass the inline style to specify its height, width and position that matches YourComponent's height, width and postion

Categories

Resources