Unwanted bottom margin in KeyboardAwareScrollView- ReactNative - react-native

I'm using following style for the loading view(Last child).
overlay: {
flex: 1,
zIndex:2,
position: 'absolute',
height:HEIGHT,//(HEIGHT & WIDTH obtained from Dimensions)
width:WIDTH,
backgroundColor: 'black',
opacity: 0.5,
alignItems:'center',
justifyContent:'center',
}
This view should cover whole screen. But at bottom some margin is there.
How to remove it?
SOLUTION: Actually problem with KeyboardAwareScrollView. I solved it by giving contentContainerStyle={{flex:1}}
<KeyboardAwareScrollView
style={styles.scrollView}
resetScrollToCoords={{ x: 0, y: 0 }}
contentContainerStyle={{flex:1}}
scrollEnabled={true}>
//All children
<LoadingView style={styles.overlay}/>
</KeyboardAwareScrollView>

Related

React-native: transparent view over ScrollView

I'm having problems setting transparency for a View that is outside of the ScrollView. I'm using Expo. The idea is that when you scroll the long scrollview content, you should just about to see it behind the bottom view. I've tried the opacity property as well as setting the background color using rgba(x,x,x, 0.5) with no luck. It looks like anything outside the Scrollview is totally opaque in relation to the scrollview content behind it.
Basic Code (the link to the snack is below):
export default function App() {
return (
<View style={styles.container}>
<ScrollView>
<View style={styles.transparentWrapper}>
<Text style={styles.textElement}>This is some text wrapped in a transparent View</Text>
</View>
<Text style={styles.paragraph}>
Lorem....
</Text>
<Text style={styles.paragraph}>
Lorem ...
</Text>
</ScrollView>
<View style={styles.bottomPart}>
<Text style={styles.textElement}>This is some text. Its wrapping view is transparent but I cannot see the lorem text underneath it.</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
},
paragraph: {
fontSize: 30,
marginBottom: 15,
},
textElement: {
color: 'blue',
},
transparentWrapper: {
position: 'absolute',
height: 100,
justifyContent: 'center',
top: 450,
left: 50,
backgroundColor: 'transparent',
zIndex: 999,
},
bottomPart: {
height: 50,
backgroundColor: 'transparent',
}
});
Full snack is here:
https://snack.expo.dev/#wastelandtime/scrollview-transparency
Here's an expected outcome. The top blue text is wrapped in a transparent view (and this is what it's supposed to look like) it's not a problem as it's within the ScrollView.
The bottom blue text does not seem to honour any transparency in terms of the scroll content behind it (I'd like just to see the blue text with complete transparency on the wrapping View.
it can be achieved without position: 'absolute', with negative margin in this way,
bottomPart: {
height: 50,
backgroundColor: 'transparent',
marginTop: -50, // add this
}
using negative top margin the text can be pushed upwards
snack link here https://snack.expo.dev/CJBbhSCzg
Setting bottomPart position to absolute and bottom: 0
bottomPart: {
height: 50,
backgroundColor: 'transparent',
position: 'absolute',
bottom: 0
}
You should get something like this.
You may also want to add marginBottom: 50, to the last element inside the ScrollView if you'll put a solid element inside the bottom part.

How do you vertically and horizontally center a View with respect to another View that is at a higher zIndex (React Native)?

Image of what I am envisioning
I'm trying to add a center tick mark to a slider.
Is it possible to vertically and horizontally center View 1 with respect to View 2 and at the same time render View 2 above View 1 (using zIndex)? I can accomplish this by placing View 1 below View 2 in the Y direction and set the margin of View 1 so it appears underneath View 2 (in the Z direction). Is that the correct way to do this?
Accomplishing this by fiddling with the margins seems like it could cause problems on different size screens.
Try giving view1 and view2 absolute positions, and place them in a parent container that centers vertically and horizontally. This will allow them to overlap without having to play with margin, and will naturally place the view2 on top of view1 without having to use zIndex
export default function App() {
return (
<View style={styles.container}>
<View style={styles.specialContainer}>
<View style={styles.tall}/>
<View style={styles.long}/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ecf0f1',
padding: 8,
},
specialContainer:{
width:300,
aspectRatio:1,
backgroundColor:'pink',
alignItems:'center',
justifyContent:'center'
},
long:{
position:'absolute',
backgroundColor:'purple',
width:'60%',
height:24,
// alignSelf:'center'
},
tall:{
position:'absolute',
backgroundColor:'green',
height:'60%',
width:24,
// alignSelf:'center',
}
});
Try it out here
You can surround the Views with a parent View like so:
<View style={{ width: '100%', justifyContent: 'center', alignItem: 'center' }}>
//horizontal
<View style={{ zIndex: 1, elevation: 1, width: '100%', height: '20'% }}></View>
//vertical
<View style={{ zIndex: 0, elevation: 0, height: '100%', width: '20%' }}></View>
</View>
This will adjust dynamically depending on screen size since all height and width values are set using percentages.

