I have a navigator structure like so:
stack
drawer
stack
tab
My hierarchy from there is:
view
view
flatlist
I'm trying to get my flatlist to scroll downward. You can see the finger animation but the list isn't moving. You can see it in this gif:
Screen Recording 2018-03-16 at 11.30 p.m..gif
Here's my code:
it('should have infinite scrolling', async () => {
await expect(element(by.id('NewsFeed.Scroller'))).toBeVisible();
await expect(element(by.id('NewsFeedScreen.ArticleListing-0'))).toExist();
await expect(element(by.id('NewsFeedScreen.ArticleListing-10'))).toNotExist();
await element(by.id('NewsFeed.Scroller')).scroll(10000, 'down');
await expect(element(by.id('NewsFeedScreen.ArticleListing-10'))).toExist();
});
I believe the issue is that scroll action begins at the bottom of my screen. When I attempt to start a scroll form there myself it does not work either. I'm not seeing anything in the API to allow me to put an offset on where that gesture begins. Looking that element in the inspect reveals that its not in the area which Detox begins its gesture: https://d3vv6lp55qjaqc.cloudfront.net/items/323C3D3U3y1Y2Z1B2L2J/Screen%20Shot%202018-03-16%20at%2023.47.48.png?X-CloudApp-Visitor-Id=2852073&v=31521c3c
I've found a solution which is good enough while we wait for https://github.com/wix/detox/issues/589 to be resolved.
await element(by.id('NewsFeedScreen.ArticleListing-0')).swipe('up', 'fast', 0.9);
https://github.com/wix/detox/blob/master/docs/APIRef.ActionsOnElement.md#swipedirection-speed-percentage
Results in the behaviour I'm looking for, scrolling down in my list
If anyone faces this issue now -- try using the startPositionX or startPositionY parameters of the .scroll() method, e.g:
await element(by.id('scrollView')).scroll(200, 'down', NaN, 0.5)
Worked like a charm for me, when I faced the same problem.
https://github.com/wix/Detox/blob/master/docs/APIRef.ActionsOnElement.md#scrolloffset-direction-startpositionx-startpositiony
Related
I am trying to do a test with detox where a I tap a button, a modal shows and then I interact with the modal in certain way (not important for my question).
The issue that I'm having is that when I tap the button the modal shows, but the test gets stuck for some reason, so I cannot do anything else from that point on.
it('My test', async function () {
const buttonToOpenModal = element(by.id(buttonTestId));
try {
console.log('ABOUT TO TAP ELEMENT');
await buttonToOpenModal.tap();
console.log('ELEMENT TAPPED');
} catch (error) {
console.error(error);
}
}
});
In the code above, I can see ABOUT TO TAP ELEMENT log, but then I do not see the ELEMENT TAPPED nor the console error printed. After four minutes the test just times out.
I saw there is already a question on this page, but it does not have an accepted answer; the person who asked just changed the library, but that is not an option for me. There are also a couple of issues about this on detox repo but they have been discarded for some reason. I also saw another answer here where they talk about wrapping the content of modal in a View and putting the testID there; even though I didn't think this applied to me because I'm not even trying to interact with the modal right now, I tried it anyways, and it didn't work either.
Do you know a solution or at least a workaround for this?
i would like to know if there is any way to stop scroll event on iOs and Android
Steps to reproduce
scroll FlatList / ScrollView
click any button
already tried "onScroll" but when i set scroll ref.scrollTo it will scroll when stroll stops
Example GIF:
This is just an idea which I think might work, you may have to test it yourself.
Assuming you have the following state, controlling the modal.
const [open, setOpen] = useState(false);
You can probably add a onScroll event to Flatlist (onScroll is inherited from ScrollView), then
const onScroll = (e) => {
if (open) e.preventDefault();
}
If there is a delay before e.preventDefault is called, since setting state is async, you may want to use useRef() instead of useState() for checking if (open) since scroll happens quickly.
Another idea is to probably use a listener for the flat list, to listen to scroll, using same logic above.
I did some changes in my second screen and comeback to my first screen the data is not updated. After reloading app the data is updated. How to update the data from second screen to first screen navigation without refresh or reload
What i believe without any code is that if you do navigation.goBack() or navigation.navigate() it doesnt call the api if its in your componentDidMount, what you can try is adding an eventlistener called onFocus so that whenever screen is focused you call that :
like this in your componentDidMount
componentDidMount(){
this.focusListener = this.props.navigation.addListener('didFocus', () => {
// The screen is focused
// Calling action to reset current day index to 1
this.getItineryData();
});
}
Hope it helps
i am getting struggling with this issue that how to stop the navigation bar pop swiping, if possible can any one give me suggestions that how to resolve it
as shown in the above image, when i was in the Property page,when i swipe from that page it goes to the previous page, this is at the time of swipe, it shows that when i swipe from Property it goes to results screen.I wanted to stop it, any help much appreciated
You can prevent all gestures by adding this to your Navigator
configureScene={(route) => ({
...Navigator.SceneConfigs.HorizontalSwipeJump,
gestures: false
})}
you can also disable this per route by adding this when you push the route
sceneConfig: {
...Navigator.SceneConfigs.HorizontalSwipeJump,
gestures: {} //or null
}
I am new to react native and new to iOS (not programming) so please excuse me if this question is a simple one. I am trying to navigate from one view to another (with a transition), however they are not related so I do not need the back navigation. I actually do not have a navigation bar at all. When using the Navigator component it seems to not support this at all. I am not sure if there is a separate way to do this but I am not able to figure it out without implementing my own hack.
If I use the navigator component and keep pushing on the views then it just keeps them all in memory and I do not want that. I can transition from one view to another and then pop but I may end up going to the wrong view in that case. I can also replace the view but it seems that does not allow for transitions.
To give you a scenario think of it like this:
Application starts and loads a "Loading" screen.
When initial loading is complete it will then go to the "Login" screen.
There is a button on the "Login" screen to "Register" or "Retrieve Password".
If they click "Register" it will take them there with a button back to "Login".
If they click "Retrieve Password" it will take them to a page with buttons to go back to "Login" or "Register".
So by this example you can see that there is no way to pop because if you were on the login screen and went to the register screen and then wanted to go the retrieve password screen then pop just simply wouldn't work. I do not want any navigation controls on the screen I just want to be able to do a smooth transition between these screens.
Now I was able to find a way to do this but I had to add a method to the Navigator class and hack code in using some of there core methods which seems like its not a good idea at all but here is the code (note this is really just a hack to see if it would work):
Navigator.prototype.pushWithUnmount = function(route) {
var activeLength = this.state.presentedIndex + 1;
var activeStack = this.state.routeStack.slice(0, activeLength);
var activeAnimationConfigStack = this.state.sceneConfigStack.slice(0, activeLength);
var nextStack = activeStack.concat([route]);
var destIndex = nextStack.length - 1;
var nextAnimationConfigStack = activeAnimationConfigStack.concat([
this.props.configureScene(route),
]);
this._emitWillFocus(nextStack[destIndex]);
this.setState({
routeStack: nextStack,
sceneConfigStack: nextAnimationConfigStack,
}, () => {
this._enableScene(destIndex);
this._transitionTo(
destIndex,
null, // default velocity
null, // no spring jumping
() => {
this.replaceAtIndex(nextStack[destIndex], 0);
this.setState({
presentedIndex: 0,
});
}
);
});
}
By using the code provided above I am now able to do:
this.props.navigator.pushWithUnmount({ component: SomeComponent });
With this code the views are pushed onto the stack with a transition and the old views are unmounted when its finished.
Please tell me that I am doing something wrong and that there is a better way to do this?
The default router with React Native is pretty limited. I'd check out React Native Router Flux. We just switched to it a few weeks ago in our product and have really liked it. It does exactly what you want.