Fix ScrollView on small scroll, React Native - react-native

I have a ScrollView and I want it to scroll only to top and bottom, I have done it depending on it's position when onTouchEnd happens. But I need to scroll to certain point where it scrolls to bottom or top. Can I do the same when I do small and sharp scroll?
here's my code
const [scrollToTop, setScrollToTop] = useState(false)
const scrollViewRef = useRef()
const handleGestureEvent = (e) => {
if (e?.nativeEvent?.contentOffset?.y > 120) {
setScrollToTop(false)
} else {
setScrollToTop(true)
}
}
const fixScrollView = () => {
if (scrollViewRef && scrollViewRef.current) {
if (scrollToTop) {
scrollViewRef.current.scrollTo({y: 0, animated: true})
} else {
scrollViewRef.current.scrollToEnd({animated: true})
}
}
}
<ScrollView
ref={scrollViewRef}
onScroll={handleGestureEvent}
onTouchEnd={fixScrollView}></ScrollView>
But now I need to scroll to certain point on the screen where it scrolls to top or bottom. I don't know, is there a way to determine small and sharp scroll so that the list would scroll to bottom or top when it occurs

You can run the "scrollTo" method of the ScrollView. Check out the source.
You can get reference the ScrollView component by setting ref property and using this.refs as described here: https://facebook.github.io/react/docs/more-about-refs.html

Related

how to count views in react native flatlist items

I have a flat list and it contains a list of posts and videos, now I need to count the views for each item, I tried using viewabilityConfig and onViewableItemsChanged in the flat list and it works fine if I only want to count visible item as a view.
problem is that I had a function written inside onViewableItemsChanged for pausing video right after user scrolls from video.
now I have two functions with different execution times. how can I handle these two functions ?
onViewableItemsChanged = (info) => {
if (this.props.enableView) {
console.log('item viewed after minimumViewavlitytime 5s: ', info) //done after 5s of view time
}
this.pauseVideoFunction(); //done exactly after scrolling
};
viewabilityConfig = {
minimumViewTime:5000,
waitForInteraction: false,
viewAreaCoveragePercentThreshold: 95,
}
i handled it this way:
removed minimumViewTime from config file
added this to constructor since its a class component
this.debouncedViewCount = debounce(this.countView, 5000);*
called debouncedViewCount inside onViewableItemsChanged
now I have a denounced view counter which runs after 5 second if scroll doesn't move and can pause video right after scrolling
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.debouncedViewCount = debounce(this.countView, 5000); //aaaaaaaaaaa
}
countView = (info) => {
debounce(console.log('Debouced 5s', info), 5000, false)
}
onVideoExitScreen = (info) => { //todo working on view aaaaaaaaaaaaaaaaaaaa
if (this.props.enableView) {
this.debouncedViewCount(info);
}
pauseVideoFunction();
};
}
//inside Flatlist
onViewableItemsChanged={this.onViewableItemsChanged}

React Native : How can I get gestures onTouchStart, onTouchEnd and onTouchMove event positions ( like X and Y Coordinations) in Android

