How to calculate position of context menu? - react-native-popup-menu

The context menu is far lower than it should be. I attempted to use
<Menu renderer={Popover} rendererProps={{ placement: 'top' }} >
but this only minimally helped. Here is a screenshot. any help is appreciated.
EDIT: I have now used the custom menu as shown at https://github.com/instea/react-native-popup-menu/blob/master/doc/extensions.md.
This moves the options menu to the correct position but loses all styling and has no animation as well as never disapearing.
const CustomMenu = (props) => {
const { style, children, layouts, ...other } = props;
const position = { top: 0, right: 0 }
return (
<View name={'newquote2'} {...other} style={[style, position]}>
{children}
</View>
);
};

You need to use the libraries menu component with your own custom menu. for example
<Menu renderer={CustomMenu} >

Related

How can I display 30 pages of text in a (scrolling) screen

I want to display 30 pages of text on a screen. I've tried ScrollView and FlatList but I get a white screen. Only when I try with ScrollView to display only 2 pages, works fine.
I do not want to use a WebView, because I would like to have all data in the app (no internet connection needed).
Here is what I've already tried:
With FlatList:
I have a text.js as a model, which I use to create a Text Object in an array, which I then use as data for the FlatList. For the renderItem function (of FlatList) I use a TextItem to display the text.
text.js
function Text(info) {
this.id = info.id;
this.text = info.text;
}
export default Text;
LongTextModule.js
import Text from '../../models/text';
export const LONGTEXT = [
new Text({
id:'text_1',
text:`.....longtext....`
})
]
TextItem.js
const TextItem = (props) => {
return (
<View style={styles.screen} >
<Text style={styles.textStyle}>{props.longText}</Text>
</View >
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
},
textStyle: {
justifyContent: 'flex-start',
alignItems: 'flex-start',
fontFamily: 'GFSNeohellenic-Regular',
fontSize: 20,
padding: 10,
}
});
TextDetailScreen.js
const TextDetailScreen = (props) => {
const renderText = data => {
return <TextItem longText={data.item.text} />
}
return <FlatList
data={LONGTEXT}
keyExtractor={(item, index) => item.id}
renderItem={renderText}
/>
};
I think it's needless to show the code with ScrollView, since ScrollView is only for a small list.
I even tried to render the longText like this in the screen.
Without the ScrollView I get the first portion, but with ScrollView a white screen.
const TextDetailScreen = (props) => {
return (
<ScrollView>
<Text> ...longText...</Text>
</ScrollView>
);
};
I'm sure there is a way to display a lot of pages of text on a screen?
But how?
Thank you :)
It seems not to be an unknown Issue, I've also read from time to time about this issue.
But not to use Webview, because you wan't to have all Data in your app - don't have to be an Argument against Webview. With WebView, you also can display Data from your App-Storage.
Example:
<WebView style={styles.myStyle} source={{html: `<p style="font-size:48px">${longtext}</p>`}} />

Only button text area is clickable