How do I position the callout with a fixed position in React Native Maps?

I'm trying to position the callout at the bottom of the screen and have it fixed to this position even though the map is moving? Has anyone had any luck in achieving this with React Native Maps?
All my attempts have not fixed the callout to the bottom of the screen.
The only way I have found is to avoid using the callout component provided by react-native-maps.
Here is the code for the callout:
<Callout
tooltip
style={styles.itemContainer}
>
<CalloutSubview
style={styles.button}
onPress={closeCallout}
>
<Ionicons name="ios-close-circle" size={30} style={styles.icon} />
</CalloutSubview>
<SemiBoldHeadline
fontSize={18}
text={title}
marginTop={0}
marginBottom={4}
marginRight={30}
/>
<BodyText
fontSize={14}
lineHeight={18}
marginRight={30}
>
{editedString}
</BodyText>
<View style={styles.inlineContainer}>
<CalloutSubview onPress={() => RouteService.openMaps(coordinates.latitude, coordinates.longitude, title)}>
<SmallDirectionsButton />
</CalloutSubview>
<CalloutSubview onPress={readMoreFunction}>
<ReadMoreButton
text={'Read More'}
/>
</CalloutSubview>
</View>
</Callout>
Here is the styling of the callout:
const styles = StyleSheet.create({
itemContainer: {
borderRadius: 5,
borderWidth: 1,
borderColor: Colors.borderColor,
width: Layout.window.width - 100,
backgroundColor: Colors.white,
padding: 20,
paddingRight: 25
},
inlineContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
},
button: {
position: 'absolute',
top: 0,
right: 0,
paddingLeft: 10,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 30,
zIndex: 10,
},
icon: {
color: Colors.almostBlack,
opacity: 0.5
}
});
If you need to render custom react components "statically" above the map you shouldn't build it with using the map's callout component. Instead, create a view and position it absolutely above the map component:
<>
<Map .../>
<View style={{ position: "absolute", bottom: "20"}}>
{/* Your custom view content goes here*/}
</View>
</>
The callout components are just build to be used directly within the map's context and are expected to move when the map moves.

Responsive React-native-web layout