How would I get the coordinates of my onTouchEnd event. So I touch or move figure anywhere within the display and I can retrieve the X, Y positioning of where it happened. onResponderRelease is not triggered in a onTouchEnd on Android,
I've included example implementations for all of the gesture response event handlers, but have commented out most of them on my View to just provide the basic functionality: subscribing to all touch and move events
pseudo code would look like this :
<View
style={this.props.style}
ref={this._saveRef}
onStartShouldSetResponder={(event) => {
return this.handleDoubleTap({nativeEvent:
event.nativeEvent});
}}
onResponderGrant={this._onTouchStart}
onResponderMove={this._onTouchMove}
onResponderRelease={this._onTouchEnd}
onResponderTerminate={this._onTouchEnd} // When
onResponderRelease can't call by some reason
>
{this.props.children}
</View>
Responder Event Handler Methods :
if (this.isDoubleTap) {
return false;
}
this.context.setScroll && this.context.setScroll(false);
const currentTouchTimeStamp = Date.now();
this._prevTouchInfo = {
prevTouchX: nativeEvent.pageX,
prevTouchY: nativeEvent.pageY,
prevTouchTimeStamp: currentTouchTimeStamp
};
this.props.onStart(nativeEvent);
};
_onTouchMove = ({nativeEvent}) => {
if (nativeEvent.touches.length <= 1) {
if (this.isDoubleTap) {
return false;
}
const self = this;
const gesture = {
x0: this._prevTouchInfo.prevTouchX,
x1: nativeEvent.pageX,
y0: this._prevTouchInfo.prevTouchY,
y1: nativeEvent.pageY,
dx: nativeEvent.pageX - this._prevTouchInfo.prevTouchX,
dy: nativeEvent.pageY - this._prevTouchInfo.prevTouchY
};
InteractionManager.runAfterInteractions(function () {
self.props.onMove(nativeEvent, gesture);
});
}
};
_onTouchEnd = ({nativeEvent}) => {
nativeEvent.touches.length === 0 && this.context.setScroll && this.context.setScroll(true);
this.props.onEnd(nativeEvent);
};
}
I am Developing an Application in React native.Actually when i am touch on Particular Position On view, getting the Corresponding x and y co-ordinates. App UI would look like this:
If this is still not enough functionality for android (eg. if you need multi-touch info), refer to PanResponde

React Native - SectionList scroll to end when list is loaded first time

I am working on a chat application.
I am using SectionList to render messages.
I want to scroll to bottom when list loaded.
All messages are of dynamic size so there is no possibility to use getItemLayout.
If I call scrollToLocation immediately, SectionList throws error that scrollToLocation should be used in conjunction with getItemLayout.
How can I achieve this?
loadNextPage() {
var dataSource = this.message_list.load_next_page()
this.setState({ data : dataSource,
isLoading:false,
isPullToRefreshing:false})
}
onMessagesReceived() {
this.loadNextPage()
this.scrollToEnd()
}
scrollToEnd(animated) {
var length = this.state.data.length
if(length > 0) {
setTimeout(()=> {
this.refs.chatList.scrollToLocation({animated:animated,
sectionIndex:length-1,
itemIndex:this.state.
data[length-1].data.length-1,
viewPosition:1})
}, 10)
}
}

How detect tablet landscape on React Native

I want to border margin of of screen S on phone and tablet to be different. There are variants for tablet landscape and portrait mode.
How to create different margin dimension for the variants on phone, tablet portrait, tablet landscape ?
For those curious how to do on Android , we just create some resource files at the right folder :
values for default
values-sw600dp for tablet default
values-sw600dp-land for tablet landscape
The other answers have already addressed the screen detection task. However, there is still the issue of detecting if the code is running on a Tablet device. You can detect that using the react-native-device-info package, in particular its isTablet method. So, as an example, in your component:
constructor(){
super();
this.state = {orientation: 'UNKNOWN'}
this._onOrientationChanged = this._onOrientationChanged.bind(this);
}
_onOrientationChanged(orientation){
this._setState({orientation})
}
componentDidMount(){
Orientation.addOrientationListener(this._onOrientationChanged);
}
componentWillUnmount(){
Orientation.removeOrientationListener(this._orientationDidChange);
}
render(){
let layoutStyles;
if(DeviceInfo.isTablet()){
layoutStyles = this.state.orientation == 'LANDSCAPE' ? landscapeTabletStyle : portraitTabletLandscape; // Basic example, this might get more complex if you account for UNKNOWN or PORTRAITUPSIDEDOWN
}else{
layoutStyles = this.state.orientation == 'LANDSCAPE' ? landscapeStyle : portraitLandscape;
}
render(){
<View style={[styles.container, layoutStyles]} // And so on...
}
}
Note that the state holds the UNKNOWN value on the beginning. Have a look at the getInitialOrientation() of the package function. I am intentionally leaving that bit out because it simply reads a property that is set when the JS code loads, and I am not sure if that satisfies your usecase (i.e. this is not your first screen). What I usually like to do is store the rotation value in a redux store (where I initialize the orientation value to that of getInitialOrientation() and then subscribe only once to the orientation listener).
I think this library will be helpful for you: https://github.com/yamill/react-native-orientation
You can do something like that with it:
Orientation.getOrientation((err,orientation)=> {
console.log("Current Device Orientation: ", orientation);
if(orientation === 'LANDSCAPE') {
//do stuff
} else {
//do other stuff
}
});
// Extract from the root element in our app's index.js
class App extends Component {
_onLayout = event => this.props.appLayout(event.nativeEvent.layout);
render() {
return (
<View onLayout={this._onLayout}>
{/* Subviews... */}
</View>
);
}
}
export const SET_ORIENTATION = 'deviceStatus/SET_ORIENTATION';
export function appLayout(event: {width:number, height:number}):StoreAction {
const { width, height } = event;
const orientation = (width > height) ? 'LANDSCAPE' : 'PORTRAIT';
return { type: SET_ORIENTATION, payload: orientation };
}
Code Copied from Here