Clicking does not work for all parts of the button. Only the text area is clickable.
As a solution, I used contentStyle instead of style prop. But it changes only the color in the touching space of the button. I need to apply button click for the whole button and to change the color of the whole button when clicking on anywhere of the button.
Here is my code:
import * as React from "react";
import { Button } from "react-native-paper";
import styles from "./styles";
const Cbutton = ({ text, onPress }) => (
<Button style={styles.wrapper} mode="contained" onPress={onPress}>
{text}
</Button>
);
export default Cbutton;
This is my code for the stylesheet.
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
wrapper: {
flexDirection: 'row',
justifyContent:'center',
alignItems: 'center',
width: ( "96%" ),
},
});
I had this same problem, and thankfully the fix is super simple - just remove { alignItems: 'center' } from your Button's style prop 👍
When applied, it shrinks the Button's content container, and it's unnecessary anyways thanks to the Button's internal styling.
For height, I recommend setting { height: '100%' } in the contentStyle prop.
Not sure about customizing the onPress color, however. If you can't find a ready-made solution, I'd try rolling your own using react-native Pressable.
You must use TouchableHighlight to change on the active state.
As for as, the clickable area is concerned I think rn-paper button by default is proper. You must check the way you had exported the component.
The issue described by #os-hewawitharana just happen after you set the disabled to true and then set back to false.
Here is how to simulate the issue. In constructor the button is enabled, therefore you can tap all the button area, after disabling and reenabling his state you will only can tap in text area. There is nothing wrong with component and his export method.
constructor(props) {
super(props);
this.state = {
desativado: false
};
}
async componentDidMount() {
setTimeout(() => {
this.setState({ desativado: true });
}, 2000);
setTimeout(() => {
this.setState({ desativado: false });
}, 4000);
}
render(){
return (
<Button
label={'Entrar'}
color={'blue'}
onPress={async () => {
await this.setState({ desativado: true });
}}
disabled={this.state.desativado}
mode="contained"
ark={true} > <Text style={{ fontSize: 14 }}>Text</Text>
</Button>
);
For while the solution is use a version 3 alpha
npm i react-native-paper#3.0.0-alpha.3
Soon they will release a v3 stable release as they answer in my issue report in github: https://github.com/callstack/react-native-paper/issues/1297

Separator style for header and body in FlatList

Currently, I'm having a problem with FlatList.
I have a component to render a list book.
By design, the header's width is the width of the screen and the body will be padding left and right 10px.
So I used contentContainerStyle={{paddingHorizontal: 10}}.
But The result is that the header and body are 10px padding left and right.
Please suggest a way to resolve it. Sorry for my bad English!!
Update: I'm so sorry for not describing my problem thoroughly.
In main.tsx
...
public render() {
return (
<FlatList
key...
data={..}
renderItem={this.renderItems}
ListHeaderComponent={this.renderHeader}
contentContainerStyle={styles.contentStyle}
/>
);
}
private renderHeader = () => {
return (
<View style={style.header}
//TODO something ...
</View>
);
}
private renderItems: ListRenderItem<IBook> = ({ item: {bookId} }) => bookId ?
(
<BookGridCell
title={...}
image={...}
//TODO more..
/>
) : <View style={styles.emptyBox} />
}
At renderItems, I called a component BookGridCell. In this component, the design of a book is set up. So if I directly add style inside renderItems, each book will have a left and right margin of 10px, not the entire body.
When use contentContainerStyle
with contenContainerStyle
When directly add style inside renderItems
with not use contentContainerStyle
Give a style to your body.
style={styles.bodyContainer}
and then inside StyleSheet add property.
const styles = StyleSheet.create({
bodyContainer: {
paddingHorizontal: 10
},
This is the correct way or
you can directly add padding inside your View.
style={{ paddingHorizontal: 10 }}

The best way to create a scrollable tab in the middle of the screen?

The mobile app of Twitter has a scrollable tab in the middle of the screen when you are on your profile. The top half of the screen displaying your profile info etc doesn't change when you click on the scrollable tabs mid screen : "Tweets & replies", "Media" etc. I am wondering how one would create this? Having half the screen stay the same and then having tabs which change mid screen... At the moment I have react navigation tabs as my main navigation - so on one of these tabs (the profile tab) I want to create the same concept as the picture..
Late answer but (for anyone else and future reference), react-navigation uses this package, react-native-tab-view: https://github.com/react-native-community/react-native-tab-view
for their tabs.
You can nest this within a screen, just like you desire (the previous answer only addresses the navigator inside navigator and that isn't what you want).
Here is an example (not exactly like you want, but you get the idea that you can. so instead of a background image, swap it out and use a view or scrollview accordingly to create that layout):
https://snack.expo.io/#satya164/collapsible-header-with-tabview
cheers :)
EDIT: i just found a way with just using react-navigation after all:
https://snack.expo.io/#mattx/collapsible-header-tabs
check it out
and another library: https://github.com/benevbright/react-navigation-collapsible
I don't know if you've figured it out yet, but you can nest the TabNavigator inside a StackNavigator. That way, you can have a scrollable Tab.
class ProfileMenu extends React.Component{
render() {
return(
//whatever you wanted at the top
)
}
}
const TabNaviga = createMaterialTopTabNavigator({
Tweets: {screen: TweetScreen,},
Replies: {screen: RepliesScreen,},
})
const YNavigator = createStackNavigator ({
Home:{screen: TabNaviga,
navigationOptions: ({navigation}) => ({
header: <ProfileMenu navigation= {navigation} />,
})
}
})
export default YNavigator
I found this tutorial and followed it,
EDIT: it seems there's a new library out that supports it https://github.com/PedroBern/react-native-collapsible-tab-view
https://medium.com/#linjunghsuan/implementing-a-collapsible-header-with-react-native-tab-view-24f15a685e07
I also wrote a bit of an explaination if you are interested.
create a ScrollY with useRef and .current at the end
create a handleScroll function which returns an event like so -
const handleScroll = Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
{ useNativeDriver: true }
);
Pass it down in props to the wanted component
<TabNavigator handleScroll={handleScroll} scrollY={scrollY} />
And also the scrollY so you can use the value in the Child component aswell
pass it farther down the line to actual events like and call handleScroll in the Child Child component onScroll prop. like so
<Animated.FlatList
...
onScroll={handleScroll}
/>
And now you can use the ScrollY value wherever you want.
what it does is checking if the current route is the one we check, it then caluclates the offset and scrollToOffset function of flatlist using the flatlist refs we got from here
return (
<Pictures
handleScroll={handleScroll}
onMomentumScrollBegin={onMomentumScrollBegin}
onScrollEndDrag={onScrollEndDrag}
onMomentumScrollEnd={onMomentumScrollEnd}
onGetRef={ref => {
if (ref) {
const found = listRefArr.current.find(e => e.key === route.key);
if (!found) {
listRefArr.current.push({ key: route.key, value: ref });
}
}
}}
/>
);
the onGetRef is connected to the FlatList ref
return (
<AnimatedFlatList
ref={onGetRef}
scrollToOverflowEnabled
onMomentumScrollBegin={onMomentumScrollBegin}
onScrollEndDrag={onScrollEndDrag}
onMomentumScrollEnd={onMomentumScrollEnd}
onScroll={handleScroll}
scrollEventThrottle={16}
contentContainerStyle={{
paddingTop: HeaderHeight + TabBarHeight,
paddingHorizontal: 10,
minHeight: windowHeight - TabBarHeight
}}
data={data}
renderItem={({ item }) => {
return <Comment data={item} />;
}}
keyExtractor={({ commentId }): any => {
return commentId.toString();
}}
/>
);
then we have these three functions which we send the flatlist as well
const onMomentumScrollBegin = () => {
isListGliding.current = true;
};
const onMomentumScrollEnd = () => {
isListGliding.current = false;
syncScrollOffset();
};
const onScrollEndDrag = () => {
syncScrollOffset();
};
and last but not least we still need to animate the TabBar so when the header is 500 height his is 0 when the header is 450 in the y the tabbar should be 50, we do that by getting the scrollY in the props and use it to interpolate.
const renderTabBar = (props: any) => {
return (
<Animated.View
style={{
top: 0,
zIndex: 1,
position: "absolute",
transform: [{ translateY: tabViewHeight }],
width: "100%"
}}
>
<TabBar ... />
</Animated.View>
);
};

Want to change opacity with react native refs on click

Here is my code. I want to change the opacity of refs when i click on any TouchableOpacity component.Please guide me how i can change opacity or change colour in react native with refs.
When i click my redirect function calls so i wanna change the opacity of particular ref in redirect function, i am passing ref and routename is redirect function.
i
mport React, { Component } from 'react';
import {
View,
Text,
TouchableOpacity,
StyleSheet
} from 'react-native';
export default class Navigation extends Component {
redirect(routeName,ref)
{
console.log(this.refs[ref]]);
this.props.navigator.push({
ident: routeName
});
}
render() {
return (
<View style={style.navigation}>
<View style={[style.navBar,styles.greenBack]}>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"AddItem","a")} ref="a">
<Text style={[style.navText,style.activeNav]}>HOME</Text></TouchableOpacity>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"AddItem","b")} ref="b">
<Text style={style.navText}>ORDER</Text></TouchableOpacity>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"ListItem","c")} ref="c">
<Text style={style.navText}>SHOP LIST</Text></TouchableOpacity>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"ListItem","d")} ref="d">
<Text style={style.navText}>DUES</Text></TouchableOpacity>
</View>
<View style={style.titleBar}>
<Text style={style.titleBarText}>{this.props.title}</Text>
</View>
</View>
);
}
}
const style = StyleSheet.create({
navigation:{
top:0,
right:0,
left:0,
position:'absolute'
},
navBar:{
flexDirection:'row',
padding:10,
paddingTop:15,
paddingBottom:15,
},
navPills:{
flex:1,
alignItems:'center'
},
navText:{
flex:1,
textAlign:'center',
fontSize:16,
fontWeight:'bold',
color:'#ffffff',
opacity:0.7
},
titleBar:{
backgroundColor:'#ffffff',
flex:1,
padding:8,
alignItems:'center',
borderBottomWidth:1,
borderBottomColor:'#dddddd'
},
titleBarText:{
fontSize:18
},
activeNav:{
opacity:1
}
});
I am not exactly sure if the following is what u are searching:
If you want to change the opacity of the TouchableOpacity use the following
export default class Navigation extends Component {
state={
opacity: 0.1
}
handleOnPress = () => {
this.setState({
opacity: 0.5 //Anything u want
});
}
render(){
return(
<TouchableOpacity underlayColor={'rgba(0,0,0,this.state.opacity)'} onPress={this.handleOnPress}>
)
}
}
If you want to change the opacity of your text use the following
export default class Navigation extends Component {
state = {
opacity: 0.1
}
handleOnPress = () => {
this.setState({
opacity: 0.5 //Anything u want
});
}
render(){
return(
<TouchableOpacity onPress={this.handleOnPress}>
<Text style={[style.navText, {opacity: this.state.opacity}]}>DUES</Text>
</TouchableOpacity>
)
}
}
Using the Stylemethods in the render allows you to take variables from the state
Hope this is the answer you wanted. If One of both is the right let me know and i delete the other one.
Best Regards
Put your opacity value into state. Then make the button click change the value of that state. This will trigger a re-render and your view will update with the new opacity.
To expand on the answer from pomo...
With the styles as you currently have them, you can easily call setState within each of your onPress functions to change the opacity of the elements you need changed. You don't even need to pass a reference if you utilize a different key in the state for each item.
Then, in your styles you would use an array of styles to use the opacity value from the state.
style={[style.navPills, { opacity: this.state.opacityA }]}
I'm not a fan of inline styles at all. So, for my purposes in a recent project I set the style of an element using its 'ref' value, then triggered a state change merely to cause the render function to be called. This is what I believe you're asking for and this sample code should point you in the right direction, otherwise perhaps this will help someone else in the future.
toggleDisplay() {
if (this.refs.blah.style.display === "") { // currently visible
this.refs.blah.style.display = "none";
this.setState({showBlah = false});
} else { // currently not visible
this.refs.blah.style.display = "";
this.setState({showBlah: true});
}
}
render() {
// Some element defined with the ref value used above.
return (<div>
<div ref="blah">Now you see me...</div>
<button onClick="this.toggleDisplay">Toggle Me</button>
</div>);
}
Nothing in my render function changed by adding the toggle functionality, other than adding a button somewhere to call the function. As I already indicated, that state value is only used to trigger the render process.