Element with absolute position is cut off by other component - react-native

I have a toolbar in my RN app. That toolbar has a button that is oversized on purpose and is overflowing from the component.
The oversized button is covered by an other component in the same page.
touchable:{
backgroundColor:'#3d3d3d',
borderRadius:27.5,
position:'absolute',
left:width/2 -25,
bottom:10,
alignItems:'center',
borderColor:'black',
width:55,
height:55,
justifyContent:'center',
}
Mark up:
render() {
return (
<View style={{flex: 1}}>
<View style={{position:'absolute', width:42,height:42,left:20,top:(height-42)/3,zIndex:3}}>
<Image style={{}} source={require('./Images/Ellipse 36.png')} />
<Image style={{position:'absolute',top:14,left:14}} source={require('./Images/Asset 65.png')} />
</View>
<View style={{position:'absolute', width:42,height:42,right:20,top:(height-42)/3,zIndex:3}}>
<Image style={{}} source={require('./Images/Ellipse 36.png')} />
<Image style={{position:'absolute',top:10,left:12}} source={require('./Images/Asset 66.png')} />
</View>
<View><TopToolbar text='Swipe' navigator={this.props.navigator} user={this.props.user}/></View>
<ScrollView style={{zIndex:1,}}><Inders style={{flex: 1}} navigator={this.props.navigator} credentials={this.props.credentials}/></ScrollView>
<View style={{zIndex:0,}}><BottomToolbar user={this.props.user} navigator={this.props.navigator} credentials={this.props.credentials}/></View>
</View>
)
}
Where Inders is a component.
I tried changing the order of the components but it didn't work.
What is the way to make a button "float" from another component?

Open inspector in the Dev tools menu and find out who cut your component, I also like to set backgroundColor to see their position, it make solve this type of bugs mack more easy.

The solution is to wrap the toolbar in another View, so that the new View is the parent of the element that you want to "float".

Related

React Navigation Top Bar Getting Same Height (NOT) dependent on its own components