move the view up when keyboard as shown in react-native

hai i am trying to move the view up when keyboard as shown using react-native,I followed the #sherlock's comment in (How to auto-slide the window out from behind keyboard when TextInput has focus? i got an error like this
I don't know how to resolve this error, can any one help me how to resolve this, any help much appreciated.
There's a great discussion about this in the react-native github issues
https://github.com/facebook/react-native/issues/3195#issuecomment-147427391
I'd start there, but here are a couple more links you may find useful, one of which is mentioned already in the article you referenced...
[React Tips] Responding to the keyboard with React Native
Andr3wHur5t/react-native-keyboard-spacer
In my library "react-native-form-generator" (https://github.com/MichaelCereda/react-native-form-generator) i did the following.
I created a Keyboard Aware scroll view (partially modified from https://github.com/facebook/react-native/issues/3195#issuecomment-146518331)
the following it's just an excerpt
export class KeyboardAwareScrollView extends React.Component {
constructor (props) {
super(props)
this.state = {
keyboardSpace: 0,
}
this.updateKeyboardSpace = this.updateKeyboardSpace.bind(this)
this.resetKeyboardSpace = this.resetKeyboardSpace.bind(this)
}
updateKeyboardSpace (frames) {
let coordinatesHeight = frames.endCoordinates.height;
const keyboardSpace = (this.props.viewIsInsideTabBar) ? coordinatesHeight - 49 : coordinatesHeight
this.setState({
keyboardSpace: keyboardSpace,
})
}
resetKeyboardSpace () {
this.setState({
keyboardSpace: 0,
})
}
componentDidMount () {
// Keyboard events
DeviceEventEmitter.addListener('keyboardWillShow', this.updateKeyboardSpace)
DeviceEventEmitter.addListener('keyboardWillHide', this.resetKeyboardSpace)
}
componentWillUnmount () {
DeviceEventEmitter.removeAllListeners('keyboardWillShow')
DeviceEventEmitter.removeAllListeners('keyboardWillHide')
}
scrollToFocusedInput (event, reactNode, extraHeight = 69) {
const scrollView = this.refs.keyboardScrollView.getScrollResponder();
setTimeout(() => {
scrollView.scrollResponderScrollNativeHandleToKeyboard(
reactNode, extraHeight, true
)
}, 220)
}
render () {
return (
<ScrollView
ref='keyboardScrollView'
keyboardDismissMode='interactive'
contentInset={{bottom: this.state.keyboardSpace}}
showsVerticalScrollIndicator={true}
style={this.props.style}>
{this.props.children}
</ScrollView>
)
}
Then i use it like any other scrollview
import { KeyboardAwareScrollView } from 'react-native-form-generator'
...
handleFormFocus(event, reactNode){
this.refs.scroll.scrollToFocusedInput(event, reactNode)
}
...
<KeyboardAwareScrollView ref='scroll'>
<Form ref='registrationForm'
onFocus={this.handleFormFocus.bind(this)}
onChange={this.handleFormChange.bind(this)}
label="Personal Information">
........
</Form>
</KeyboardAwareScrollView>
on change my component (Form) will call scrollToFocusedInput in KeyboardAwareScrollView (using the ref).
i suggest to check the code of my library (see the link on top), or simply use it (everything it's already tested and working).
If you have further questions just comment