I'm trying to create a dashboard layout from a react-native project. The idea is to keep most of the code similar for Android, iOS and Web only the layout or navigation style will change. But I find making this type of layout in web is easy but to make it responsive without re-rendering is difficult.
I have achieved this by manually calculating the windows heigh and width by following the code
Dimensions.get('window').width
Dimensions.get('window').height
and by eventListener keep updating the state so that it re-renders the whole page again and again.
Dimensions.addEventListener("change", this.updateScreen);
Is there a way I can simply use some % value to fill up the screen. Right now if I use % it squeezed to a child View size. I even tried flex:1 with alignSelf:stretch, alignItem:stretch, width:'100%' etc but no luck.
For a while, let's talk about center row (image attached) it contain 3 columns. I want left and right block (Menu & Call to Action) to be 300px each. Now if I'm on 1000px width monitor my Content block should be (1000 - (300+300)) 400px. if monitor is 1200px then Content block will be (1200 - (300+300)) 600px.
I hope this doesn't come too late.
<View style={{ flex: 1 }}>
<View style={{ height: 100, backgroundColor: 'red' }} />
<View style={{ flex: 1, backgroundColor: 'gray', flexDirection: 'row' }}>
<View style={{ width: 100, backgroundColor: 'green' }} />
<View style={{ flex: 1, backgroundColor: 'blue' }} />
<View style={{ width: 100, backgroundColor: 'green' }} />
</View>
<View style={{ height: 100, backgroundColor: 'red' }} />
</View>
This is the result from the above code.
You don't need to do percentage calculations at all; just structure it in 2 layers of flex layout.
For the components that should not stretch, state their width. For the rest, specify the flex value.
If you insist on using 1 layer to handle it all, then we shall discuss again.
Cheers.
I made this exactly for the same reasons:
https://www.npmjs.com/package/react-native-animated-layout
Demos:
Expo snack: https://snack.expo.dev/#mehmetkaplan/react-native-animated-layout
Web demo: https://mehmetkaplan.github.io/react-native-animated-layout/
It takes layouts as inputs and using the Width / Height ratio of the screen, decides which layout to use.
And within each layout, you define top, right, bottom, left of each screen using the coordinates between 0 and 1. (Because browser resizing changes the coordinates of each View and you want views to stay exact relative places.)
import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';
import ReactNativeAnimatedLayout from 'react-native-animated-layout';
export default function App() {
const [rerender, setRerender] = useState(0);
const redView = <View style={{ backgroundColor: 'red', height: '100%', width: '100%', }}><Text>{"I am the red view"}</Text></View>;
const greenView = <View style={{ backgroundColor: 'green', height: '100%', width: '100%', overflow: 'hidden'}}>
<Text>{"I am the green view and my contents overflow. Because of the overflow prop, the over-flown content is hidden."}</Text><Text>{"0"}</Text><Text>{"1"}</Text><Text>{"2"}</Text><Text>{"3"}</Text><Text>{"4"}</Text><Text>{"5"}</Text><Text>{"6"}</Text><Text>{"7"}</Text><Text>{"8"}</Text><Text>{"9"}</Text><Text>{"10"}</Text><Text>{"11"}</Text><Text>{"12"}</Text><Text>{"13"}</Text><Text>{"14"}</Text><Text>{"15"}</Text><Text>{"16"}</Text><Text>{"17"}</Text><Text>{"18"}</Text><Text>{"19"}</Text><Text>{"20"}</Text><Text>{"21"}</Text><Text>{"22"}</Text><Text>{"23"}</Text><Text>{"24"}</Text><Text>{"25"}</Text><Text>{"26"}</Text><Text>{"27"}</Text><Text>{"28"}</Text><Text>{"29"}</Text>
</View>;
const blueView = <View style={{ backgroundColor: 'blue', height: '100%', width: '100%', }}><Text>{"I am the blue view"}</Text></View>;
const layouts = [
{
validAfterWHRatio: 0,
validBeforeWHRatio: 0.9,
views: [
{ top: 0, bottom: 0.5, left: 0, right: 1, children: redView },
{ top: 0.75, bottom: 1, left: 0, right: 1, children: blueView },
{ top: 0.5, bottom: 0.75, left: 0, right: 1, children: greenView },
]
},
{
validAfterWHRatio: 1 / 0.62,
validBeforeWHRatio: 999, // infinity
views: [
{ top: 0, bottom: 1, left: 0, right: 0.5, children: redView },
{ top: 0.5, bottom: 1, left: 0.5, right: 1, children: blueView },
{ top: 0, bottom: 0.5, left: 0.5, right: 1, children: greenView },
]
},
{
defaultFlag: true,
views: [
{ top: 0.16, bottom: 0.84, left: 0.16, right: 0.5, children: redView },
{ top: 0.50, bottom: 0.84, left: 0.5, right: 0.84, children: blueView },
{ top: 0.16, bottom: 0.50, left: 0.5, right: 0.84, children: greenView },
]
},
];
useEffect(() => {
let nextRerender = rerender + 1;
setRerender(nextRerender);
}, []); // when we want to re-render
return <ReactNativeAnimatedLayout
layouts={layouts}
rerender={rerender}
/>;
}
Note: This approach may be useful especially for PWAs. If you need to use scroll bars, they should be inside one of the views, probably "the" content view.

Can we set only one side shadow of View in React Native?

As the title saying, how can we set only one side shadow of View in React Native, or hide any side shadow?
What I want is showing the only one side shadow, any solutions?
Use this
const style = {
shadowColor: "#000000",
shadowOffset: { width: 0, height: 2 }, // change this for more shadow
shadowOpacity: 0.4,
shadowRadius: 6,
}
For example:
shadowOffset: { width: 0, height: 10 } shadows place only in bottom of View
shadowOffset: { width: 0, height: -10 } shadows place only in top of View
shadowOffset: { width: 10, height: 0 } shadows place only in right of View
shadowOffset: { width: -10, height: 10 } shadows place only in left of View
I have implemented it by two ways:
1.Using react-native-linear-gradient Plugin:
<LinearGradient start={{ x: 1, y: 0 }} end={{ x: 1, y: 1 }} colors={['#e4e2e4', '#FFF']} style={{height:8}} ></LinearGradient>
2.Without using Plugin:
<View style={{height:1,backgroundColor:'#e9e8e9'}} ></View>
<View style={{height:1,backgroundColor:'#e4e2e4'}} ></View>
<View style={{height:1,backgroundColor:'#efeeef'}} ></View>
<View style={{height:1,backgroundColor:'#f5f5f5'}} ></View>
<View style={{height:1,backgroundColor:'#fafafa'}} ></View>
<View style={{height:1,backgroundColor:'#fdfdfd'}} ></View>
<View style={{height:1,backgroundColor:'#fefefe'}} ></View>
<View style={{height:1,backgroundColor:'#fff'}} ></View>
Yes, You can make your shadow of your own view using like this code:
<View style={{borderTopColor:'#ebebeb',borderTopWidth:1,borderBottomWidth:5,borderRightWidth:2,borderLeftWidth:2,borderColor:'#bcbaba',}}>
</View>
This help me pls use this according your use..