React native Fixed header / footer iphone X - iphone

As a personal project to learn ReactNative, i am building an instagram like app (Fixed header, footer and scrollable content section). What would be a best practice to make this kind of layout?
The problem is that, in iPhone X this doesn't work quite well. If I use the SafeAreaView component i can get the Header section to work, but then I lose the ability to correctly position the footer. By using the following code:
render() {
const {width, height} = Dimensions.get('window');
return (
<View style={[{backgroundColor: '#F00'}]}>
<View style={{backgroundColor: '#AFD', height: 50}}>
<Text>Head</Text>
</View>
<View style={{backgroundColor: '#DFC', height: height-100}}>
<Text>Body</Text>
</View>
<View style={{backgroundColor: '#CDF', height: 50}}>
<Text>Toes</Text>
</View>
</View>
);
}
I get:
If I use the SafeAreaView component, it gets a bit better for the header but the footer loses the reference completely:
<SafeAreaView style={[{backgroundColor: '#F00'}]}>
<View style={{backgroundColor: '#AFD', height: 50}}>
<Text>Head</Text>
</View>
<View style={{backgroundColor: '#DFC', height: height-100}}>
<Text>Body</Text>
</View>
<View style={{backgroundColor: '#CDF', height: 50}}>
<Text>Footer</Text>
</View>
</SafeAreaView>
My last option was then to use the SafeAreaView for the header part, which then makes the header too small (the content gets clipped if i don't account for the extra height, which doesn't help so much)
<View style={[{backgroundColor: '#F00'}]}>
<SafeAreaView style={{backgroundColor: '#AFD', height: 50}}>
<Text>Head</Text>
</SafeAreaView>
<View style={{backgroundColor: '#DFC', height: height-100}}>
<Text>Body</Text>
</View>
<View style={{backgroundColor: '#CDF', height: 50}}>
<Text>Footer</Text>
</View>
</View>
So, what would be a best practice to achieve this layout? Also, is there any good resources for layouts in ReactNative besides the documentation?
thanks in advance!

Use https://github.com/miyabi/react-native-safe-area module. It's very easy to use and works as per requirement. Works well on different iOS versions, automatically adjusts on orientation change. You just have to addEventListener and all will be handled automatically.
Follow instructions from https://github.com/miyabi/react-native-safe-area#installation

Related

how to set fixed width of material-ui table cell to truncate content

I display a Table of users setup with infinite scroll. The first column contains the user name which varies in length. This makes the table jump in size as the list expands when scrolling down for more users. So I want to set a fixed width on that column and truncate the name column accordingly.
I tried to do it like but it doesn't work. The table cell adjust to the other cells and distributing the page width.
<Table>
<TableBody>
<TableRow>
<TableCell style={{ width: '20%' }}>
<Typography noWrap>SomeveeeeeeeeeeeeeryLoooooooooongNaaaaaame</Typography>
</TableCell>
</TableRow>
</TableBody>
</Table>
How do I achieve this?
Create an ellipsis style and use that on your Typography component.
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
ellipsis: {
maxWidth: 200, // percentage also works
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
},
});
...
const classes = useStyles();
<Table>
<TableBody>
<TableRow>
<TableCell>
<Typography className={classes.ellipsis}>
SomeveeeeeeeeeeeeeryLoooooooooongNaaaaaame
</Typography>
</TableCell>
</TableRow>
</TableBody>
</Table>
codesandbox

Classnames mismatch using Material-UI and NextJS

Using Intersection Observer API I'm trying to render a Material-UI Component by visibility on the viewport.
export default function Index() {
const [onScreen, theRef] = useOnScreen({
rootMargin: "-300px",
ssr: true
});
const classes = useStyles();
return (
<Container maxWidth="sm">
<DummyContainer />
<div
ref={theRef}
style={{
height: "100vh",
padding: "20px",
backgroundColor: "green",
transition: "all .5s ease-in"
}}
>
{onScreen && (
<Box className={classes.rootBox} my={16}>
<Typography variant="h2" gutterBottom>
Content Lazy using Intersection Observer
</Typography>
<Copyright />
</Box>
)}
</div>
<Box className={classes.rootBox} my={4}>
<Typography variant="h2" gutterBottom>
Content no lazy, why this Box loses margin?
</Typography>
<Typography gutterBottom>
If you request this page with JavaScript disabled, you will notice
that has been properly rendered in SSR
</Typography>
</Box>
</Container>
);
}
Basic stuff, onScreen is a toggled boolean using Intersection Observer
In order to be "SEO friendly" I'm using NextJS and I wanted this component to always be visible in SSR and conditional visible in CSR.
The problem arises during rehydration in CSR, it's seems that some classnames after the lazy component are recreated and I'm losing styling in second Box component.
I've created this CodeSandbox to have a look : https://codesandbox.io/s/nextjsmaterialuiclassnamemismatch-1j4oi
Is this a bug in MaterialUI, JSS? Or most probably I'm doing something wrong?