Looking at this example from React Navigation website, between Chat and Contacts, the heights are independent of each other. However, When I tried to implement a top bar, the heights are the same. It takes the height of which ever tab has the most content in it.
But in the example, you can see in Contacts that there may be more contacts where you can scroll, and in Chat, the input field is at the bottom, making it look like that's where it stops.
Here's a screen shot from the example:
Chat tab
Contacts tab
Here's some of my code and what I'm experiencing:
<View style={{backgroundColor: 'orange'}}>
{!loading &&
!loadingProfileInfo &&
typeof data.infoByUser !== 'undefined' && (
<FlatList
data={data.infoByUser}
ListHeaderComponent={
<View>
<UserInfo />
<Tab.Navigator>
<Tab.Screen
name="Test"
component={TestComponent} />
<Tab.Screen
name="New Tab"
component={NewTabComponent}
/>
</Tab.Navigator>
</View>
}
numColumns={2}
renderItem={({item}) => (
<View>
// ...
</View>
)}
keyExtractor={item => item._id}
/>
)}
</View>
TestComponent
<View style={{backgroundColor: 'grey'}}>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
<View>
<Text>Test Test</Text>
</View>
</View>
NewTabComponent
<View style={{backgroundColor: 'red'}}>
<Text>new tab</Text>
</View>
Notice how the New Tab has a big gap between the red and the orange, that's from the Test tab's height.
You are rendering your entire navigator as the FlatList 'header'. You shouldn't even use Flatlist in this component. Each screen has a different number of items, and should have its own Flatlist.
To fix this:
Remove the FlatList from your main component (with backgroundColor: 'orange'), and just render the Tab Navigator in that render function.
Inside of TestComponent and NewTabComponent, render a ScrollView (or FlatList) if you need it.
All screens (TestComponent and NewTabComponent) should have a height: '100%' or flex: 1 if you want all screens to take all up all the space of the screen, even when its real height is less than the screen height.
To have heights according to the content inside the particular tab, use Scrollview inside each tab screen. Thank me later if this works perfectly. :)
import * as React from "react";
import { ScrollView, Text, View } from "react-native";
import { createMaterialTopTabNavigator } from "#react-navigation/material-top-tabs";
function Screen1() {
return (
<ScrollView>
<View style={{ flex: 1, alignItems: "center" }}>
<Text style={{ padding: 10 }}>Screen1 </Text>
</View>
</ScrollView>
);
}
function Screen2() {
return (
<ScrollView>
<View style={{ flex: 1, alignItems: "center" }}>
<Text style={{ padding: 10 }}>Screen2</Text>
</View>
</ScrollView>
);
}
function Screen3() {
return (
<ScrollView>
<View style={{ flex: 1, alignItems: "center" }}>
<Text style={{ padding: 10 }}>Screen3 </Text>
</View>
</ScrollView>
);
}
const Tab = createMaterialTopTabNavigator();
export default function TopBarNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name="Screen1" component={Screen1} />
<Tab.Screen name="Screen2" component={Screen2} />
<Tab.Screen name="Screen3" component={Screen3} />
</Tab.Navigator>
);
}
I'm having no idea why you're rendering it inside FlatList as it also inherits props from Scroll View.
<View style={{backgroundColor: 'orange'}}>
<Tab.Navigator>
<Tab.Screen
name="Test"
component={TestComponent} />
<Tab.Screen
name="New Tab"
component={NewTabComponent}
/>
</Tab.Navigator>
</View>
and move the FlatList and other business logics inside the TestComponent or the NewTabComponent.
The point is don't render Tabs inside ScrollView or FlatList or SectionList as they both inherit the props of ScrollView.
After a long research I found out that your problem is because react-native-tab-view (which is used by material-tob-tabs), has this code :
_defineProperty(this, "handleLayout", e => {
const {
height,
width
} = e.nativeEvent.layout;
if (this.state.layout.width === width && this.state.layout.height === height) {
return;
}
this.setState({
layout: {
height,
width
}
});
With option lazy={true} , and using the "New Tab" component on first tab and "Test" on second, you get the right height until you change the tab. When you press on "Test" the layout changes so the height is bigger. After changing tab the height does't change anymore because the layout stays the same ("New Tab" fits perfectly in the bigger height) and doesn't trigger handleLayout from react-native-tab-view.
Hope you can find a way to change the layout again when you change tabs.

keyboard avoid view not enough height

keyboard pushes "CreateComment" component to top but not enough height ,it's still hides the "CreateComment" component which it includes "InputText"
<ScrollView >
....
</ScrollView>
<KeyboardAvoidingView behavior='position'>
<View style={styles.footer}>
<CreateComment GetComments={()=>this.GetComments()}
roomId={this.state.postID} />
</View>
</KeyboardAvoidingView>
</View>
and here is stlye:
container: {
flex: 1,
},
footer :{
position:'absolute',
bottom:0 },
...
You can change the height you want to specify yourself.
You can use offset
Example
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={100}
>

how to overlap one view on another view in react native android

I want to put Search Input between two View border,but half input hides behind another View.
Click Here To Show Image.
There are two views. One View's backgroundColor is purple and another view's backgroundColor is white.And half Input type is hide behind another view.
<Container>
<Header style={{ backgroundColor: "#635DB7" }}>
<Left>
<Button
transparent
onPress={() => this.props.navigation.navigate("DrawerOpen")}
>
<Icon name="ios-menu" />
</Button>
</Left>
<Right />
</Header>
<View style={{flex:1,zIndex:2}}>
<View style={{height:192,backgroundColor: "#635DB7"}}>
<View style={{position:'absolute',opacity: 1,flex:1,flexDirection:"row",marginTop:160}}>
<Input style={{flexDirection:"row",borderRadius:20,marginLeft:30,marginRight:30,backgroundColor:"#434353", zIndex: 2,opacity: 1}} placeholder="Search" />
</View>
</View>
<View style={{height:448,backgroundColor: "#ffffff",zIndex:1}}>
</View>
</View>
</Container>
Try to put the search bar as a last item in the container, and with absolute position. If that does not work, then you might have hit a bug in RN android, which does not support overflow:
https://github.com/facebook/react-native/issues/6802
https://github.com/facebook/react-native/issues/3198

React native: How to use Flatlist with other views in a component

I am using "react-native": "^0.50.4", and this is how componentrender looks like:
render(){
return(
<View style={{flex: 1}}>
<View>
....
</View>
<FlatlistComponent />
</View>
);
}
The above FlatlistComponent renders a list, except the last item is partially shown/pushed down, this is because the View above the flatlist, how do I go about this ?
If the FlatList disappears when you add a style of flex: 1, you must continue moving up the hierarchy of elements, adding flex, until the FlatList finally appears.
I guess the View component other then the flat list is taking up the whole space of the flex 1. Flatlist being scrollable it is supposed to go down.
Try assigning separate flex values to the child components.
render(){
return(
<View style={{flex: 1}}>
<View style={{flex: 1}>
<View>
....
</View>
</View>
<View style={{flex: 3}>
<FlatlistComponent />
</View>
</View>
);
}

React Native FlatList last item visibility issue

I am fetching products list and then displaying using a FlatList, my list contains 5 items and as you can see FlatList row height is variable because of varying description text. So the issue is my last item card is not completely visible maybe this is some kind of flat list issue or layout issue. Any help would be highly appreciated
renderProducts() {
if (this.props.loading === true) {
return (
<View style={Styles.spinnerStyle}>
<ActivityIndicator size='large' />
</View>
);
}
return (
<FlatList
data={this.props.myProducts}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<Card
title={item.title}
image={{
uri: item.image !== null ? item.image.src :'../resImage.jpg'
}}
>
<Text style={{ marginBottom: 10 }}>
{item.body_html}
</Text>
<Button
icon={{ name: 'code' }}
backgroundColor='#03A9F4'
fontFamily='Lato'
buttonStyle={{ borderRadius: 0, marginLeft: 0, marginRight: 0, marginBottom: 0 }}
title='VIEW NOW'
/>
</Card>
)}
/>
);
}
render() {
return (
<View>
<View style={Styles.viewStyle}>
<Text style {Styles.textStyle}>ProductsList</Text>
</View>
{
this.renderProducts()
}
</View>
);
}
Set bottom padding to the <FlatList> content container:
<FlatList
contentContainerStyle={{ paddingBottom: 20 }}
/>
Add {flex: 1} to the View tag housing the Flatlist component.
In my case,
const App = () => {
return (
<Provider store={createStore(reducers)}>
<View style={{ flex: 1 }}>
<Header headerText={'My App'} />
<ScreenTabs /> // this is my content with FlatList
</View>
</Provider>
);
};
export default App;
Just wrap it in a view with flex:1
<ParentView style={{flex:1}
<View style={{flex:1}}>
// Your flatlist
<View>
</ParentView>
Also, note that the each parent of this "View" in which Flatlist is wrapped must also be a View with Flex of 1. Otherwise, that your flatlist wont be visible.
use contentContainerStyle props of FlatList
<FlatList contentContainerStyle={{ paddingBottom: 20}} />
Latest update:
react-navigation has a SafeAreaView with an option to not show that bottom area.
import { SafeAreaView } from 'react-navigation';
<SafeAreaView forceInset={{ bottom: 'never' }} />
Old response below:
You can't see your list with flex: 1 because flex: 1 will grow the component to the parent. If the parent doesn't have flex: 1, it won't stretch to its parent or the screen. Keep in mind, however, that flex: 1 with a SafeAreaView will cause the bottom safe area to show. This will look bad if your SafeAreaView backgroundColor is a different color from your list's back ground.
My old workaround was to add an item to the bottom of the array of items, but I'm still exploring how to scroll past/under the bottom safe area margin with a FlatList (which is how I found this post to begin with).
Update: Using ListFooterComponent you can create even a plain white "footer" with height and/or a margin
For example (I wouldn't directly copy and paste this if I were you... there's surely a better way to detect bezel-less iPhones, especially in 2019 when we have more than one)
ListFooterComponent={<View style={{ height: 0, marginBottom: 90 }}></View>}
This is how I would do it, using the iPhoneX's height for now. But it's not future-proof since the conditional will need to be updated every time a new iPhone with no bezels comes out:
ListFooterComponent={<View style={{ height: 0, marginBottom: noBezels ? 90 : 0 }}></View>}
Or you could just always have some spacing at the bottom, like a loading gif, a message... whatever.
UPDATE 2:
I found out about react-native-device-info which has a hasNotch() method. I find that useful for styling for iPhones with no bezels by combining hasNotch() with Platform.OS === 'ios'
You can try this solution
For Vertical FlatList:
<FlatList
ListFooterComponent={<View />}
ListFooterComponentStyle={{height:200}}
/>
For Horizontal FlatList:
<FlatList
contentContainerStyle={{paddingRight:40}}
/>
For IOS issues you can apply some IOS specific props:
<FlatList
// ...
contentInset={{top: 0, bottom: 20, left: 0, right: 0}}
contentInsetAdjustmentBehavior="automatic"
// ...
/>
The solution with contentContainerStyle padding didn't seem the best overall for fixing the safe area IOS issues in my case.
Work very well for me
<FlatList
data={data}
contentContainerStyle={{ paddingBottom: 30 }}
style={{height: '95%'}}
renderItem={({ item, index }) => (
<ListItem item={item} onPress={() => handlePress(item, index)} />
)}
/>
Make use of the contentContainerStyle prop in the flatlist
<FlatList contentContainerStyle={{paddingBottom: 10}} />
For dynamic flatlist, you can assign height to the parent view. I resolved it with same.
<View style={{height:'80%'}}>
<Flatlist
extraData={data}
data={data}
renderItem={renderItem}
/>
</View>
I had the same issue and found the solution. To fix the issue just add style={{flex: 1}} for each View element who is a parent for FlatList.
See updated code below.
render() {
return (
<View style={{flex: 1}}> // Here you should add style as {flex: 1}
<View style={Styles.viewStyle}>
<Text style={Styles.textStyle}>ProductsList</Text>
</View>
{ this.renderProducts() }
</View>
);
}
This worked for me.
<View style={{flex: 1}}>
<FlatList
style={{flex: 1}}
data={data}
renderItem={({item}) => (
<ListItem item={item} onPress={() => handlePress(item)} />
)}
/>
</View>
#krish solution is great for the fixed-size list items, however as
#Neeraj Sewani said, it may not be suitable for dynamic size list items.
so you can fix the issue like this -in case direction is column -:
<View style={{height: '90%'}}>
<FlatList/>
</View>
Otherwise, -in case direction is row -:
<View style={{height: '90%', width:'90%'}}>
<FlatList/>
</View>
I was seeing this same problem in our Android + iOS React Native hybrid app. We embed the FlatList component within our native UIs inside a Fragment in Android and we were unable to scroll to the last item in the list, even though the scroll indicator would show that there was more to scroll, the ScrollView would simply not scroll further. I tried all the combinations of using a wrapping <View style={{flex:1}}> to wrap the FlatList as well as using contentContainerStyle={{flexGrow:1}} on the FlatList without success. Pursuing the clue further it turned out that the FlatList needs an absolute, predefined height on Android to allow scroll to the bottom - it works just fine on iOS but on Android using match_parent wasn't going to work. Since we need to support all types of devices, phone and tablet too, it wasn't possible to pre-define an absolute height either.
To fix this, I made a custom FrameLayout subclass to house the ReactRootView's fragment, which overrides onLayout() to ignore the child view measurements, forcing the views to have the exact dimensions of the FrameLayout, somewhat like so in Kotlin:
class StretchFrameLayout #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
for (child in children){
if (child.visibility == View.GONE) continue
child.updateLayoutParams {
this.width = measuredWidth
this.height = measuredHeight
}
if (needsRelayout){
handler.postDelayed({child.requestLayout()},1)
}
}
super.onLayout(changed, left, top, right, bottom)
}
}
This work very well in my case:
<FlatList
data={todos}
contentContainerStyle={{ height: '100%' }}
renderItem={({ item }) => <Todos items={item} pressed={pressed} />}
/>
I've solved it doing contentInset={{ bottom: data.length * itemStyle.height, }} with itemStyle.height being 50 worked fine.