How to find x,y position of Component in React native - react-native

How do I find out the x,y position of where an element is positioned on the screen, I'm using React Native v0.14. I have tried the following but it says measure is not a function.
componentDidMount() {
setTimeout(this.measurePosition);
},
measurePosition() {
this.refs.q.measure((a, b, width, height, px,py ) => console.log(width))
},

Option1:
You can use the NativeMethodsMixin. Make sure you've added the mixin to your class
var NativeMethodsMixin = require('NativeMethodsMixin')
...
var MyComponent = React.createClass({
mixins: [NativeMethodsMixin]
...
componentDidMount: function(){
this.refs.element.measure((x,y,w,h,pX,pY) => console.log("dets"))
}
Option 2
You can use the onLayout property on Views. It is available on most components.
render:function(){
...
<View onLayout = {this.onLayout} />
...
},
onLayout:function(event){
console.log(event.nativeEvent.layout)
}
You will get the x,y, width and height

Can you use something like
1. get the browser DOM element using (ReactDOM.findDOMNode())
2. Use the elements getBoundingClientRect()
3. You have top, left, bottom and right coords
this may also be useful Retrieve the position (X,Y) of an HTML element

Related

Move Xposition of View from 0 to its origianl position in React Native

const valueX = useRef(new Animated.Value(0)).current
useEffect(() => {
Animated.timing( valueX , {
toValue : // How to get the original X position of the component here.
duration : 1000,
easing : Easing.linear
}).start()
}, [])
So, I have a component (i.e View) originally at some position on the screen. I wanted to have a slight animation there using react native animated API. What I want is to move X position of that view from 0 to its original position . How can it be done?
I guess you need the position of the element - set that as your state and then change it in the way you want. Check out this question to get the elements position.
React Native: Getting the position of an element

Is there a way to animate the increased size of a View when new children are added?

I’m currently using LayoutAnimation to animate a view when children are added. However, since LayoutAnimation causes everything to be animated, globally, and I can’t easily use built-in Animated library to fit my use-case, I’m wondering if react-native-reanimated is able to help.
Here's a snack of my current solution:
https://snack.expo.io/#insats/height-adapation
This is what the result of that looks like:
Is there a way to achieve the same thing without using LayoutAnimation? I've looked through all exampled in react-native-reanimated, and I've read through the docs but I'm still not sure if this is possible to do or how I should get started. I've thought about using Animated to move the item-wrapper out of the viewable area and "scroll" it upwards (using transform translateY) when items are added, but that would require fixed height, which I don't have.
I have 2 approaches that I can suggest out of my mind:
You can configure your LayoutAnimation only when your desired state changed. If you use hooks it would be too easy:
const [state,setState] = useState([]);
useEffect(()=>{
/*rest code*/
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
},[state])
Or if you use class component you can catch your desired state change in componentDidUpdate:
componentDidUpdate(prevProps,prevState){
if(prevState.items!==state.items){
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
}
}
You can use onLayout function of view:
addItem = () => {
this.setState({
items: [...this.state.items, {title:'An item',isNew:true}]
})
};
renderItems = () => {
return this.state.items.map((item, index) => {
let opacity = new Animated.Value(0);
return (
<Animated.View onLayout={({nativeEvent})=>{
if(this.state.item.isNew){
// here you got the height from nativeEvent.layout.height
// Then you have to store the height animate height and opacity to its precise value
// PS I used opacity:0 to calculate the height
}
}} key={index} style={[styles.item,{opacity}>
<Text>{item.title}</Text>
</View>
)
});
};
When it comes to react-native-reanimated I regard it as more faster version of react-native's Animated library. So either way you will have to calculate the height!

Is it possible to know how many lines of text are rendered by React Native when using numberOfLines prop?

The React Native numberOfLines prop is very useful but I want to programmatically adjust the height of my row between two numbers based on how many lines of text are actually rendered.
For example, I have a Text component of this form <Text numberOfLines={2} ellipsizeMode={'tail'}>{item.text}</Text>
If the text is longer than two lines, it defaults to two lines as desired. But when it is less than two lines, it just shows a single line, again as desired. I just want to know when the content is a single lien versus two lines. Is there any way of finding this out?
possible answer here
herehttps://stackoverflow.com/a/58632169/11816387
I want to provide a modern solution. There is now a onTextLayout event that includes an array of lines which can be determined what number of lines are being rendered. There's other details in the lines array like actual height and width of every line which can be further used to determine if the text is being truncated.
const NUM_OF_LINES = 5;
const SOME_LONG_TEXT_BLOCK = 'Lorem ipsum ...';
function SomeComponent () {
const [ showMore, setShowMore ] = useState(false);
const onTextLayout = useCallback(e =>
setShowMore(e.nativeEvent.lines.length > NUM_OF_LINES);
}, []);
return (
<Text numberOfLines={NUM_OF_LINES} onTextLayout={onTextLayout}>
{SOME_LONG_TEXT_BLOCK}
</Text>
);
}
In React Native, Text component has a props called onLayout
http://facebook.github.io/react-native/docs/text.html#onlayout
with {nativeEvent: {layout: {x, y, width, height}}}
So first, have a state
state = {
numOfLines: 0
}
Then in your Text component
<Text
numberOfLines={this.state.numOfLines}
onLayout={(e) => {
this.setState({ numOfLines: e.nativeEvent.layout.height > YOUR_FONT_SIZE ? 2 : 1 })
}
>
{item.text}
</Text>
I am not totally sure with this solution because I just think it from my mind straight away. But, my logic is if your text height is more than your text fontSize it means that it is more than one line?
Let me know if it is work or not
If you don't mind using an npm package react-native-text-size will solve your problem.
From their docs:
const size = await rnTextSize.measure({
text, // text to measure, can include symbols
width, // max-width of the "virtual" container
...fontSpecs, // RN font specification
})
"size" is not only the size, it has more info, one of which is lineCount, which is what you need.
Personally, I needed to send allowFontScaling: false in the fontSpecs, because we handle that internally.

How to implement, React Native Drag-n-Drop

I want to implement react-native drag-and-drop, to swap component on the drop. supposed there is five component on a screen once I drag it should highlight dropable element. and once it is dropped the component should be swap.
In order to implement drag an drop you need to use the pan responders. First you need to define where are you going to store the values when the object is moving, you can set a property on the state.
state = {
pan: new Animated.ValueXY(),
};
Then you will have to create the pan responders in componentWillMount for example:
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder : () => true,
onPanResponderMove : Animated.event([null,{ // <--- When moving
dx : this.state.pan.x,
dy : this.state.pan.y
}]),
onPanResponderRelease : (e, gesture) => {} // <--- callback when dropped
});
Finally you need to set the left and top to the animated element in the render method.
<Animated.View
{...this.panResponder.panHandlers}
style={[this.state.pan.getLayout(), styles.circle]}>
<Text style={styles.text}>Drag me!</Text>
</Animated.View>
The this.state.pan.getLayout() returns the top and left, you need this in order to move the element around.
In order to swap the elements you need to implement the onPanResponderRelease.
For more detailed steps you can take a look at this tutorial: https://moduscreate.com/blog/animated_drag_and_drop_with_react_native

React Native VirtualizedList get Scroll and scroll to position

So i am on RN 49.3,
I am looking for a way to get the scroll position or the index of the item visible on the virtualizedList!
PS: when i opened the source code of VirtualizedList.js which seems to have props.onScrollEndDrag & props.onScroll
We were using a different approach. It has changed a lot since, but I can help you with the initial approach. We added onScroll param to the list. We captured event.nativeEvent.contentOffset.y into the state or some variable inside spec. We used redux. When the user left the screen we saved this value inside a database. Second part was to load this value from the db in componentDidMount . You just put a ref into the list component and then call this.refs.myRef.scrollTo({ x: 0, y: loadedValue, animated: false });
Capture the scroll
render() {
return (
<VirtualizedList
ref='myRef'
onScroll={event => {
this.scroll = event.nativeEvent.contentOffset.y;
}}
...
/>
);}
Save on exit
componentWillUnmount() {
AsyncStorage.setItem(key, this.scroll);
}
Load after mounting
componentDidMount() {
AsyncStorage.getItem(key)
.then(y => {
this.refs.myRef.scrollTo({ x: 0, y, animated: false });
});
}
Best approach I think is to handle it inside redux and you connect this component with the list to the store. I mentioned saving into db because we do save the position for later use, this is only optional and depends on your requirements.
You may use the state as well, but then you need to handle the unnecessary updates