Disable react native classes on pressing a different class in the same group

I am completely new to react, Using TouchableHighlight, I have created a class,
import React, { Component } from "react";
import { Text, View, Image, TouchableHighlight } from "react-native";
export default class ChooseProComp extends Component {
render() {
return (
<TouchableHighlight
underlayColor="transparent"
onPress={this.props.onPress}
style={{ flex: 1 }}
>
<View
style={{
marginRight: this.props.mr,
borderRadius: 3,
backgroundColor: "#ffffff",
borderWidth: 0.7,
borderColor: "#e1e1e1",
}}
>
<View style={{ flexDirection: "row", padding: 8 }}>
<Image
style={{
width: 26,
height: 26
}}
source={this.props.typeImage}
/>
<Text
style={{
fontSize: 13,
alignSelf: "center",
marginLeft: 8,
color: "#737f8d"
}}
>
{this.props.type}
</Text>
</View>
</View>
</TouchableHighlight>
);
}
}
I have imported ChooseProComp class in a different component like this, I am not sure whether I have to add a custom method.
<View style={{ flexDirection: "row", marginBottom: 6 }}>
<ChooseProComp
mr={7}
typeImage={require("../../../Images/homescreen/typeicons/medical/medical.png")}
type="Medical"
onPress={() => this.renderType("Medical")
}
/>
<ChooseProComp
typeImage={require("../../../Images/homescreen/typeicons/dental/dental.png")}
type="Dental"
onPress={() => this.renderType("Dental")}
/>
</View>
<View style={{ flexDirection: "row", marginBottom: 6 }}>
<ChooseProComp
mr={7}
typeImage={require("../../../Images/homescreen/typeicons/homiopathi/homia.png")}
type="Homeopathy"
onPress={() => this.renderType("Homeopathy")}
/>
<ChooseProComp
typeImage={require("../../../Images/homescreen/typeicons/ayurveda/ayurveda.png")}
type="Ayurveda"
onPress={() => this.renderType("Ayurveda")}
/>
</View>
<View
style={{ flexDirection: "row", marginBottom: 6, marginBottom: 25 }}
>
<ChooseProComp
mr={7}
typeImage={require("../../../Images/homescreen/typeicons/yoga/yoga.png")}
type="Yogic science"
onPress={() => this.renderType("Yogic science")}
/>
<ChooseProComp
typeImage={require("../../../Images/homescreen/typeicons/unani/unani.png")}
type="Unani"
onPress={() => this.renderType("Unani")}
/>
</View>
So when I select a particular type, like Medical, I want to disable the ChooseProComp classes of other types. Please help me with this. Other types opacity needs to be decreased as well.
Since it seems you just want one item (<ChooseProComp>) to be selected, I suggest you to simply handle the selected one in your main component state, which at the beginning will be undefined:
state = {
selected: undefined
};
Then define onPress function of each <ChooseProComp> like:
onPress={() => {
this.renderType("Medical"); // I don't know how this works so I won't modify it
if(!this.state.selected){ // if the state is undefined, then set it!
this.setState({
selected: "Medical"
})
}
}
Then, again for each <ChooseProComp> pass a prop disabled like:
<ChooseProComp
...
disabled={this.state.selected && this.state.selected !== 'Medical'}
/>
So, in <ChooseProComp> component (class) you can use it in <TouchableHighlight>:
<TouchableHighlight
underlayColor="transparent"
onPress={this.props.onPress}
style={{ flex: 1 }}
disabled={this.props.disabled}
>
Let me know if this fits your question, or I've misunderstood, or it's not clear enough!

How to make something like this in material ui react?

How can i make this in material ui react?
The main problem i have is i don't know how to make the right part with the refresh icon.
This question is kinds an amateur question. But I can give you little insights how you can start with little basics and you can later make it stateful component.
const styles = theme => ({
margin: {
margin: theme.spacing.unit,
},
roundBorder : {
borderRadius: '25px',
borderColor: '#80bdff',
border: '1px solid #ced4da',
}
});
function App(props) {
const { classes } = props;
return (
<div>
<div className={classes.margin}>
<Grid container spacing={8} alignItems="flex-end">
<Grid item>
<TextField className={classes.roundBorder} id="input-with-icon-grid" label="With a grid" />
</Grid>
<Grid item>
<AccountCircle />
</Grid>
</Grid>
</div>
</div>
);
}
This will create something like this:
Check this sample which has searching with icon, just align icon to the right:
https://codesandbox.io/s/material-demo-jhy9f

Adjusting the gap between svg icon and text on Material-UI's List component

I've been trying to figure out how to lessen the gap using css with no luck. I created the style object and used leftPosition key but the result was not the one I expected. I was expecting that the text is the only thing that will move. However, if you look at the screenshot specifically the first menu, the icon also moved. What I'd like to achieve is reduce the gap between the svn icon and the text.
import React from 'react';
import List from 'material-ui/lib/lists/list';
import ListItem from 'material-ui/lib/lists/list-item';
import ActionGrade from 'material-ui/lib/svg-icons/action/grade';
import ActionInfo from 'material-ui/lib/svg-icons/action/info';
import ContentInbox from 'material-ui/lib/svg-icons/content/inbox';
import ContentDrafts from 'material-ui/lib/svg-icons/content/drafts';
import ContentSend from 'material-ui/lib/svg-icons/content/send';
import Divider from 'material-ui/lib/divider';
import Assignment from 'material-ui/lib/svg-icons/action/assignment';
import Settings from 'material-ui/lib/svg-icons/action/settings';
import ManageDB from 'material-ui/lib/svg-icons/content/unarchive';
const style = {
menu: {
marginRight: 32,
marginBottom: 32,
float: 'left',
position: 'relative',
zIndex: 0,
width: 235,
},
rightIcon: {
textAlign: 'center',
lineHeight: '24px',
},
width: {
width: 235
},
leftPosition: {
left: 50
}
};
const LeftNavigation = () => (
<div>
<List>
<ListItem style={style.leftPosition} primaryText="Logs" leftIcon={<Assignment />} />
<ListItem primaryText="Manage DB" leftIcon={<ManageDB style={style.gap}/>} />
<ListItem primaryText="Top Issues" leftIcon={<ContentSend style={style.gap}/>} />
<ListItem primaryText="Settings" leftIcon={<Settings style={style.gap}/>} />
<ListItem primaryText="Logout" leftIcon={<ContentInbox style={style.gap}/>} />
</List>
<Divider />
<List>
<ListItem primaryText="All mail" rightIcon={<ActionInfo />} />
<ListItem primaryText="Trash" rightIcon={<ActionInfo />} />
<ListItem primaryText="Spam" rightIcon={<ActionInfo />} />
<ListItem primaryText="Follow up" rightIcon={<ActionInfo />} />
</List>
</div>
);
export default LeftNavigation;
The accepted solution didn't work for me. Here is what I ended up doing after exploring the DOM.
const useStyles = makeStyles((theme) => ({
icon: {
minWidth: '30px',
}
}));
and then apply this class for the ListItemIcon as:
<ListItemIcon className={classes.icon}> <HelpOutlineIcon/> </ListItemIcon>
Hope it helps someone save time.
You can add style in ListItemIcon.
<ListItemIcon style={{minWidth: '40px'}} >
This is what worked for me. I set this in my global css file.
.MuiListItemIcon-root {
min-width: 40px !important;
}
If you want to do it globally use overrides in createMuiTheme
const theme = createMuiTheme({
overrides: {
MuiListItemIcon: {
root: {
minWidth: 40,
},
},
},
})
Note:
If you're using MUI version 5 then locate createTheme instead of createMuiTheme
This is my 2¢:
<ListItemText primary={<div style={{ margin: -25, marginTop: -7, color: 'white', fontSize: 11 }}>Your text here</div>} />
Adjusting margin (n.b., it's a negative number) and the top margin you can align the icon (on the left) with your text
You can also use sx prop instead of style, if you want access to the theme object, e.g.:
<ListItemIcon sx={{minWidth: (theme) => theme.spacing(4)}}>
This is only applicable to Mui 1.x.x. For later versions, please see responses to this answer below.
The ListItem renders a div called innerDiv with 72px left/right padding to render the left/right icon and label with sufficient space. You should try this in the Style -
<ListItem innerDivStyle={{paddingLeft: 60}} primaryText="Logs" leftIcon={<Assignment />} />
Replace 60 with whatever pleases you.
Just information for #Adam Mańkowski 's answer.
In MUI v5.5, you can config your theme like this.
createTheme({
components: {
MuiListItemIcon: {
styleOverrides: {
root: {
minWidth: 0
}
}
}
}
});